Update clang to r86025.
This commit is contained in:
parent
73490b8909
commit
51fb8b013e
@ -65,7 +65,7 @@ macro(add_clang_library name)
|
||||
set_target_properties(${name} PROPERTIES COMPILE_FLAGS ${cflag})
|
||||
endif(MSVC)
|
||||
install(TARGETS ${name}
|
||||
LIBRARY DESTINATION lib
|
||||
LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX}
|
||||
ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX})
|
||||
endmacro(add_clang_library)
|
||||
|
||||
@ -83,8 +83,12 @@ include_directories(
|
||||
${CMAKE_CURRENT_BINARY_DIR}/include
|
||||
)
|
||||
|
||||
install(DIRECTORY include
|
||||
DESTINATION .
|
||||
install(DIRECTORY include/
|
||||
DESTINATION include
|
||||
FILES_MATCHING
|
||||
PATTERN "*.def"
|
||||
PATTERN "*.h"
|
||||
PATTERN "*.td"
|
||||
PATTERN ".svn" EXCLUDE
|
||||
)
|
||||
|
||||
|
@ -49,6 +49,7 @@
|
||||
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 */; };
|
||||
1AF1B50F109A4FB800AFAFAC /* CGException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AF1B50E109A4FB800AFAFAC /* CGException.cpp */; };
|
||||
1AFEF4070F8A6B2300476F2B /* clang-cc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AFEF4050F8A6B2300476F2B /* clang-cc.cpp */; };
|
||||
1AFF8AE31012BFC900D248DA /* CGRecordLayoutBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AFF8AE11012BFC900D248DA /* CGRecordLayoutBuilder.cpp */; };
|
||||
3507E4C20E27FE2D00FB7B57 /* CheckObjCInstMethSignature.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3507E4C10E27FE2D00FB7B57 /* CheckObjCInstMethSignature.cpp */; };
|
||||
@ -399,6 +400,7 @@
|
||||
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; };
|
||||
1AE4EE3F103B8A0A00888A23 /* TargetABIInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = TargetABIInfo.cpp; path = lib/CodeGen/TargetABIInfo.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1AF1B50E109A4FB800AFAFAC /* CGException.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGException.cpp; path = lib/CodeGen/CGException.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1AFEF4050F8A6B2300476F2B /* clang-cc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = "clang-cc.cpp"; path = "tools/clang-cc/clang-cc.cpp"; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1AFF8AE11012BFC900D248DA /* CGRecordLayoutBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGRecordLayoutBuilder.cpp; path = lib/CodeGen/CGRecordLayoutBuilder.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1AFF8AE21012BFC900D248DA /* CGRecordLayoutBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = CGRecordLayoutBuilder.h; path = lib/CodeGen/CGRecordLayoutBuilder.h; sourceTree = "<group>"; tabWidth = 2; };
|
||||
@ -515,6 +517,13 @@
|
||||
9012911C1048068D0083456D /* ASTUnit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ASTUnit.cpp; path = lib/Frontend/ASTUnit.cpp; sourceTree = "<group>"; };
|
||||
9012911F104812F90083456D /* CIndex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CIndex.cpp; path = tools/CIndex/CIndex.cpp; sourceTree = "<group>"; };
|
||||
90129120104812F90083456D /* CIndex.exports */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = CIndex.exports; path = tools/CIndex/CIndex.exports; sourceTree = "<group>"; };
|
||||
904753791096376F00CBDDDD /* CXXInheritance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CXXInheritance.h; path = clang/AST/CXXInheritance.h; sourceTree = "<group>"; };
|
||||
9047537A1096376F00CBDDDD /* Redeclarable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Redeclarable.h; path = clang/AST/Redeclarable.h; sourceTree = "<group>"; };
|
||||
9047537B1096376F00CBDDDD /* TypeLoc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TypeLoc.h; path = clang/AST/TypeLoc.h; sourceTree = "<group>"; };
|
||||
9047537C1096376F00CBDDDD /* TypeLocBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TypeLocBuilder.h; path = clang/AST/TypeLocBuilder.h; sourceTree = "<group>"; };
|
||||
9047537D1096376F00CBDDDD /* TypeLocNodes.def */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = TypeLocNodes.def; path = clang/AST/TypeLocNodes.def; sourceTree = "<group>"; };
|
||||
9047537E1096376F00CBDDDD /* TypeLocVisitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TypeLocVisitor.h; path = clang/AST/TypeLocVisitor.h; sourceTree = "<group>"; };
|
||||
9047537F1096376F00CBDDDD /* TypeVisitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TypeVisitor.h; path = clang/AST/TypeVisitor.h; sourceTree = "<group>"; };
|
||||
9063F2210F9E8BDF002F7251 /* ExternalSemaSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ExternalSemaSource.h; path = clang/Sema/ExternalSemaSource.h; sourceTree = "<group>"; };
|
||||
9063F2220F9E8BDF002F7251 /* SemaConsumer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SemaConsumer.h; path = clang/Sema/SemaConsumer.h; sourceTree = "<group>"; };
|
||||
9063F2280F9E911F002F7251 /* OnDiskHashTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OnDiskHashTable.h; sourceTree = "<group>"; };
|
||||
@ -1257,6 +1266,7 @@
|
||||
35A3E7000DD3874400757F74 /* CGDebugInfo.cpp */,
|
||||
35A3E7010DD3874400757F74 /* CGDebugInfo.h */,
|
||||
DE4264FB0C113592005A861D /* CGDecl.cpp */,
|
||||
1AF1B50E109A4FB800AFAFAC /* CGException.cpp */,
|
||||
DE4772FB0C10EAEC002239E8 /* CGExpr.cpp */,
|
||||
DEF2EFF20C6CDD74000C4259 /* CGExprAgg.cpp */,
|
||||
DE224FF70C7AA98800D370A5 /* CGExprComplex.cpp */,
|
||||
@ -1298,6 +1308,13 @@
|
||||
DEC8D98B0A9433BC00353FCA /* AST */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
904753791096376F00CBDDDD /* CXXInheritance.h */,
|
||||
9047537A1096376F00CBDDDD /* Redeclarable.h */,
|
||||
9047537B1096376F00CBDDDD /* TypeLoc.h */,
|
||||
9047537C1096376F00CBDDDD /* TypeLocBuilder.h */,
|
||||
9047537D1096376F00CBDDDD /* TypeLocNodes.def */,
|
||||
9047537E1096376F00CBDDDD /* TypeLocVisitor.h */,
|
||||
9047537F1096376F00CBDDDD /* TypeVisitor.h */,
|
||||
DECB78540FA58F5500F5FBC7 /* AccessSpecifier.h */,
|
||||
DE613EF30E0E148D00B05B79 /* APValue.h */,
|
||||
DEC8D9A30A94346E00353FCA /* AST.h */,
|
||||
@ -1901,6 +1918,7 @@
|
||||
1A535ED9107BC45E000C3AE7 /* CXXInheritance.cpp in Sources */,
|
||||
1A6C01F7108128710072DEE4 /* CGRtti.cpp in Sources */,
|
||||
1A81AA19108144F40094E50B /* CGVtable.cpp in Sources */,
|
||||
1AF1B50F109A4FB800AFAFAC /* CGException.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -20,6 +20,7 @@ td {
|
||||
<ul>
|
||||
<li><a href="#intro">Introduction</a></li>
|
||||
<li><a href="#feature_check">Feature Checking Macros</a></li>
|
||||
<li><a href="#has_include">Include File Checking Macros</a></li>
|
||||
<li><a href="#builtinmacros">Builtin Macros</a></li>
|
||||
<li><a href="#vectors">Vectors and Extended Vectors</a></li>
|
||||
<li><a href="#blocks">Blocks</a></li>
|
||||
@ -112,6 +113,69 @@ can be used like this:</p>
|
||||
|
||||
<p>The feature tag is described along with the language feature below.</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h2 id="has_include">Include File Checking Macros</h2>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<p>Not all developments systems have the same include files.
|
||||
The <a href="#__has_include">__has_include</a> and
|
||||
<a href="#__has_include_next">__has_include_next</a> macros allow you to
|
||||
check for the existence of an include file before doing
|
||||
a possibly failing #include directive.</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h3 id="__has_include">__has_include</h3>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<p>This function-like macro takes a single file name string argument that
|
||||
is the name of an include file. It evaluates to 1 if the file can
|
||||
be found using the include paths, or 0 otherwise:</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
// Note the two possible file name string formats.
|
||||
#if __has_include("myinclude.h") && __has_include(<stdint.h>)
|
||||
# include "myinclude.h"
|
||||
#endif
|
||||
|
||||
// To avoid problem with non-clang compilers not having this macro.
|
||||
#if defined(__has_include) && __has_include("myinclude.h")
|
||||
# include "myinclude.h"
|
||||
#endif
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>To test for this feature, use #if defined(__has_include).</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h3 id="__has_include_next">__has_include_next</h3>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<p>This function-like macro takes a single file name string argument that
|
||||
is the name of an include file. It is like __has_include except that it
|
||||
looks for the second instance of the given file found in the include
|
||||
paths. It evaluates to 1 if the second instance of the file can
|
||||
be found using the include paths, or 0 otherwise:</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
// Note the two possible file name string formats.
|
||||
#if __has_include_next("myinclude.h") && __has_include_next(<stdint.h>)
|
||||
# include_next "myinclude.h"
|
||||
#endif
|
||||
|
||||
// To avoid problem with non-clang compilers not having this macro.
|
||||
#if defined(__has_include_next) && __has_include_next("myinclude.h")
|
||||
# include_next "myinclude.h"
|
||||
#endif
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>Note that __has_include_next, like the GNU extension
|
||||
#include_next directive, is intended for use in headers only,
|
||||
and will issue a warning if used in the top-level compilation
|
||||
file. A warning will also be issued if an absolute path
|
||||
is used in the file argument.</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h2 id="builtinmacros">Builtin Macros</h2>
|
||||
|
@ -424,6 +424,10 @@ Add the specified directory to the search path for framework include files.
|
||||
|
||||
Do not search the standard system directories for include files.
|
||||
|
||||
=item B<-nobuiltininc>
|
||||
|
||||
Do not search clang's builtin directory for include files.
|
||||
|
||||
=cut
|
||||
|
||||
## TODO, but do we really want people using this stuff?
|
||||
|
@ -16,10 +16,23 @@
|
||||
#ifndef CLANG_C_INDEX_H
|
||||
#define CLANG_C_INDEX_H
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* MSVC DLL import/export. */
|
||||
#ifdef _MSC_VER
|
||||
#ifdef _CINDEX_LIB_
|
||||
#define CINDEX_LINKAGE __declspec(dllexport)
|
||||
#else
|
||||
#define CINDEX_LINKAGE __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#define CINDEX_LINKAGE
|
||||
#endif
|
||||
|
||||
/*
|
||||
Clang indeX abstractions. The backing store for the following API's will be
|
||||
clangs AST file (currently based on PCH). AST files are created as follows:
|
||||
@ -33,6 +46,7 @@ typedef void *CXIndex; /* An indexing instance. */
|
||||
|
||||
typedef void *CXTranslationUnit; /* A translation unit instance. */
|
||||
|
||||
typedef void *CXFile; /* A source file */
|
||||
typedef void *CXDecl; /* A specific declaration within a translation unit. */
|
||||
typedef void *CXStmt; /* A specific statement within a function/method */
|
||||
|
||||
@ -138,22 +152,22 @@ typedef void *CXEntity;
|
||||
* -include-pch) allows 'excludeDeclsFromPCH' to remove redundant callbacks
|
||||
* (which gives the indexer the same performance benefit as the compiler).
|
||||
*/
|
||||
CXIndex clang_createIndex(int excludeDeclarationsFromPCH,
|
||||
CINDEX_LINKAGE CXIndex clang_createIndex(int excludeDeclarationsFromPCH,
|
||||
int displayDiagnostics);
|
||||
void clang_disposeIndex(CXIndex);
|
||||
CINDEX_LINKAGE void clang_disposeIndex(CXIndex);
|
||||
|
||||
const char *clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit);
|
||||
CINDEX_LINKAGE const char *clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit);
|
||||
|
||||
/*
|
||||
* \brief Create a translation unit from an AST file (-emit-ast).
|
||||
*/
|
||||
CXTranslationUnit clang_createTranslationUnit(
|
||||
CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnit(
|
||||
CXIndex, const char *ast_filename
|
||||
);
|
||||
/**
|
||||
* \brief Destroy the specified CXTranslationUnit object.
|
||||
*/
|
||||
void clang_disposeTranslationUnit(CXTranslationUnit);
|
||||
CINDEX_LINKAGE void clang_disposeTranslationUnit(CXTranslationUnit);
|
||||
|
||||
/**
|
||||
* \brief Return the CXTranslationUnit for a given source file and the provided
|
||||
@ -170,7 +184,7 @@ void clang_disposeTranslationUnit(CXTranslationUnit);
|
||||
* '-o <output file>' (both '-o' and '<output file>' are ignored)
|
||||
*
|
||||
*/
|
||||
CXTranslationUnit clang_createTranslationUnitFromSourceFile(
|
||||
CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnitFromSourceFile(
|
||||
CXIndex CIdx,
|
||||
const char *source_filename /* specify NULL if the source file is in clang_command_line_args */,
|
||||
int num_clang_command_line_args,
|
||||
@ -197,7 +211,7 @@ CXTranslationUnit clang_createTranslationUnitFromSourceFile(
|
||||
typedef void *CXClientData;
|
||||
typedef void (*CXTranslationUnitIterator)(CXTranslationUnit, CXCursor,
|
||||
CXClientData);
|
||||
void clang_loadTranslationUnit(CXTranslationUnit, CXTranslationUnitIterator,
|
||||
CINDEX_LINKAGE void clang_loadTranslationUnit(CXTranslationUnit, CXTranslationUnitIterator,
|
||||
CXClientData);
|
||||
|
||||
/*
|
||||
@ -227,23 +241,30 @@ void clang_loadTranslationUnit(CXTranslationUnit, CXTranslationUnitIterator,
|
||||
*/
|
||||
typedef void (*CXDeclIterator)(CXDecl, CXCursor, CXClientData);
|
||||
|
||||
void clang_loadDeclaration(CXDecl, CXDeclIterator, CXClientData);
|
||||
CINDEX_LINKAGE void clang_loadDeclaration(CXDecl, CXDeclIterator, CXClientData);
|
||||
|
||||
/*
|
||||
* CXFile Operations.
|
||||
*/
|
||||
CINDEX_LINKAGE const char *clang_getFileName(CXFile SFile);
|
||||
CINDEX_LINKAGE time_t clang_getFileTime(CXFile SFile);
|
||||
|
||||
/*
|
||||
* CXEntity Operations.
|
||||
*/
|
||||
const char *clang_getDeclarationName(CXEntity);
|
||||
const char *clang_getURI(CXEntity);
|
||||
CXEntity clang_getEntity(const char *URI);
|
||||
CINDEX_LINKAGE const char *clang_getDeclarationName(CXEntity);
|
||||
CINDEX_LINKAGE const char *clang_getURI(CXEntity);
|
||||
CINDEX_LINKAGE CXEntity clang_getEntity(const char *URI);
|
||||
/*
|
||||
* CXDecl Operations.
|
||||
*/
|
||||
CXCursor clang_getCursorFromDecl(CXDecl);
|
||||
CXEntity clang_getEntityFromDecl(CXDecl);
|
||||
const char *clang_getDeclSpelling(CXDecl);
|
||||
unsigned clang_getDeclLine(CXDecl);
|
||||
unsigned clang_getDeclColumn(CXDecl);
|
||||
const char *clang_getDeclSource(CXDecl);
|
||||
CINDEX_LINKAGE CXCursor clang_getCursorFromDecl(CXDecl);
|
||||
CINDEX_LINKAGE CXEntity clang_getEntityFromDecl(CXDecl);
|
||||
CINDEX_LINKAGE const char *clang_getDeclSpelling(CXDecl);
|
||||
CINDEX_LINKAGE unsigned clang_getDeclLine(CXDecl);
|
||||
CINDEX_LINKAGE unsigned clang_getDeclColumn(CXDecl);
|
||||
CINDEX_LINKAGE const char *clang_getDeclSource(CXDecl); /* deprecate */
|
||||
CINDEX_LINKAGE CXFile clang_getDeclSourceFile(CXDecl);
|
||||
|
||||
/*
|
||||
* CXCursor Operations.
|
||||
@ -252,38 +273,24 @@ const char *clang_getDeclSource(CXDecl);
|
||||
Usage: clang_getCursor() will translate a source/line/column position
|
||||
into an AST cursor (to derive semantic information from the source code).
|
||||
*/
|
||||
CXCursor clang_getCursor(CXTranslationUnit, const char *source_name,
|
||||
CINDEX_LINKAGE CXCursor clang_getCursor(CXTranslationUnit, const char *source_name,
|
||||
unsigned line, unsigned column);
|
||||
|
||||
/**
|
||||
Usage: clang_getCursorWithHint() provides the same functionality as
|
||||
clang_getCursor() except that it takes an option 'hint' argument.
|
||||
The 'hint' is a temporary CXLookupHint object (whose lifetime is managed by
|
||||
the caller) that should be initialized with clang_initCXLookupHint().
|
||||
CINDEX_LINKAGE enum CXCursorKind clang_getCursorKind(CXCursor);
|
||||
CINDEX_LINKAGE unsigned clang_isDeclaration(enum CXCursorKind);
|
||||
CINDEX_LINKAGE unsigned clang_isReference(enum CXCursorKind);
|
||||
CINDEX_LINKAGE unsigned clang_isDefinition(enum CXCursorKind);
|
||||
CINDEX_LINKAGE unsigned clang_isInvalid(enum CXCursorKind);
|
||||
|
||||
FIXME: Add a better comment once getCursorWithHint() has more functionality.
|
||||
*/
|
||||
typedef CXCursor CXLookupHint;
|
||||
CXCursor clang_getCursorWithHint(CXTranslationUnit, const char *source_name,
|
||||
unsigned line, unsigned column,
|
||||
CXLookupHint *hint);
|
||||
|
||||
void clang_initCXLookupHint(CXLookupHint *hint);
|
||||
|
||||
enum CXCursorKind clang_getCursorKind(CXCursor);
|
||||
unsigned clang_isDeclaration(enum CXCursorKind);
|
||||
unsigned clang_isReference(enum CXCursorKind);
|
||||
unsigned clang_isDefinition(enum CXCursorKind);
|
||||
unsigned clang_isInvalid(enum CXCursorKind);
|
||||
|
||||
unsigned clang_getCursorLine(CXCursor);
|
||||
unsigned clang_getCursorColumn(CXCursor);
|
||||
const char *clang_getCursorSource(CXCursor);
|
||||
const char *clang_getCursorSpelling(CXCursor);
|
||||
CINDEX_LINKAGE unsigned clang_getCursorLine(CXCursor);
|
||||
CINDEX_LINKAGE unsigned clang_getCursorColumn(CXCursor);
|
||||
CINDEX_LINKAGE const char *clang_getCursorSpelling(CXCursor);
|
||||
CINDEX_LINKAGE const char *clang_getCursorSource(CXCursor); /* deprecate */
|
||||
CINDEX_LINKAGE CXFile clang_getCursorSourceFile(CXCursor);
|
||||
|
||||
/* for debug/testing */
|
||||
const char *clang_getCursorKindSpelling(enum CXCursorKind Kind);
|
||||
void clang_getDefinitionSpellingAndExtent(CXCursor,
|
||||
CINDEX_LINKAGE const char *clang_getCursorKindSpelling(enum CXCursorKind Kind);
|
||||
CINDEX_LINKAGE void clang_getDefinitionSpellingAndExtent(CXCursor,
|
||||
const char **startBuf,
|
||||
const char **endBuf,
|
||||
unsigned *startLine,
|
||||
@ -296,7 +303,7 @@ void clang_getDefinitionSpellingAndExtent(CXCursor,
|
||||
* declaration.
|
||||
* If CXCursorKind == Cursor_Declaration, then this will return the declaration.
|
||||
*/
|
||||
CXDecl clang_getCursorDecl(CXCursor);
|
||||
CINDEX_LINKAGE CXDecl clang_getCursorDecl(CXCursor);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include "clang/Basic/IdentifierTable.h"
|
||||
#include "clang/Basic/LangOptions.h"
|
||||
#include "clang/Basic/OperatorKinds.h"
|
||||
#include "clang/AST/Attr.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/NestedNameSpecifier.h"
|
||||
@ -301,22 +302,22 @@ class ASTContext {
|
||||
const char *getCommentForDecl(const Decl *D);
|
||||
|
||||
// Builtin Types.
|
||||
QualType VoidTy;
|
||||
QualType BoolTy;
|
||||
QualType CharTy;
|
||||
QualType WCharTy; // [C++ 3.9.1p5], integer type in C99.
|
||||
QualType Char16Ty; // [C++0x 3.9.1p5], integer type in C99.
|
||||
QualType Char32Ty; // [C++0x 3.9.1p5], integer type in C99.
|
||||
QualType SignedCharTy, ShortTy, IntTy, LongTy, LongLongTy, Int128Ty;
|
||||
QualType UnsignedCharTy, UnsignedShortTy, UnsignedIntTy, UnsignedLongTy;
|
||||
QualType UnsignedLongLongTy, UnsignedInt128Ty;
|
||||
QualType FloatTy, DoubleTy, LongDoubleTy;
|
||||
QualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy;
|
||||
QualType VoidPtrTy, NullPtrTy;
|
||||
QualType OverloadTy;
|
||||
QualType DependentTy;
|
||||
QualType UndeducedAutoTy;
|
||||
QualType ObjCBuiltinIdTy, ObjCBuiltinClassTy;
|
||||
CanQualType VoidTy;
|
||||
CanQualType BoolTy;
|
||||
CanQualType CharTy;
|
||||
CanQualType WCharTy; // [C++ 3.9.1p5], integer type in C99.
|
||||
CanQualType Char16Ty; // [C++0x 3.9.1p5], integer type in C99.
|
||||
CanQualType Char32Ty; // [C++0x 3.9.1p5], integer type in C99.
|
||||
CanQualType SignedCharTy, ShortTy, IntTy, LongTy, LongLongTy, Int128Ty;
|
||||
CanQualType UnsignedCharTy, UnsignedShortTy, UnsignedIntTy, UnsignedLongTy;
|
||||
CanQualType UnsignedLongLongTy, UnsignedInt128Ty;
|
||||
CanQualType FloatTy, DoubleTy, LongDoubleTy;
|
||||
CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy;
|
||||
CanQualType VoidPtrTy, NullPtrTy;
|
||||
CanQualType OverloadTy;
|
||||
CanQualType DependentTy;
|
||||
CanQualType UndeducedAutoTy;
|
||||
CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy;
|
||||
|
||||
ASTContext(const LangOptions& LOpts, SourceManager &SM, TargetInfo &t,
|
||||
IdentifierTable &idents, SelectorTable &sels,
|
||||
@ -387,10 +388,16 @@ class ASTContext {
|
||||
/// getComplexType - Return the uniqued reference to the type for a complex
|
||||
/// number with the specified element type.
|
||||
QualType getComplexType(QualType T);
|
||||
CanQualType getComplexType(CanQualType T) {
|
||||
return CanQualType::CreateUnsafe(getComplexType((QualType) T));
|
||||
}
|
||||
|
||||
/// getPointerType - Return the uniqued reference to the type for a pointer to
|
||||
/// the specified type.
|
||||
QualType getPointerType(QualType T);
|
||||
CanQualType getPointerType(CanQualType T) {
|
||||
return CanQualType::CreateUnsafe(getPointerType((QualType) T));
|
||||
}
|
||||
|
||||
/// getBlockPointerType - Return the uniqued reference to the type for a block
|
||||
/// of the specified type.
|
||||
@ -525,6 +532,11 @@ class ASTContext {
|
||||
unsigned NumArgs,
|
||||
QualType Canon = QualType());
|
||||
|
||||
QualType getTemplateSpecializationType(TemplateName T,
|
||||
const TemplateArgumentLoc *Args,
|
||||
unsigned NumArgs,
|
||||
QualType Canon = QualType());
|
||||
|
||||
QualType getQualifiedNameType(NestedNameSpecifier *NNS,
|
||||
QualType NamedType);
|
||||
QualType getTypenameType(NestedNameSpecifier *NNS,
|
||||
@ -728,6 +740,8 @@ class ASTContext {
|
||||
|
||||
TemplateName getDependentTemplateName(NestedNameSpecifier *NNS,
|
||||
const IdentifierInfo *Name);
|
||||
TemplateName getDependentTemplateName(NestedNameSpecifier *NNS,
|
||||
OverloadedOperatorKind Operator);
|
||||
|
||||
enum GetBuiltinTypeError {
|
||||
GE_None, //< No error
|
||||
@ -739,7 +753,7 @@ class ASTContext {
|
||||
QualType GetBuiltinType(unsigned ID, GetBuiltinTypeError &Error);
|
||||
|
||||
private:
|
||||
QualType getFromTargetType(unsigned Type) const;
|
||||
CanQualType getFromTargetType(unsigned Type) const;
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Type Predicates.
|
||||
@ -826,6 +840,8 @@ class ASTContext {
|
||||
llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);
|
||||
unsigned CountSynthesizedIvars(const ObjCInterfaceDecl *OI);
|
||||
unsigned CountProtocolSynthesizedIvars(const ObjCProtocolDecl *PD);
|
||||
void CollectInheritedProtocols(const Decl *CDecl,
|
||||
llvm::SmallVectorImpl<ObjCProtocolDecl*> &Protocols);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Type Operators
|
||||
@ -1013,7 +1029,9 @@ class ASTContext {
|
||||
bool canAssignObjCInterfaces(const ObjCInterfaceType *LHS,
|
||||
const ObjCInterfaceType *RHS);
|
||||
bool areComparableObjCPointerTypes(QualType LHS, QualType RHS);
|
||||
|
||||
QualType areCommonBaseCompatible(const ObjCObjectPointerType *LHSOPT,
|
||||
const ObjCObjectPointerType *RHSOPT);
|
||||
|
||||
// Functions for calculating composite types
|
||||
QualType mergeTypes(QualType, QualType);
|
||||
QualType mergeFunctionTypes(QualType, QualType);
|
||||
@ -1085,12 +1103,18 @@ class ASTContext {
|
||||
/// should be calculated based on the type.
|
||||
DeclaratorInfo *CreateDeclaratorInfo(QualType T, unsigned Size = 0);
|
||||
|
||||
/// \brief Allocate a DeclaratorInfo where all locations have been
|
||||
/// initialized to a given location, which defaults to the empty
|
||||
/// location.
|
||||
DeclaratorInfo *
|
||||
getTrivialDeclaratorInfo(QualType T, SourceLocation Loc = SourceLocation());
|
||||
|
||||
private:
|
||||
ASTContext(const ASTContext&); // DO NOT IMPLEMENT
|
||||
void operator=(const ASTContext&); // DO NOT IMPLEMENT
|
||||
|
||||
void InitBuiltinTypes();
|
||||
void InitBuiltinType(QualType &R, BuiltinType::Kind K);
|
||||
void InitBuiltinType(CanQualType &R, BuiltinType::Kind K);
|
||||
|
||||
// Return the ObjC type encoding for a given type.
|
||||
void getObjCEncodingForTypeImpl(QualType t, std::string &S,
|
||||
@ -1103,6 +1127,18 @@ class ASTContext {
|
||||
const ASTRecordLayout &getObjCLayout(const ObjCInterfaceDecl *D,
|
||||
const ObjCImplementationDecl *Impl);
|
||||
};
|
||||
|
||||
/// @brief Utility function for constructing a nullary selector.
|
||||
static inline Selector GetNullarySelector(const char* name, ASTContext& Ctx) {
|
||||
IdentifierInfo* II = &Ctx.Idents.get(name);
|
||||
return Ctx.Selectors.getSelector(0, &II);
|
||||
}
|
||||
|
||||
/// @brief Utility function for constructing an unary selector.
|
||||
static inline Selector GetUnarySelector(const char* name, ASTContext& Ctx) {
|
||||
IdentifierInfo* II = &Ctx.Idents.get(name);
|
||||
return Ctx.Selectors.getSelector(1, &II);
|
||||
}
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
|
@ -64,15 +64,6 @@ class CanQual {
|
||||
CanQual(const CanQual<U>& Other,
|
||||
typename llvm::enable_if<llvm::is_base_of<T, U>, int>::type = 0);
|
||||
|
||||
/// \brief Implicit conversion to the underlying pointer.
|
||||
///
|
||||
/// Also provides the ability to use canonical types in a boolean context,
|
||||
/// e.g.,
|
||||
/// @code
|
||||
/// if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) { ... }
|
||||
/// @endcode
|
||||
operator const T*() const { return getTypePtr(); }
|
||||
|
||||
/// \brief Retrieve the underlying type pointer, which refers to a
|
||||
/// canonical type.
|
||||
T *getTypePtr() const { return cast_or_null<T>(Stored.getTypePtr()); }
|
||||
@ -80,6 +71,10 @@ class CanQual {
|
||||
/// \brief Implicit conversion to a qualified type.
|
||||
operator QualType() const { return Stored; }
|
||||
|
||||
bool isNull() const {
|
||||
return Stored.isNull();
|
||||
}
|
||||
|
||||
/// \brief Retrieve a canonical type pointer with a different static type,
|
||||
/// upcasting or downcasting as needed.
|
||||
///
|
||||
@ -125,8 +120,10 @@ class CanQual {
|
||||
/// \brief Retrieve the unqualified form of this type.
|
||||
CanQual<T> getUnqualifiedType() const;
|
||||
|
||||
CanQual<T> getQualifiedType(unsigned TQs) const {
|
||||
return CanQual<T>::CreateUnsafe(QualType(getTypePtr(), TQs));
|
||||
/// \brief Retrieves a version of this type with const applied.
|
||||
/// Note that this does not always yield a canonical type.
|
||||
QualType withConst() const {
|
||||
return Stored.withConst();
|
||||
}
|
||||
|
||||
/// \brief Determines whether this canonical type is more qualified than
|
||||
|
@ -605,6 +605,9 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
|
||||
/// \brief Determine whether this is or was instantiated from an out-of-line
|
||||
/// definition of a static data member.
|
||||
bool isOutOfLine() const;
|
||||
|
||||
/// \brief If this is a static data member, find its out-of-line definition.
|
||||
VarDecl *getOutOfLineDefinition();
|
||||
|
||||
/// \brief If this variable is an instantiated static data member of a
|
||||
/// class template specialization, returns the templated static data member
|
||||
@ -768,7 +771,11 @@ class ParmVarDecl : public VarDecl {
|
||||
Init = (UnparsedDefaultArgument *)0;
|
||||
}
|
||||
|
||||
QualType getOriginalType() const;
|
||||
QualType getOriginalType() const {
|
||||
if (getDeclaratorInfo())
|
||||
return getDeclaratorInfo()->getType();
|
||||
return getType();
|
||||
}
|
||||
|
||||
/// setOwningFunction - Sets the function declaration that owns this
|
||||
/// ParmVarDecl. Since ParmVarDecls are often created before the
|
||||
@ -778,41 +785,11 @@ class ParmVarDecl : public VarDecl {
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) {
|
||||
return (D->getKind() == ParmVar ||
|
||||
D->getKind() == OriginalParmVar);
|
||||
return (D->getKind() == ParmVar);
|
||||
}
|
||||
static bool classof(const ParmVarDecl *D) { return true; }
|
||||
};
|
||||
|
||||
/// OriginalParmVarDecl - Represent a parameter to a function, when
|
||||
/// the type of the parameter has been promoted. This node represents the
|
||||
/// parameter to the function with its original type.
|
||||
///
|
||||
class OriginalParmVarDecl : public ParmVarDecl {
|
||||
friend class ParmVarDecl;
|
||||
protected:
|
||||
QualType OriginalType;
|
||||
private:
|
||||
OriginalParmVarDecl(DeclContext *DC, SourceLocation L,
|
||||
IdentifierInfo *Id, QualType T,
|
||||
DeclaratorInfo *DInfo,
|
||||
QualType OT, StorageClass S,
|
||||
Expr *DefArg)
|
||||
: ParmVarDecl(OriginalParmVar, DC, L, Id, T, DInfo, S, DefArg),
|
||||
OriginalType(OT) {}
|
||||
public:
|
||||
static OriginalParmVarDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L,IdentifierInfo *Id,
|
||||
QualType T, DeclaratorInfo *DInfo,
|
||||
QualType OT, StorageClass S, Expr *DefArg);
|
||||
|
||||
void setOriginalType(QualType T) { OriginalType = T; }
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return D->getKind() == OriginalParmVar; }
|
||||
static bool classof(const OriginalParmVarDecl *D) { return true; }
|
||||
};
|
||||
|
||||
/// FunctionDecl - An instance of this class is created to represent a
|
||||
/// function declaration or definition.
|
||||
///
|
||||
@ -1067,9 +1044,18 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
|
||||
StorageClass getStorageClass() const { return StorageClass(SClass); }
|
||||
void setStorageClass(StorageClass SC) { SClass = SC; }
|
||||
|
||||
bool isInline() const { return IsInline; }
|
||||
void setInline(bool I) { IsInline = I; }
|
||||
/// \brief Determine whether the "inline" keyword was specified for this
|
||||
/// function.
|
||||
bool isInlineSpecified() const { return IsInline; }
|
||||
|
||||
/// Set whether the "inline" keyword was specified for this function.
|
||||
void setInlineSpecified(bool I) { IsInline = I; }
|
||||
|
||||
/// \brief Determine whether this function should be inlined, because it is
|
||||
/// either marked "inline" or is a member function of a C++ class that
|
||||
/// was defined in the class body.
|
||||
bool isInlined() const;
|
||||
|
||||
bool isInlineDefinitionExternallyVisible() const;
|
||||
|
||||
/// isOverloadedOperator - Whether this function declaration
|
||||
@ -1146,7 +1132,17 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
|
||||
return TemplateOrSpecialization.
|
||||
dyn_cast<FunctionTemplateSpecializationInfo*>();
|
||||
}
|
||||
|
||||
|
||||
/// \brief Determines whether this function is a function template
|
||||
/// specialization or a member of a class template specialization that can
|
||||
/// be implicitly instantiated.
|
||||
bool isImplicitlyInstantiable() const;
|
||||
|
||||
/// \brief Retrieve the function declaration from which this function could
|
||||
/// be instantiated, if it is an instantiation (rather than a non-template
|
||||
/// or a specialization, for example).
|
||||
FunctionDecl *getTemplateInstantiationPattern() const;
|
||||
|
||||
/// \brief Retrieve the primary template that this function template
|
||||
/// specialization either specializes or was instantiated from.
|
||||
///
|
||||
@ -1199,7 +1195,7 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
|
||||
/// instantiated from a template; otherwie, returns an invalid source
|
||||
/// location.
|
||||
SourceLocation getPointOfInstantiation() const;
|
||||
|
||||
|
||||
/// \brief Determine whether this is or was instantiated from an out-of-line
|
||||
/// definition of a member function.
|
||||
bool isOutOfLine() const;
|
||||
@ -1337,20 +1333,29 @@ class TypeDecl : public NamedDecl {
|
||||
|
||||
class TypedefDecl : public TypeDecl {
|
||||
/// UnderlyingType - This is the type the typedef is set to.
|
||||
QualType UnderlyingType;
|
||||
DeclaratorInfo *DInfo;
|
||||
|
||||
TypedefDecl(DeclContext *DC, SourceLocation L,
|
||||
IdentifierInfo *Id, QualType T)
|
||||
: TypeDecl(Typedef, DC, L, Id), UnderlyingType(T) {}
|
||||
IdentifierInfo *Id, DeclaratorInfo *DInfo)
|
||||
: TypeDecl(Typedef, DC, L, Id), DInfo(DInfo) {}
|
||||
|
||||
virtual ~TypedefDecl() {}
|
||||
public:
|
||||
|
||||
static TypedefDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L,IdentifierInfo *Id,
|
||||
QualType T);
|
||||
SourceLocation L, IdentifierInfo *Id,
|
||||
DeclaratorInfo *DInfo);
|
||||
|
||||
QualType getUnderlyingType() const { return UnderlyingType; }
|
||||
void setUnderlyingType(QualType newType) { UnderlyingType = newType; }
|
||||
DeclaratorInfo *getTypeDeclaratorInfo() const {
|
||||
return DInfo;
|
||||
}
|
||||
|
||||
QualType getUnderlyingType() const {
|
||||
return DInfo->getType();
|
||||
}
|
||||
void setTypeDeclaratorInfo(DeclaratorInfo *newType) {
|
||||
DInfo = newType;
|
||||
}
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return D->getKind() == Typedef; }
|
||||
|
@ -14,7 +14,7 @@
|
||||
#ifndef LLVM_CLANG_AST_DECLGROUP_H
|
||||
#define LLVM_CLANG_AST_DECLGROUP_H
|
||||
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/System/DataTypes.h"
|
||||
#include <cassert>
|
||||
|
||||
namespace clang {
|
||||
|
@ -103,7 +103,6 @@ ABSTRACT_DECL(Named, Decl)
|
||||
DECL(Var, DeclaratorDecl)
|
||||
DECL(ImplicitParam, VarDecl)
|
||||
DECL(ParmVar, VarDecl)
|
||||
DECL(OriginalParmVar, ParmVarDecl)
|
||||
DECL(NonTypeTemplateParm, VarDecl)
|
||||
DECL(Template, NamedDecl)
|
||||
DECL(FunctionTemplate, TemplateDecl)
|
||||
|
@ -347,6 +347,8 @@ class ObjCContainerDecl : public NamedDecl, public DeclContext {
|
||||
ObjCIvarDecl *getIvarDecl(IdentifierInfo *Id) const;
|
||||
|
||||
ObjCPropertyDecl *FindPropertyDeclaration(IdentifierInfo *PropertyId) const;
|
||||
ObjCPropertyDecl *FindPropertyVisibleInPrimaryClass(
|
||||
IdentifierInfo *PropertyId) const;
|
||||
|
||||
// Marks the end of the container.
|
||||
SourceLocation getAtEndLoc() const { return AtEndLoc; }
|
||||
@ -862,7 +864,7 @@ class ObjCCategoryDecl : public ObjCContainerDecl {
|
||||
};
|
||||
|
||||
class ObjCImplDecl : public ObjCContainerDecl {
|
||||
/// Class interface for this category implementation
|
||||
/// Class interface for this class/category implementation
|
||||
ObjCInterfaceDecl *ClassInterface;
|
||||
|
||||
protected:
|
||||
@ -935,14 +937,20 @@ class ObjCCategoryImplDecl : public ObjCImplDecl {
|
||||
SourceLocation L, IdentifierInfo *Id,
|
||||
ObjCInterfaceDecl *classInterface);
|
||||
|
||||
/// getIdentifier - Get the identifier that names the class
|
||||
/// getIdentifier - Get the identifier that names the category
|
||||
/// interface associated with this implementation.
|
||||
/// FIXME: This is a bad API, we are overriding the NamedDecl::getIdentifier()
|
||||
/// to mean something different. For example:
|
||||
/// ((NamedDecl *)SomeCategoryImplDecl)->getIdentifier()
|
||||
/// returns the class interface name, whereas
|
||||
/// ((ObjCCategoryImplDecl *)SomeCategoryImplDecl)->getIdentifier()
|
||||
/// returns the category name.
|
||||
IdentifierInfo *getIdentifier() const {
|
||||
return Id;
|
||||
}
|
||||
void setIdentifier(IdentifierInfo *II) { Id = II; }
|
||||
|
||||
ObjCCategoryDecl *getCategoryClass() const;
|
||||
ObjCCategoryDecl *getCategoryDecl() const;
|
||||
|
||||
/// getName - Get the name of identifier for the class interface associated
|
||||
/// with this implementation as a StringRef.
|
||||
|
@ -15,8 +15,7 @@
|
||||
#define LLVM_CLANG_AST_DECLTEMPLATE_H
|
||||
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
#include "llvm/ADT/APSInt.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "clang/AST/TemplateBase.h"
|
||||
#include "llvm/ADT/PointerUnion.h"
|
||||
#include <limits>
|
||||
|
||||
@ -91,6 +90,13 @@ class TemplateParameterList {
|
||||
/// arguments or if there is a parameter pack.
|
||||
unsigned getMinRequiredArguments() const;
|
||||
|
||||
/// \brief Get the depth of this template parameter list in the set of
|
||||
/// template parameter lists.
|
||||
///
|
||||
/// The first template parameter list in a declaration will have depth 0,
|
||||
/// the second template parameter list will have depth 1, etc.
|
||||
unsigned getDepth() const;
|
||||
|
||||
SourceLocation getTemplateLoc() const { return TemplateLoc; }
|
||||
SourceLocation getLAngleLoc() const { return LAngleLoc; }
|
||||
SourceLocation getRAngleLoc() const { return RAngleLoc; }
|
||||
@ -100,251 +106,6 @@ class TemplateParameterList {
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Represents a template argument within a class template
|
||||
/// specialization.
|
||||
class TemplateArgument {
|
||||
union {
|
||||
uintptr_t TypeOrValue;
|
||||
struct {
|
||||
char Value[sizeof(llvm::APSInt)];
|
||||
void *Type;
|
||||
} Integer;
|
||||
struct {
|
||||
TemplateArgument *Args;
|
||||
unsigned NumArgs;
|
||||
bool CopyArgs;
|
||||
} Args;
|
||||
};
|
||||
|
||||
/// \brief Location of the beginning of this template argument.
|
||||
SourceLocation StartLoc;
|
||||
|
||||
public:
|
||||
/// \brief The type of template argument we're storing.
|
||||
enum ArgKind {
|
||||
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,
|
||||
/// The template argument is a value- or type-dependent expression
|
||||
/// stored in an Expr*.
|
||||
Expression = 4,
|
||||
|
||||
/// The template argument is actually a parameter pack. Arguments are stored
|
||||
/// in the Args struct.
|
||||
Pack = 5
|
||||
} Kind;
|
||||
|
||||
/// \brief Construct an empty, invalid template argument.
|
||||
TemplateArgument() : TypeOrValue(0), StartLoc(), Kind(Null) { }
|
||||
|
||||
/// \brief Construct a template type argument.
|
||||
TemplateArgument(SourceLocation Loc, QualType T) : Kind(Type) {
|
||||
TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
|
||||
StartLoc = Loc;
|
||||
}
|
||||
|
||||
/// \brief Construct a template argument that refers to a
|
||||
/// declaration, which is either an external declaration or a
|
||||
/// template declaration.
|
||||
TemplateArgument(SourceLocation Loc, Decl *D) : Kind(Declaration) {
|
||||
// FIXME: Need to be sure we have the "canonical" declaration!
|
||||
TypeOrValue = reinterpret_cast<uintptr_t>(D);
|
||||
StartLoc = Loc;
|
||||
}
|
||||
|
||||
/// \brief Construct an integral constant template argument.
|
||||
TemplateArgument(SourceLocation Loc, const llvm::APSInt &Value,
|
||||
QualType Type)
|
||||
: Kind(Integral) {
|
||||
new (Integer.Value) llvm::APSInt(Value);
|
||||
Integer.Type = Type.getAsOpaquePtr();
|
||||
StartLoc = Loc;
|
||||
}
|
||||
|
||||
/// \brief Construct a template argument that is an expression.
|
||||
///
|
||||
/// This form of template argument only occurs in template argument
|
||||
/// lists used for dependent types and for expression; it will not
|
||||
/// occur in a non-dependent, canonical template argument list.
|
||||
TemplateArgument(Expr *E);
|
||||
|
||||
/// \brief Copy constructor for a template argument.
|
||||
TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) {
|
||||
if (Kind == Integral) {
|
||||
new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
|
||||
Integer.Type = Other.Integer.Type;
|
||||
} else if (Kind == Pack) {
|
||||
Args.NumArgs = Other.Args.NumArgs;
|
||||
Args.Args = new TemplateArgument[Args.NumArgs];
|
||||
for (unsigned I = 0; I != Args.NumArgs; ++I)
|
||||
Args.Args[I] = Other.Args.Args[I];
|
||||
}
|
||||
else
|
||||
TypeOrValue = Other.TypeOrValue;
|
||||
StartLoc = Other.StartLoc;
|
||||
}
|
||||
|
||||
TemplateArgument& operator=(const TemplateArgument& Other) {
|
||||
// FIXME: Does not provide the strong guarantee for exception
|
||||
// safety.
|
||||
using llvm::APSInt;
|
||||
|
||||
// FIXME: Handle Packs
|
||||
assert(Kind != Pack && "FIXME: Handle packs");
|
||||
assert(Other.Kind != Pack && "FIXME: Handle packs");
|
||||
|
||||
if (Kind == Other.Kind && Kind == Integral) {
|
||||
// Copy integral values.
|
||||
*this->getAsIntegral() = *Other.getAsIntegral();
|
||||
Integer.Type = Other.Integer.Type;
|
||||
} else {
|
||||
// Destroy the current integral value, if that's what we're holding.
|
||||
if (Kind == Integral)
|
||||
getAsIntegral()->~APSInt();
|
||||
|
||||
Kind = Other.Kind;
|
||||
|
||||
if (Other.Kind == Integral) {
|
||||
new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
|
||||
Integer.Type = Other.Integer.Type;
|
||||
} else
|
||||
TypeOrValue = Other.TypeOrValue;
|
||||
}
|
||||
StartLoc = Other.StartLoc;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
~TemplateArgument() {
|
||||
using llvm::APSInt;
|
||||
|
||||
if (Kind == Integral)
|
||||
getAsIntegral()->~APSInt();
|
||||
else if (Kind == Pack && Args.CopyArgs)
|
||||
delete[] Args.Args;
|
||||
}
|
||||
|
||||
/// \brief Return the kind of stored template argument.
|
||||
ArgKind getKind() const { return Kind; }
|
||||
|
||||
/// \brief Determine whether this template argument has no value.
|
||||
bool isNull() const { return Kind == Null; }
|
||||
|
||||
/// \brief Retrieve the template argument as a type.
|
||||
QualType getAsType() const {
|
||||
if (Kind != Type)
|
||||
return QualType();
|
||||
|
||||
return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue));
|
||||
}
|
||||
|
||||
/// \brief Retrieve the template argument as a declaration.
|
||||
Decl *getAsDecl() const {
|
||||
if (Kind != Declaration)
|
||||
return 0;
|
||||
return reinterpret_cast<Decl *>(TypeOrValue);
|
||||
}
|
||||
|
||||
/// \brief Retrieve the template argument as an integral value.
|
||||
llvm::APSInt *getAsIntegral() {
|
||||
if (Kind != Integral)
|
||||
return 0;
|
||||
return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]);
|
||||
}
|
||||
|
||||
const llvm::APSInt *getAsIntegral() const {
|
||||
return const_cast<TemplateArgument*>(this)->getAsIntegral();
|
||||
}
|
||||
|
||||
/// \brief Retrieve the type of the integral value.
|
||||
QualType getIntegralType() const {
|
||||
if (Kind != Integral)
|
||||
return QualType();
|
||||
|
||||
return QualType::getFromOpaquePtr(Integer.Type);
|
||||
}
|
||||
|
||||
void setIntegralType(QualType T) {
|
||||
assert(Kind == Integral &&
|
||||
"Cannot set the integral type of a non-integral template argument");
|
||||
Integer.Type = T.getAsOpaquePtr();
|
||||
};
|
||||
|
||||
/// \brief Retrieve the template argument as an expression.
|
||||
Expr *getAsExpr() const {
|
||||
if (Kind != Expression)
|
||||
return 0;
|
||||
|
||||
return reinterpret_cast<Expr *>(TypeOrValue);
|
||||
}
|
||||
|
||||
/// \brief Iterator that traverses the elements of a template argument pack.
|
||||
typedef const TemplateArgument * pack_iterator;
|
||||
|
||||
/// \brief Iterator referencing the first argument of a template argument
|
||||
/// pack.
|
||||
pack_iterator pack_begin() const {
|
||||
assert(Kind == Pack);
|
||||
return Args.Args;
|
||||
}
|
||||
|
||||
/// \brief Iterator referencing one past the last argument of a template
|
||||
/// argument pack.
|
||||
pack_iterator pack_end() const {
|
||||
assert(Kind == Pack);
|
||||
return Args.Args + Args.NumArgs;
|
||||
}
|
||||
|
||||
/// \brief The number of template arguments in the given template argument
|
||||
/// pack.
|
||||
unsigned pack_size() const {
|
||||
assert(Kind == Pack);
|
||||
return Args.NumArgs;
|
||||
}
|
||||
|
||||
/// \brief Retrieve the location where the template argument starts.
|
||||
SourceLocation getLocation() const { return StartLoc; }
|
||||
|
||||
/// \brief Construct a template argument pack.
|
||||
void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs);
|
||||
|
||||
/// \brief Used to insert TemplateArguments into FoldingSets.
|
||||
void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context) const {
|
||||
ID.AddInteger(Kind);
|
||||
switch (Kind) {
|
||||
case Null:
|
||||
break;
|
||||
|
||||
case Type:
|
||||
getAsType().Profile(ID);
|
||||
break;
|
||||
|
||||
case Declaration:
|
||||
ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0);
|
||||
break;
|
||||
|
||||
case Integral:
|
||||
getAsIntegral()->Profile(ID);
|
||||
getIntegralType().Profile(ID);
|
||||
break;
|
||||
|
||||
case Expression:
|
||||
getAsExpr()->Profile(ID, Context, true);
|
||||
break;
|
||||
|
||||
case Pack:
|
||||
ID.AddInteger(Args.NumArgs);
|
||||
for (unsigned I = 0; I != Args.NumArgs; ++I)
|
||||
Args.Args[I].Profile(ID, Context);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief A helper class for making template argument lists.
|
||||
class TemplateArgumentListBuilder {
|
||||
TemplateArgument *StructuredArgs;
|
||||
@ -811,11 +572,8 @@ class TemplateTypeParmDecl : public TypeDecl {
|
||||
/// \brief Whether this is a parameter pack.
|
||||
bool ParameterPack : 1;
|
||||
|
||||
/// \brief The location of the default argument, if any.
|
||||
SourceLocation DefaultArgumentLoc;
|
||||
|
||||
/// \brief The default template argument, if any.
|
||||
QualType DefaultArgument;
|
||||
DeclaratorInfo *DefaultArgument;
|
||||
|
||||
TemplateTypeParmDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
|
||||
bool Typename, QualType Type, bool ParameterPack)
|
||||
@ -837,13 +595,16 @@ class TemplateTypeParmDecl : public TypeDecl {
|
||||
|
||||
/// \brief Determine whether this template parameter has a default
|
||||
/// argument.
|
||||
bool hasDefaultArgument() const { return !DefaultArgument.isNull(); }
|
||||
bool hasDefaultArgument() const { return DefaultArgument != 0; }
|
||||
|
||||
/// \brief Retrieve the default argument, if any.
|
||||
QualType getDefaultArgument() const { return DefaultArgument; }
|
||||
QualType getDefaultArgument() const { return DefaultArgument->getType(); }
|
||||
|
||||
/// \brief Retrieve the location of the default argument, if any.
|
||||
SourceLocation getDefaultArgumentLoc() const { return DefaultArgumentLoc; }
|
||||
/// \brief Retrieves the default argument's source information, if any.
|
||||
DeclaratorInfo *getDefaultArgumentInfo() const { return DefaultArgument; }
|
||||
|
||||
/// \brief Retrieves the location of the default argument declaration.
|
||||
SourceLocation getDefaultArgumentLoc() const;
|
||||
|
||||
/// \brief Determines whether the default argument was inherited
|
||||
/// from a previous declaration of this template.
|
||||
@ -852,13 +613,23 @@ class TemplateTypeParmDecl : public TypeDecl {
|
||||
/// \brief Set the default argument for this template parameter, and
|
||||
/// whether that default argument was inherited from another
|
||||
/// declaration.
|
||||
void setDefaultArgument(QualType DefArg, SourceLocation DefArgLoc,
|
||||
bool Inherited) {
|
||||
void setDefaultArgument(DeclaratorInfo *DefArg, bool Inherited) {
|
||||
DefaultArgument = DefArg;
|
||||
DefaultArgumentLoc = DefArgLoc;
|
||||
InheritedDefault = Inherited;
|
||||
}
|
||||
|
||||
/// \brief Removes the default argument of this template parameter.
|
||||
void removeDefaultArgument() {
|
||||
DefaultArgument = 0;
|
||||
InheritedDefault = false;
|
||||
}
|
||||
|
||||
/// \brief Retrieve the depth of the template parameter.
|
||||
unsigned getDepth() const;
|
||||
|
||||
/// \brief Retrieve the index of the template parameter.
|
||||
unsigned getIndex() const;
|
||||
|
||||
/// \brief Returns whether this is a parameter pack.
|
||||
bool isParameterPack() const { return ParameterPack; }
|
||||
|
||||
@ -1150,17 +921,32 @@ class ClassTemplatePartialSpecializationDecl
|
||||
/// \brief The list of template parameters
|
||||
TemplateParameterList* TemplateParams;
|
||||
|
||||
/// \brief The source info for the template arguments as written.
|
||||
TemplateArgumentLoc *ArgsAsWritten;
|
||||
unsigned NumArgsAsWritten;
|
||||
|
||||
/// \brief The class template partial specialization from which this
|
||||
/// class template partial specialization was instantiated.
|
||||
///
|
||||
/// The boolean value will be true to indicate that this class template
|
||||
/// partial specialization was specialized at this level.
|
||||
llvm::PointerIntPair<ClassTemplatePartialSpecializationDecl *, 1, bool>
|
||||
InstantiatedFromMember;
|
||||
|
||||
ClassTemplatePartialSpecializationDecl(ASTContext &Context,
|
||||
DeclContext *DC, SourceLocation L,
|
||||
TemplateParameterList *Params,
|
||||
ClassTemplateDecl *SpecializedTemplate,
|
||||
TemplateArgumentListBuilder &Builder,
|
||||
TemplateArgumentLoc *ArgInfos,
|
||||
unsigned NumArgInfos,
|
||||
ClassTemplatePartialSpecializationDecl *PrevDecl)
|
||||
: ClassTemplateSpecializationDecl(Context,
|
||||
ClassTemplatePartialSpecialization,
|
||||
DC, L, SpecializedTemplate, Builder,
|
||||
PrevDecl),
|
||||
TemplateParams(Params) { }
|
||||
TemplateParams(Params), ArgsAsWritten(ArgInfos),
|
||||
NumArgsAsWritten(NumArgInfos), InstantiatedFromMember(0, false) { }
|
||||
|
||||
public:
|
||||
static ClassTemplatePartialSpecializationDecl *
|
||||
@ -1168,6 +954,8 @@ class ClassTemplatePartialSpecializationDecl
|
||||
TemplateParameterList *Params,
|
||||
ClassTemplateDecl *SpecializedTemplate,
|
||||
TemplateArgumentListBuilder &Builder,
|
||||
TemplateArgumentLoc *ArgInfos,
|
||||
unsigned NumArgInfos,
|
||||
ClassTemplatePartialSpecializationDecl *PrevDecl);
|
||||
|
||||
/// Get the list of template parameters
|
||||
@ -1175,6 +963,80 @@ class ClassTemplatePartialSpecializationDecl
|
||||
return TemplateParams;
|
||||
}
|
||||
|
||||
/// Get the template arguments as written.
|
||||
TemplateArgumentLoc *getTemplateArgsAsWritten() const {
|
||||
return ArgsAsWritten;
|
||||
}
|
||||
|
||||
/// Get the number of template arguments as written.
|
||||
unsigned getNumTemplateArgsAsWritten() const {
|
||||
return NumArgsAsWritten;
|
||||
}
|
||||
|
||||
/// \brief Retrieve the member class template partial specialization from
|
||||
/// which this particular class template partial specialization was
|
||||
/// instantiated.
|
||||
///
|
||||
/// \code
|
||||
/// template<typename T>
|
||||
/// struct Outer {
|
||||
/// template<typename U> struct Inner;
|
||||
/// template<typename U> struct Inner<U*> { }; // #1
|
||||
/// };
|
||||
///
|
||||
/// Outer<float>::Inner<int*> ii;
|
||||
/// \endcode
|
||||
///
|
||||
/// In this example, the instantiation of \c Outer<float>::Inner<int*> will
|
||||
/// end up instantiating the partial specialization
|
||||
/// \c Outer<float>::Inner<U*>, which itself was instantiated from the class
|
||||
/// template partial specialization \c Outer<T>::Inner<U*>. Given
|
||||
/// \c Outer<float>::Inner<U*>, this function would return
|
||||
/// \c Outer<T>::Inner<U*>.
|
||||
ClassTemplatePartialSpecializationDecl *getInstantiatedFromMember() {
|
||||
ClassTemplatePartialSpecializationDecl *First
|
||||
= cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration());
|
||||
return First->InstantiatedFromMember.getPointer();
|
||||
}
|
||||
|
||||
void setInstantiatedFromMember(
|
||||
ClassTemplatePartialSpecializationDecl *PartialSpec) {
|
||||
ClassTemplatePartialSpecializationDecl *First
|
||||
= cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration());
|
||||
First->InstantiatedFromMember.setPointer(PartialSpec);
|
||||
}
|
||||
|
||||
/// \brief Determines whether this class template partial specialization
|
||||
/// template was a specialization of a member partial specialization.
|
||||
///
|
||||
/// In the following example, the member template partial specialization
|
||||
/// \c X<int>::Inner<T*> is a member specialization.
|
||||
///
|
||||
/// \code
|
||||
/// template<typename T>
|
||||
/// struct X {
|
||||
/// template<typename U> struct Inner;
|
||||
/// template<typename U> struct Inner<U*>;
|
||||
/// };
|
||||
///
|
||||
/// template<> template<typename T>
|
||||
/// struct X<int>::Inner<T*> { /* ... */ };
|
||||
/// \endcode
|
||||
bool isMemberSpecialization() {
|
||||
ClassTemplatePartialSpecializationDecl *First
|
||||
= cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration());
|
||||
return First->InstantiatedFromMember.getInt();
|
||||
}
|
||||
|
||||
/// \brief Note that this member template is a specialization.
|
||||
void setMemberSpecialization() {
|
||||
ClassTemplatePartialSpecializationDecl *First
|
||||
= cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration());
|
||||
assert(First->InstantiatedFromMember.getPointer() &&
|
||||
"Only member templates can be member template specializations");
|
||||
return First->InstantiatedFromMember.setInt(true);
|
||||
}
|
||||
|
||||
// FIXME: Add Profile support!
|
||||
|
||||
static bool classof(const Decl *D) {
|
||||
|
@ -34,6 +34,7 @@ namespace clang {
|
||||
class BlockDecl;
|
||||
class CXXOperatorCallExpr;
|
||||
class CXXMemberCallExpr;
|
||||
class TemplateArgumentLoc;
|
||||
|
||||
/// Expr - This represents one expression. Note that Expr's are subclasses of
|
||||
/// Stmt. This allows an expression to be transparently used any place a Stmt
|
||||
@ -134,7 +135,7 @@ class Expr : public Stmt {
|
||||
/// with location to warn on and the source range[s] to report with the
|
||||
/// warning.
|
||||
bool isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
|
||||
SourceRange &R2) const;
|
||||
SourceRange &R2, ASTContext &Ctx) const;
|
||||
|
||||
/// isLvalue - C99 6.3.2.1: an lvalue is an expression with an object type or
|
||||
/// incomplete type other than void. Nonarray expressions that can be lvalues:
|
||||
@ -241,6 +242,10 @@ class Expr : public Stmt {
|
||||
/// in Result.
|
||||
bool Evaluate(EvalResult &Result, ASTContext &Ctx) const;
|
||||
|
||||
/// EvaluateAsAny - The same as Evaluate, except that it also succeeds on
|
||||
/// stack based objects.
|
||||
bool EvaluateAsAny(EvalResult &Result, ASTContext &Ctx) const;
|
||||
|
||||
/// isEvaluatable - Call Evaluate to see if this expression can be constant
|
||||
/// folded, but discard the result.
|
||||
bool isEvaluatable(ASTContext &Ctx) const;
|
||||
@ -322,47 +327,221 @@ class Expr : public Stmt {
|
||||
// Primary Expressions.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// \brief Represents the qualifier that may precede a C++ name, e.g., the
|
||||
/// "std::" in "std::sort".
|
||||
struct NameQualifier {
|
||||
/// \brief The nested name specifier.
|
||||
NestedNameSpecifier *NNS;
|
||||
|
||||
/// \brief The source range covered by the nested name specifier.
|
||||
SourceRange Range;
|
||||
};
|
||||
|
||||
/// \brief Represents an explicit template argument list in C++, e.g.,
|
||||
/// the "<int>" in "sort<int>".
|
||||
struct ExplicitTemplateArgumentList {
|
||||
/// \brief The source location of the left angle bracket ('<');
|
||||
SourceLocation LAngleLoc;
|
||||
|
||||
/// \brief The source location of the right angle bracket ('>');
|
||||
SourceLocation RAngleLoc;
|
||||
|
||||
/// \brief The number of template arguments in TemplateArgs.
|
||||
/// The actual template arguments (if any) are stored after the
|
||||
/// ExplicitTemplateArgumentList structure.
|
||||
unsigned NumTemplateArgs;
|
||||
|
||||
/// \brief Retrieve the template arguments
|
||||
TemplateArgumentLoc *getTemplateArgs() {
|
||||
return reinterpret_cast<TemplateArgumentLoc *> (this + 1);
|
||||
}
|
||||
|
||||
/// \brief Retrieve the template arguments
|
||||
const TemplateArgumentLoc *getTemplateArgs() const {
|
||||
return reinterpret_cast<const TemplateArgumentLoc *> (this + 1);
|
||||
}
|
||||
};
|
||||
|
||||
/// DeclRefExpr - [C99 6.5.1p2] - A reference to a declared variable, function,
|
||||
/// enum, etc.
|
||||
class DeclRefExpr : public Expr {
|
||||
NamedDecl *D;
|
||||
enum {
|
||||
// Flag on DecoratedD that specifies when this declaration reference
|
||||
// expression has a C++ nested-name-specifier.
|
||||
HasQualifierFlag = 0x01,
|
||||
// Flag on DecoratedD that specifies when this declaration reference
|
||||
// expression has an explicit C++ template argument list.
|
||||
HasExplicitTemplateArgumentListFlag = 0x02
|
||||
};
|
||||
|
||||
// DecoratedD - The declaration that we are referencing, plus two bits to
|
||||
// indicate whether (1) the declaration's name was explicitly qualified and
|
||||
// (2) the declaration's name was followed by an explicit template
|
||||
// argument list.
|
||||
llvm::PointerIntPair<NamedDecl *, 2> DecoratedD;
|
||||
|
||||
// Loc - The location of the declaration name itself.
|
||||
SourceLocation Loc;
|
||||
|
||||
/// \brief Retrieve the qualifier that preceded the declaration name, if any.
|
||||
NameQualifier *getNameQualifier() {
|
||||
if ((DecoratedD.getInt() & HasQualifierFlag) == 0)
|
||||
return 0;
|
||||
|
||||
return reinterpret_cast<NameQualifier *> (this + 1);
|
||||
}
|
||||
|
||||
/// \brief Retrieve the qualifier that preceded the member name, if any.
|
||||
const NameQualifier *getNameQualifier() const {
|
||||
return const_cast<DeclRefExpr *>(this)->getNameQualifier();
|
||||
}
|
||||
|
||||
/// \brief Retrieve the explicit template argument list that followed the
|
||||
/// member template name, if any.
|
||||
ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() {
|
||||
if ((DecoratedD.getInt() & HasExplicitTemplateArgumentListFlag) == 0)
|
||||
return 0;
|
||||
|
||||
if ((DecoratedD.getInt() & HasQualifierFlag) == 0)
|
||||
return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
|
||||
|
||||
return reinterpret_cast<ExplicitTemplateArgumentList *>(
|
||||
getNameQualifier() + 1);
|
||||
}
|
||||
|
||||
/// \brief Retrieve the explicit template argument list that followed the
|
||||
/// member template name, if any.
|
||||
const ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() const {
|
||||
return const_cast<DeclRefExpr *>(this)->getExplicitTemplateArgumentList();
|
||||
}
|
||||
|
||||
DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange,
|
||||
NamedDecl *D, SourceLocation NameLoc,
|
||||
bool HasExplicitTemplateArgumentList,
|
||||
SourceLocation LAngleLoc,
|
||||
const TemplateArgumentLoc *ExplicitTemplateArgs,
|
||||
unsigned NumExplicitTemplateArgs,
|
||||
SourceLocation RAngleLoc,
|
||||
QualType T, bool TD, bool VD);
|
||||
|
||||
protected:
|
||||
// FIXME: Eventually, this constructor will go away and all subclasses
|
||||
// will have to provide the type- and value-dependent flags.
|
||||
DeclRefExpr(StmtClass SC, NamedDecl *d, QualType t, SourceLocation l) :
|
||||
Expr(SC, t), D(d), Loc(l) {}
|
||||
Expr(SC, t), DecoratedD(d, 0), Loc(l) {}
|
||||
|
||||
DeclRefExpr(StmtClass SC, NamedDecl *d, QualType t, SourceLocation l, bool TD,
|
||||
bool VD) :
|
||||
Expr(SC, t, TD, VD), D(d), Loc(l) {}
|
||||
Expr(SC, t, TD, VD), DecoratedD(d, 0), Loc(l) {}
|
||||
|
||||
public:
|
||||
// FIXME: Eventually, this constructor will go away and all clients
|
||||
// will have to provide the type- and value-dependent flags.
|
||||
DeclRefExpr(NamedDecl *d, QualType t, SourceLocation l) :
|
||||
Expr(DeclRefExprClass, t), D(d), Loc(l) {}
|
||||
Expr(DeclRefExprClass, t), DecoratedD(d, 0), Loc(l) {}
|
||||
|
||||
DeclRefExpr(NamedDecl *d, QualType t, SourceLocation l, bool TD, bool VD) :
|
||||
Expr(DeclRefExprClass, t, TD, VD), D(d), Loc(l) {}
|
||||
Expr(DeclRefExprClass, t, TD, VD), DecoratedD(d, 0), Loc(l) {}
|
||||
|
||||
/// \brief Construct an empty declaration reference expression.
|
||||
explicit DeclRefExpr(EmptyShell Empty)
|
||||
: Expr(DeclRefExprClass, Empty) { }
|
||||
|
||||
NamedDecl *getDecl() { return D; }
|
||||
const NamedDecl *getDecl() const { return D; }
|
||||
void setDecl(NamedDecl *NewD) { D = NewD; }
|
||||
static DeclRefExpr *Create(ASTContext &Context,
|
||||
NestedNameSpecifier *Qualifier,
|
||||
SourceRange QualifierRange,
|
||||
NamedDecl *D,
|
||||
SourceLocation NameLoc,
|
||||
QualType T, bool TD, bool VD);
|
||||
|
||||
static DeclRefExpr *Create(ASTContext &Context,
|
||||
NestedNameSpecifier *Qualifier,
|
||||
SourceRange QualifierRange,
|
||||
NamedDecl *D,
|
||||
SourceLocation NameLoc,
|
||||
bool HasExplicitTemplateArgumentList,
|
||||
SourceLocation LAngleLoc,
|
||||
const TemplateArgumentLoc *ExplicitTemplateArgs,
|
||||
unsigned NumExplicitTemplateArgs,
|
||||
SourceLocation RAngleLoc,
|
||||
QualType T, bool TD, bool VD);
|
||||
|
||||
NamedDecl *getDecl() { return DecoratedD.getPointer(); }
|
||||
const NamedDecl *getDecl() const { return DecoratedD.getPointer(); }
|
||||
void setDecl(NamedDecl *NewD) { DecoratedD.setPointer(NewD); }
|
||||
|
||||
SourceLocation getLocation() const { return Loc; }
|
||||
void setLocation(SourceLocation L) { Loc = L; }
|
||||
virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
|
||||
virtual SourceRange getSourceRange() const;
|
||||
|
||||
/// \brief Determine whether this declaration reference was preceded by a
|
||||
/// C++ nested-name-specifier, e.g., \c N::foo.
|
||||
bool hasQualifier() const { return DecoratedD.getInt() & HasQualifierFlag; }
|
||||
|
||||
/// \brief If the name was qualified, retrieves the source range of
|
||||
/// the nested-name-specifier that precedes the name. Otherwise,
|
||||
/// returns an empty source range.
|
||||
SourceRange getQualifierRange() const {
|
||||
if (!hasQualifier())
|
||||
return SourceRange();
|
||||
|
||||
return getNameQualifier()->Range;
|
||||
}
|
||||
|
||||
/// \brief If the name was qualified, retrieves the nested-name-specifier
|
||||
/// that precedes the name. Otherwise, returns NULL.
|
||||
NestedNameSpecifier *getQualifier() const {
|
||||
if (!hasQualifier())
|
||||
return 0;
|
||||
|
||||
return getNameQualifier()->NNS;
|
||||
}
|
||||
|
||||
/// \brief Determines whether this member expression actually had a C++
|
||||
/// template argument list explicitly specified, e.g., x.f<int>.
|
||||
bool hasExplicitTemplateArgumentList() const {
|
||||
return DecoratedD.getInt() & HasExplicitTemplateArgumentListFlag;
|
||||
}
|
||||
|
||||
/// \brief Retrieve the location of the left angle bracket following the
|
||||
/// member name ('<'), if any.
|
||||
SourceLocation getLAngleLoc() const {
|
||||
if (!hasExplicitTemplateArgumentList())
|
||||
return SourceLocation();
|
||||
|
||||
return getExplicitTemplateArgumentList()->LAngleLoc;
|
||||
}
|
||||
|
||||
/// \brief Retrieve the template arguments provided as part of this
|
||||
/// template-id.
|
||||
const TemplateArgumentLoc *getTemplateArgs() const {
|
||||
if (!hasExplicitTemplateArgumentList())
|
||||
return 0;
|
||||
|
||||
return getExplicitTemplateArgumentList()->getTemplateArgs();
|
||||
}
|
||||
|
||||
/// \brief Retrieve the number of template arguments provided as part of this
|
||||
/// template-id.
|
||||
unsigned getNumTemplateArgs() const {
|
||||
if (!hasExplicitTemplateArgumentList())
|
||||
return 0;
|
||||
|
||||
return getExplicitTemplateArgumentList()->NumTemplateArgs;
|
||||
}
|
||||
|
||||
/// \brief Retrieve the location of the right angle bracket following the
|
||||
/// template arguments ('>').
|
||||
SourceLocation getRAngleLoc() const {
|
||||
if (!hasExplicitTemplateArgumentList())
|
||||
return SourceLocation();
|
||||
|
||||
return getExplicitTemplateArgumentList()->RAngleLoc;
|
||||
}
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == DeclRefExprClass ||
|
||||
T->getStmtClass() == CXXConditionDeclExprClass ||
|
||||
T->getStmtClass() == QualifiedDeclRefExprClass;
|
||||
T->getStmtClass() == CXXConditionDeclExprClass;
|
||||
}
|
||||
static bool classof(const DeclRefExpr *) { return true; }
|
||||
|
||||
@ -797,7 +976,7 @@ class SizeOfAlignOfExpr : public Expr {
|
||||
bool isSizeof : 1; // true if sizeof, false if alignof.
|
||||
bool isType : 1; // true if operand is a type, false if an expression
|
||||
union {
|
||||
void *Ty;
|
||||
DeclaratorInfo *Ty;
|
||||
Stmt *Ex;
|
||||
} Argument;
|
||||
SourceLocation OpLoc, RParenLoc;
|
||||
@ -806,15 +985,15 @@ class SizeOfAlignOfExpr : public Expr {
|
||||
virtual void DoDestroy(ASTContext& C);
|
||||
|
||||
public:
|
||||
SizeOfAlignOfExpr(bool issizeof, QualType T,
|
||||
SizeOfAlignOfExpr(bool issizeof, DeclaratorInfo *DInfo,
|
||||
QualType resultType, SourceLocation op,
|
||||
SourceLocation rp) :
|
||||
Expr(SizeOfAlignOfExprClass, resultType,
|
||||
false, // Never type-dependent (C++ [temp.dep.expr]p3).
|
||||
// Value-dependent if the argument is type-dependent.
|
||||
T->isDependentType()),
|
||||
DInfo->getType()->isDependentType()),
|
||||
isSizeof(issizeof), isType(true), OpLoc(op), RParenLoc(rp) {
|
||||
Argument.Ty = T.getAsOpaquePtr();
|
||||
Argument.Ty = DInfo;
|
||||
}
|
||||
|
||||
SizeOfAlignOfExpr(bool issizeof, Expr *E,
|
||||
@ -837,8 +1016,11 @@ class SizeOfAlignOfExpr : public Expr {
|
||||
|
||||
bool isArgumentType() const { return isType; }
|
||||
QualType getArgumentType() const {
|
||||
return getArgumentTypeInfo()->getType();
|
||||
}
|
||||
DeclaratorInfo *getArgumentTypeInfo() const {
|
||||
assert(isArgumentType() && "calling getArgumentType() when arg is expr");
|
||||
return QualType::getFromOpaquePtr(Argument.Ty);
|
||||
return Argument.Ty;
|
||||
}
|
||||
Expr *getArgumentExpr() {
|
||||
assert(!isArgumentType() && "calling getArgumentExpr() when arg is type");
|
||||
@ -849,8 +1031,8 @@ class SizeOfAlignOfExpr : public Expr {
|
||||
}
|
||||
|
||||
void setArgument(Expr *E) { Argument.Ex = E; isType = false; }
|
||||
void setArgument(QualType T) {
|
||||
Argument.Ty = T.getAsOpaquePtr();
|
||||
void setArgument(DeclaratorInfo *DInfo) {
|
||||
Argument.Ty = DInfo;
|
||||
isType = true;
|
||||
}
|
||||
|
||||
@ -1062,41 +1244,6 @@ class CallExpr : public Expr {
|
||||
virtual child_iterator child_end();
|
||||
};
|
||||
|
||||
/// \brief Represents the qualifier that may precede a C++ name, e.g., the
|
||||
/// "std::" in "std::sort".
|
||||
struct NameQualifier {
|
||||
/// \brief The nested name specifier.
|
||||
NestedNameSpecifier *NNS;
|
||||
|
||||
/// \brief The source range covered by the nested name specifier.
|
||||
SourceRange Range;
|
||||
};
|
||||
|
||||
/// \brief Represents an explicit template argument list in C++, e.g.,
|
||||
/// the "<int>" in "sort<int>".
|
||||
struct ExplicitTemplateArgumentList {
|
||||
/// \brief The source location of the left angle bracket ('<');
|
||||
SourceLocation LAngleLoc;
|
||||
|
||||
/// \brief The source location of the right angle bracket ('>');
|
||||
SourceLocation RAngleLoc;
|
||||
|
||||
/// \brief The number of template arguments in TemplateArgs.
|
||||
/// The actual template arguments (if any) are stored after the
|
||||
/// ExplicitTemplateArgumentList structure.
|
||||
unsigned NumTemplateArgs;
|
||||
|
||||
/// \brief Retrieve the template arguments
|
||||
TemplateArgument *getTemplateArgs() {
|
||||
return reinterpret_cast<TemplateArgument *> (this + 1);
|
||||
}
|
||||
|
||||
/// \brief Retrieve the template arguments
|
||||
const TemplateArgument *getTemplateArgs() const {
|
||||
return reinterpret_cast<const TemplateArgument *> (this + 1);
|
||||
}
|
||||
};
|
||||
|
||||
/// MemberExpr - [C99 6.5.2.3] Structure and Union Members. X->F and X.F.
|
||||
///
|
||||
class MemberExpr : public Expr {
|
||||
@ -1161,7 +1308,7 @@ class MemberExpr : public Expr {
|
||||
MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual,
|
||||
SourceRange qualrange, NamedDecl *memberdecl, SourceLocation l,
|
||||
bool has_explicit, SourceLocation langle,
|
||||
const TemplateArgument *targs, unsigned numtargs,
|
||||
const TemplateArgumentLoc *targs, unsigned numtargs,
|
||||
SourceLocation rangle, QualType ty);
|
||||
|
||||
public:
|
||||
@ -1183,7 +1330,7 @@ class MemberExpr : public Expr {
|
||||
SourceLocation l,
|
||||
bool has_explicit,
|
||||
SourceLocation langle,
|
||||
const TemplateArgument *targs,
|
||||
const TemplateArgumentLoc *targs,
|
||||
unsigned numtargs,
|
||||
SourceLocation rangle,
|
||||
QualType ty);
|
||||
@ -1240,7 +1387,7 @@ class MemberExpr : public Expr {
|
||||
|
||||
/// \brief Retrieve the template arguments provided as part of this
|
||||
/// template-id.
|
||||
const TemplateArgument *getTemplateArgs() const {
|
||||
const TemplateArgumentLoc *getTemplateArgs() const {
|
||||
if (!HasExplicitTemplateArgumentList)
|
||||
return 0;
|
||||
|
||||
@ -1388,6 +1535,10 @@ class CastExpr : public Expr {
|
||||
/// member pointer in derived class.
|
||||
CK_BaseToDerivedMemberPointer,
|
||||
|
||||
/// CK_DerivedToBaseMemberPointer - Member pointer in derived class to
|
||||
/// member pointer in base class.
|
||||
CK_DerivedToBaseMemberPointer,
|
||||
|
||||
/// CK_UserDefinedConversion - Conversion using a user defined type
|
||||
/// conversion function.
|
||||
CK_UserDefinedConversion,
|
||||
@ -1687,7 +1838,9 @@ class BinaryOperator : public Expr {
|
||||
bool isAdditiveOp() const { return Opc == Add || Opc == Sub; }
|
||||
static bool isShiftOp(Opcode Opc) { return Opc == Shl || Opc == Shr; }
|
||||
bool isShiftOp() const { return isShiftOp(Opc); }
|
||||
bool isBitwiseOp() const { return Opc >= And && Opc <= Or; }
|
||||
|
||||
static bool isBitwiseOp(Opcode Opc) { return Opc >= And && Opc <= Or; }
|
||||
bool isBitwiseOp() const { return isBitwiseOp(Opc); }
|
||||
|
||||
static bool isRelationalOp(Opcode Opc) { return Opc >= LT && Opc <= GE; }
|
||||
bool isRelationalOp() const { return isRelationalOp(Opc); }
|
||||
@ -1695,6 +1848,9 @@ class BinaryOperator : public Expr {
|
||||
static bool isEqualityOp(Opcode Opc) { return Opc == EQ || Opc == NE; }
|
||||
bool isEqualityOp() const { return isEqualityOp(Opc); }
|
||||
|
||||
static bool isComparisonOp(Opcode Opc) { return Opc >= LT && Opc <= NE; }
|
||||
bool isComparisonOp() const { return isComparisonOp(Opc); }
|
||||
|
||||
static bool isLogicalOp(Opcode Opc) { return Opc == LAnd || Opc == LOr; }
|
||||
bool isLogicalOp() const { return isLogicalOp(Opc); }
|
||||
|
||||
|
@ -1061,46 +1061,11 @@ class UnaryTypeTraitExpr : public Expr {
|
||||
virtual child_iterator child_end();
|
||||
};
|
||||
|
||||
/// QualifiedDeclRefExpr - A reference to a declared variable,
|
||||
/// function, enum, etc., that includes a qualification, e.g.,
|
||||
/// "N::foo".
|
||||
class QualifiedDeclRefExpr : public DeclRefExpr {
|
||||
/// QualifierRange - The source range that covers the
|
||||
/// nested-name-specifier.
|
||||
SourceRange QualifierRange;
|
||||
|
||||
/// \brief The nested-name-specifier that qualifies this declaration
|
||||
/// name.
|
||||
NestedNameSpecifier *NNS;
|
||||
|
||||
public:
|
||||
QualifiedDeclRefExpr(NamedDecl *d, QualType t, SourceLocation l, bool TD,
|
||||
bool VD, SourceRange R, NestedNameSpecifier *NNS)
|
||||
: DeclRefExpr(QualifiedDeclRefExprClass, d, t, l, TD, VD),
|
||||
QualifierRange(R), NNS(NNS) { }
|
||||
|
||||
/// \brief Retrieve the source range of the nested-name-specifier.
|
||||
SourceRange getQualifierRange() const { return QualifierRange; }
|
||||
|
||||
/// \brief Retrieve the nested-name-specifier that qualifies this
|
||||
/// declaration.
|
||||
NestedNameSpecifier *getQualifier() const { return NNS; }
|
||||
|
||||
virtual SourceRange getSourceRange() const {
|
||||
return SourceRange(QualifierRange.getBegin(), getLocation());
|
||||
}
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == QualifiedDeclRefExprClass;
|
||||
}
|
||||
static bool classof(const QualifiedDeclRefExpr *) { return true; }
|
||||
};
|
||||
|
||||
/// \brief A qualified reference to a name whose declaration cannot
|
||||
/// yet be resolved.
|
||||
///
|
||||
/// UnresolvedDeclRefExpr is similar to QualifiedDeclRefExpr in that
|
||||
/// it expresses a qualified reference to a declaration such as
|
||||
/// UnresolvedDeclRefExpr is similar to eclRefExpr in that
|
||||
/// it expresses a reference to a declaration such as
|
||||
/// X<T>::value. The difference, however, is that an
|
||||
/// UnresolvedDeclRefExpr node is used only within C++ templates when
|
||||
/// the qualification (e.g., X<T>::) refers to a dependent type. In
|
||||
@ -1108,8 +1073,8 @@ class QualifiedDeclRefExpr : public DeclRefExpr {
|
||||
/// declaration will differ from on instantiation of X<T> to the
|
||||
/// next. Therefore, UnresolvedDeclRefExpr keeps track of the
|
||||
/// qualifier (X<T>::) and the name of the entity being referenced
|
||||
/// ("value"). Such expressions will instantiate to
|
||||
/// QualifiedDeclRefExprs.
|
||||
/// ("value"). Such expressions will instantiate to a DeclRefExpr once the
|
||||
/// declaration can be found.
|
||||
class UnresolvedDeclRefExpr : public Expr {
|
||||
/// The name of the entity we will be referencing.
|
||||
DeclarationName Name;
|
||||
@ -1126,6 +1091,7 @@ class UnresolvedDeclRefExpr : public Expr {
|
||||
NestedNameSpecifier *NNS;
|
||||
|
||||
/// \brief Whether this expr is an address of (&) operand.
|
||||
/// FIXME: Stash this bit into NNS!
|
||||
bool IsAddressOfOperand;
|
||||
|
||||
public:
|
||||
@ -1195,7 +1161,7 @@ class TemplateIdRefExpr : public Expr {
|
||||
NestedNameSpecifier *Qualifier, SourceRange QualifierRange,
|
||||
TemplateName Template, SourceLocation TemplateNameLoc,
|
||||
SourceLocation LAngleLoc,
|
||||
const TemplateArgument *TemplateArgs,
|
||||
const TemplateArgumentLoc *TemplateArgs,
|
||||
unsigned NumTemplateArgs,
|
||||
SourceLocation RAngleLoc);
|
||||
|
||||
@ -1206,7 +1172,7 @@ class TemplateIdRefExpr : public Expr {
|
||||
Create(ASTContext &Context, QualType T,
|
||||
NestedNameSpecifier *Qualifier, SourceRange QualifierRange,
|
||||
TemplateName Template, SourceLocation TemplateNameLoc,
|
||||
SourceLocation LAngleLoc, const TemplateArgument *TemplateArgs,
|
||||
SourceLocation LAngleLoc, const TemplateArgumentLoc *TemplateArgs,
|
||||
unsigned NumTemplateArgs, SourceLocation RAngleLoc);
|
||||
|
||||
/// \brief Retrieve the nested name specifier used to qualify the name of
|
||||
@ -1232,8 +1198,8 @@ class TemplateIdRefExpr : public Expr {
|
||||
|
||||
/// \brief Retrieve the template arguments provided as part of this
|
||||
/// template-id.
|
||||
const TemplateArgument *getTemplateArgs() const {
|
||||
return reinterpret_cast<const TemplateArgument *>(this + 1);
|
||||
const TemplateArgumentLoc *getTemplateArgs() const {
|
||||
return reinterpret_cast<const TemplateArgumentLoc *>(this + 1);
|
||||
}
|
||||
|
||||
/// \brief Retrieve the number of template arguments provided as part of this
|
||||
@ -1477,7 +1443,7 @@ class CXXUnresolvedMemberExpr : public Expr {
|
||||
SourceLocation MemberLoc,
|
||||
bool HasExplicitTemplateArgs,
|
||||
SourceLocation LAngleLoc,
|
||||
const TemplateArgument *TemplateArgs,
|
||||
const TemplateArgumentLoc *TemplateArgs,
|
||||
unsigned NumTemplateArgs,
|
||||
SourceLocation RAngleLoc);
|
||||
|
||||
@ -1508,7 +1474,7 @@ class CXXUnresolvedMemberExpr : public Expr {
|
||||
SourceLocation MemberLoc,
|
||||
bool HasExplicitTemplateArgs,
|
||||
SourceLocation LAngleLoc,
|
||||
const TemplateArgument *TemplateArgs,
|
||||
const TemplateArgumentLoc *TemplateArgs,
|
||||
unsigned NumTemplateArgs,
|
||||
SourceLocation RAngleLoc);
|
||||
|
||||
@ -1576,7 +1542,7 @@ class CXXUnresolvedMemberExpr : public Expr {
|
||||
|
||||
/// \brief Retrieve the template arguments provided as part of this
|
||||
/// template-id.
|
||||
const TemplateArgument *getTemplateArgs() const {
|
||||
const TemplateArgumentLoc *getTemplateArgs() const {
|
||||
if (!HasExplicitTemplateArgumentList)
|
||||
return 0;
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
#ifndef LLVM_CLANG_AST_LAYOUTINFO_H
|
||||
#define LLVM_CLANG_AST_LAYOUTINFO_H
|
||||
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/System/DataTypes.h"
|
||||
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
|
@ -88,6 +88,11 @@ class Redeclarable {
|
||||
return D;
|
||||
}
|
||||
|
||||
/// \brief Returns the most recent (re)declaration of this declaration.
|
||||
const decl_type *getMostRecentDeclaration() const {
|
||||
return getFirstDeclaration()->RedeclLink.getNext();
|
||||
}
|
||||
|
||||
/// \brief Set the previous declaration. If PrevDecl is NULL, set this as the
|
||||
/// first and only declaration.
|
||||
void setPreviousDeclaration(decl_type *PrevDecl) {
|
||||
|
@ -14,7 +14,7 @@
|
||||
#ifndef LLVM_CLANG_AST_STMT_ITR_H
|
||||
#define LLVM_CLANG_AST_STMT_ITR_H
|
||||
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/System/DataTypes.h"
|
||||
#include <cassert>
|
||||
#include <iterator>
|
||||
|
||||
|
@ -127,7 +127,6 @@ EXPR(CXXDeleteExpr , Expr)
|
||||
EXPR(CXXPseudoDestructorExpr, Expr)
|
||||
EXPR(UnresolvedFunctionNameExpr , Expr)
|
||||
EXPR(UnaryTypeTraitExpr , Expr)
|
||||
EXPR(QualifiedDeclRefExpr , DeclRefExpr)
|
||||
EXPR(UnresolvedDeclRefExpr , Expr)
|
||||
EXPR(TemplateIdRefExpr , Expr)
|
||||
EXPR(CXXConstructExpr , Expr)
|
||||
|
366
include/clang/AST/TemplateBase.h
Normal file
366
include/clang/AST/TemplateBase.h
Normal file
@ -0,0 +1,366 @@
|
||||
//===-- TemplateBase.h - Core classes for C++ templates ---------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file provides definitions which are common for all kinds of
|
||||
// template representation.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_AST_TEMPLATEBASE_H
|
||||
#define LLVM_CLANG_AST_TEMPLATEBASE_H
|
||||
|
||||
#include "llvm/ADT/APSInt.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "clang/AST/Type.h"
|
||||
|
||||
namespace llvm {
|
||||
class FoldingSetNodeID;
|
||||
}
|
||||
|
||||
namespace clang {
|
||||
|
||||
class Decl;
|
||||
class Expr;
|
||||
class DeclaratorInfo;
|
||||
|
||||
/// \brief Represents a template argument within a class template
|
||||
/// specialization.
|
||||
class TemplateArgument {
|
||||
union {
|
||||
uintptr_t TypeOrValue;
|
||||
struct {
|
||||
char Value[sizeof(llvm::APSInt)];
|
||||
void *Type;
|
||||
} Integer;
|
||||
struct {
|
||||
TemplateArgument *Args;
|
||||
unsigned NumArgs;
|
||||
bool CopyArgs;
|
||||
} Args;
|
||||
};
|
||||
|
||||
public:
|
||||
/// \brief The type of template argument we're storing.
|
||||
enum ArgKind {
|
||||
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,
|
||||
/// The template argument is a value- or type-dependent expression
|
||||
/// stored in an Expr*.
|
||||
Expression = 4,
|
||||
|
||||
/// The template argument is actually a parameter pack. Arguments are stored
|
||||
/// in the Args struct.
|
||||
Pack = 5
|
||||
} Kind;
|
||||
|
||||
/// \brief Construct an empty, invalid template argument.
|
||||
TemplateArgument() : TypeOrValue(0), Kind(Null) { }
|
||||
|
||||
/// \brief Construct a template type argument.
|
||||
TemplateArgument(QualType T) : Kind(Type) {
|
||||
TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
|
||||
}
|
||||
|
||||
/// \brief Construct a template argument that refers to a
|
||||
/// declaration, which is either an external declaration or a
|
||||
/// template declaration.
|
||||
TemplateArgument(Decl *D) : Kind(Declaration) {
|
||||
// FIXME: Need to be sure we have the "canonical" declaration!
|
||||
TypeOrValue = reinterpret_cast<uintptr_t>(D);
|
||||
}
|
||||
|
||||
/// \brief Construct an integral constant template argument.
|
||||
TemplateArgument(const llvm::APSInt &Value, QualType Type)
|
||||
: Kind(Integral) {
|
||||
new (Integer.Value) llvm::APSInt(Value);
|
||||
Integer.Type = Type.getAsOpaquePtr();
|
||||
}
|
||||
|
||||
/// \brief Construct a template argument that is an expression.
|
||||
///
|
||||
/// This form of template argument only occurs in template argument
|
||||
/// lists used for dependent types and for expression; it will not
|
||||
/// occur in a non-dependent, canonical template argument list.
|
||||
TemplateArgument(Expr *E) : Kind(Expression) {
|
||||
TypeOrValue = reinterpret_cast<uintptr_t>(E);
|
||||
}
|
||||
|
||||
/// \brief Copy constructor for a template argument.
|
||||
TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) {
|
||||
if (Kind == Integral) {
|
||||
new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
|
||||
Integer.Type = Other.Integer.Type;
|
||||
} else if (Kind == Pack) {
|
||||
Args.NumArgs = Other.Args.NumArgs;
|
||||
Args.Args = new TemplateArgument[Args.NumArgs];
|
||||
for (unsigned I = 0; I != Args.NumArgs; ++I)
|
||||
Args.Args[I] = Other.Args.Args[I];
|
||||
}
|
||||
else
|
||||
TypeOrValue = Other.TypeOrValue;
|
||||
}
|
||||
|
||||
TemplateArgument& operator=(const TemplateArgument& Other) {
|
||||
// FIXME: Does not provide the strong guarantee for exception
|
||||
// safety.
|
||||
using llvm::APSInt;
|
||||
|
||||
// FIXME: Handle Packs
|
||||
assert(Kind != Pack && "FIXME: Handle packs");
|
||||
assert(Other.Kind != Pack && "FIXME: Handle packs");
|
||||
|
||||
if (Kind == Other.Kind && Kind == Integral) {
|
||||
// Copy integral values.
|
||||
*this->getAsIntegral() = *Other.getAsIntegral();
|
||||
Integer.Type = Other.Integer.Type;
|
||||
} else {
|
||||
// Destroy the current integral value, if that's what we're holding.
|
||||
if (Kind == Integral)
|
||||
getAsIntegral()->~APSInt();
|
||||
|
||||
Kind = Other.Kind;
|
||||
|
||||
if (Other.Kind == Integral) {
|
||||
new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
|
||||
Integer.Type = Other.Integer.Type;
|
||||
} else
|
||||
TypeOrValue = Other.TypeOrValue;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
~TemplateArgument() {
|
||||
using llvm::APSInt;
|
||||
|
||||
if (Kind == Integral)
|
||||
getAsIntegral()->~APSInt();
|
||||
else if (Kind == Pack && Args.CopyArgs)
|
||||
delete[] Args.Args;
|
||||
}
|
||||
|
||||
/// \brief Return the kind of stored template argument.
|
||||
ArgKind getKind() const { return Kind; }
|
||||
|
||||
/// \brief Determine whether this template argument has no value.
|
||||
bool isNull() const { return Kind == Null; }
|
||||
|
||||
/// \brief Retrieve the template argument as a type.
|
||||
QualType getAsType() const {
|
||||
if (Kind != Type)
|
||||
return QualType();
|
||||
|
||||
return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue));
|
||||
}
|
||||
|
||||
/// \brief Retrieve the template argument as a declaration.
|
||||
Decl *getAsDecl() const {
|
||||
if (Kind != Declaration)
|
||||
return 0;
|
||||
return reinterpret_cast<Decl *>(TypeOrValue);
|
||||
}
|
||||
|
||||
/// \brief Retrieve the template argument as an integral value.
|
||||
llvm::APSInt *getAsIntegral() {
|
||||
if (Kind != Integral)
|
||||
return 0;
|
||||
return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]);
|
||||
}
|
||||
|
||||
const llvm::APSInt *getAsIntegral() const {
|
||||
return const_cast<TemplateArgument*>(this)->getAsIntegral();
|
||||
}
|
||||
|
||||
/// \brief Retrieve the type of the integral value.
|
||||
QualType getIntegralType() const {
|
||||
if (Kind != Integral)
|
||||
return QualType();
|
||||
|
||||
return QualType::getFromOpaquePtr(Integer.Type);
|
||||
}
|
||||
|
||||
void setIntegralType(QualType T) {
|
||||
assert(Kind == Integral &&
|
||||
"Cannot set the integral type of a non-integral template argument");
|
||||
Integer.Type = T.getAsOpaquePtr();
|
||||
};
|
||||
|
||||
/// \brief Retrieve the template argument as an expression.
|
||||
Expr *getAsExpr() const {
|
||||
if (Kind != Expression)
|
||||
return 0;
|
||||
|
||||
return reinterpret_cast<Expr *>(TypeOrValue);
|
||||
}
|
||||
|
||||
/// \brief Iterator that traverses the elements of a template argument pack.
|
||||
typedef const TemplateArgument * pack_iterator;
|
||||
|
||||
/// \brief Iterator referencing the first argument of a template argument
|
||||
/// pack.
|
||||
pack_iterator pack_begin() const {
|
||||
assert(Kind == Pack);
|
||||
return Args.Args;
|
||||
}
|
||||
|
||||
/// \brief Iterator referencing one past the last argument of a template
|
||||
/// argument pack.
|
||||
pack_iterator pack_end() const {
|
||||
assert(Kind == Pack);
|
||||
return Args.Args + Args.NumArgs;
|
||||
}
|
||||
|
||||
/// \brief The number of template arguments in the given template argument
|
||||
/// pack.
|
||||
unsigned pack_size() const {
|
||||
assert(Kind == Pack);
|
||||
return Args.NumArgs;
|
||||
}
|
||||
|
||||
/// \brief Construct a template argument pack.
|
||||
void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs);
|
||||
|
||||
/// \brief Used to insert TemplateArguments into FoldingSets.
|
||||
void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context) const;
|
||||
};
|
||||
|
||||
/// Location information for a TemplateArgument.
|
||||
struct TemplateArgumentLocInfo {
|
||||
private:
|
||||
union {
|
||||
Expr *Expression;
|
||||
DeclaratorInfo *Declarator;
|
||||
};
|
||||
|
||||
#ifndef NDEBUG
|
||||
enum Kind {
|
||||
K_None,
|
||||
K_DeclaratorInfo,
|
||||
K_Expression
|
||||
} Kind;
|
||||
#endif
|
||||
|
||||
public:
|
||||
TemplateArgumentLocInfo()
|
||||
: Expression(0)
|
||||
#ifndef NDEBUG
|
||||
, Kind(K_None)
|
||||
#endif
|
||||
{}
|
||||
|
||||
TemplateArgumentLocInfo(DeclaratorInfo *DInfo)
|
||||
: Declarator(DInfo)
|
||||
#ifndef NDEBUG
|
||||
, Kind(K_DeclaratorInfo)
|
||||
#endif
|
||||
{}
|
||||
|
||||
TemplateArgumentLocInfo(Expr *E)
|
||||
: Expression(E)
|
||||
#ifndef NDEBUG
|
||||
, Kind(K_Expression)
|
||||
#endif
|
||||
{}
|
||||
|
||||
DeclaratorInfo *getAsDeclaratorInfo() const {
|
||||
assert(Kind == K_DeclaratorInfo);
|
||||
return Declarator;
|
||||
}
|
||||
|
||||
Expr *getAsExpr() const {
|
||||
assert(Kind == K_Expression);
|
||||
return Expression;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void validateForArgument(const TemplateArgument &Arg) {
|
||||
switch (Arg.getKind()) {
|
||||
case TemplateArgument::Type:
|
||||
assert(Kind == K_DeclaratorInfo);
|
||||
break;
|
||||
case TemplateArgument::Expression:
|
||||
case TemplateArgument::Declaration:
|
||||
assert(Kind == K_Expression);
|
||||
break;
|
||||
case TemplateArgument::Integral:
|
||||
case TemplateArgument::Pack:
|
||||
assert(Kind == K_None);
|
||||
break;
|
||||
case TemplateArgument::Null:
|
||||
llvm::llvm_unreachable("source info for null template argument?");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
/// Location wrapper for a TemplateArgument. TemplateArgument is to
|
||||
/// TemplateArgumentLoc as Type is to TypeLoc.
|
||||
class TemplateArgumentLoc {
|
||||
TemplateArgument Argument;
|
||||
TemplateArgumentLocInfo LocInfo;
|
||||
|
||||
public:
|
||||
TemplateArgumentLoc() {}
|
||||
|
||||
TemplateArgumentLoc(const TemplateArgument &Argument,
|
||||
TemplateArgumentLocInfo Opaque)
|
||||
: Argument(Argument), LocInfo(Opaque) {
|
||||
}
|
||||
|
||||
TemplateArgumentLoc(const TemplateArgument &Argument, DeclaratorInfo *DInfo)
|
||||
: Argument(Argument), LocInfo(DInfo) {
|
||||
assert(Argument.getKind() == TemplateArgument::Type);
|
||||
}
|
||||
|
||||
TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E)
|
||||
: Argument(Argument), LocInfo(E) {
|
||||
assert(Argument.getKind() == TemplateArgument::Expression);
|
||||
}
|
||||
|
||||
/// \brief - Fetches the start location of the argument.
|
||||
SourceLocation getLocation() const {
|
||||
return getSourceRange().getBegin();
|
||||
}
|
||||
|
||||
/// \brief - Fetches the full source range of the argument.
|
||||
SourceRange getSourceRange() const;
|
||||
|
||||
const TemplateArgument &getArgument() const {
|
||||
return Argument;
|
||||
}
|
||||
|
||||
TemplateArgumentLocInfo getLocInfo() const {
|
||||
return LocInfo;
|
||||
}
|
||||
|
||||
DeclaratorInfo *getSourceDeclaratorInfo() const {
|
||||
assert(Argument.getKind() == TemplateArgument::Type);
|
||||
return LocInfo.getAsDeclaratorInfo();
|
||||
}
|
||||
|
||||
Expr *getSourceExpression() const {
|
||||
assert(Argument.getKind() == TemplateArgument::Expression);
|
||||
return LocInfo.getAsExpr();
|
||||
}
|
||||
|
||||
Expr *getSourceDeclExpression() const {
|
||||
assert(Argument.getKind() == TemplateArgument::Declaration);
|
||||
return LocInfo.getAsExpr();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/ADT/PointerUnion.h"
|
||||
#include "clang/Basic/OperatorKinds.h"
|
||||
|
||||
namespace llvm {
|
||||
class raw_ostream;
|
||||
@ -224,10 +225,24 @@ class QualifiedTemplateName : public llvm::FoldingSetNode {
|
||||
class DependentTemplateName : public llvm::FoldingSetNode {
|
||||
/// \brief The nested name specifier that qualifies the template
|
||||
/// name.
|
||||
NestedNameSpecifier *Qualifier;
|
||||
///
|
||||
/// The bit stored in this qualifier describes whether the \c Name field
|
||||
/// is interpreted as an IdentifierInfo pointer (when clear) or as an
|
||||
/// overloaded operator kind (when set).
|
||||
llvm::PointerIntPair<NestedNameSpecifier *, 1, bool> Qualifier;
|
||||
|
||||
/// \brief The dependent template name.
|
||||
const IdentifierInfo *Name;
|
||||
union {
|
||||
/// \brief The identifier template name.
|
||||
///
|
||||
/// Only valid when the bit on \c Qualifier is clear.
|
||||
const IdentifierInfo *Identifier;
|
||||
|
||||
/// \brief The overloaded operator name.
|
||||
///
|
||||
/// Only valid when the bit on \c Qualifier is set.
|
||||
OverloadedOperatorKind Operator;
|
||||
};
|
||||
|
||||
/// \brief The canonical template name to which this dependent
|
||||
/// template name refers.
|
||||
@ -240,30 +255,70 @@ class DependentTemplateName : public llvm::FoldingSetNode {
|
||||
friend class ASTContext;
|
||||
|
||||
DependentTemplateName(NestedNameSpecifier *Qualifier,
|
||||
const IdentifierInfo *Name)
|
||||
: Qualifier(Qualifier), Name(Name), CanonicalTemplateName(this) { }
|
||||
const IdentifierInfo *Identifier)
|
||||
: Qualifier(Qualifier, false), Identifier(Identifier),
|
||||
CanonicalTemplateName(this) { }
|
||||
|
||||
DependentTemplateName(NestedNameSpecifier *Qualifier,
|
||||
const IdentifierInfo *Name,
|
||||
const IdentifierInfo *Identifier,
|
||||
TemplateName Canon)
|
||||
: Qualifier(Qualifier), Name(Name), CanonicalTemplateName(Canon) { }
|
||||
: Qualifier(Qualifier, false), Identifier(Identifier),
|
||||
CanonicalTemplateName(Canon) { }
|
||||
|
||||
DependentTemplateName(NestedNameSpecifier *Qualifier,
|
||||
OverloadedOperatorKind Operator)
|
||||
: Qualifier(Qualifier, true), Operator(Operator),
|
||||
CanonicalTemplateName(this) { }
|
||||
|
||||
DependentTemplateName(NestedNameSpecifier *Qualifier,
|
||||
OverloadedOperatorKind Operator,
|
||||
TemplateName Canon)
|
||||
: Qualifier(Qualifier, true), Operator(Operator),
|
||||
CanonicalTemplateName(Canon) { }
|
||||
|
||||
public:
|
||||
/// \brief Return the nested name specifier that qualifies this name.
|
||||
NestedNameSpecifier *getQualifier() const { return Qualifier; }
|
||||
NestedNameSpecifier *getQualifier() const { return Qualifier.getPointer(); }
|
||||
|
||||
/// \brief Return the name to which this dependent template name
|
||||
/// refers.
|
||||
const IdentifierInfo *getName() const { return Name; }
|
||||
/// \brief Determine whether this template name refers to an identifier.
|
||||
bool isIdentifier() const { return !Qualifier.getInt(); }
|
||||
|
||||
/// \brief Returns the identifier to which this template name refers.
|
||||
const IdentifierInfo *getIdentifier() const {
|
||||
assert(isIdentifier() && "Template name isn't an identifier?");
|
||||
return Identifier;
|
||||
}
|
||||
|
||||
/// \brief Determine whether this template name refers to an overloaded
|
||||
/// operator.
|
||||
bool isOverloadedOperator() const { return Qualifier.getInt(); }
|
||||
|
||||
/// \brief Return the overloaded operator to which this template name refers.
|
||||
OverloadedOperatorKind getOperator() const {
|
||||
assert(isOverloadedOperator() &&
|
||||
"Template name isn't an overloaded operator?");
|
||||
return Operator;
|
||||
}
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
Profile(ID, getQualifier(), getName());
|
||||
if (isIdentifier())
|
||||
Profile(ID, getQualifier(), getIdentifier());
|
||||
else
|
||||
Profile(ID, getQualifier(), getOperator());
|
||||
}
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
|
||||
const IdentifierInfo *Name) {
|
||||
const IdentifierInfo *Identifier) {
|
||||
ID.AddPointer(NNS);
|
||||
ID.AddPointer(Name);
|
||||
ID.AddBoolean(false);
|
||||
ID.AddPointer(Identifier);
|
||||
}
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
|
||||
OverloadedOperatorKind Operator) {
|
||||
ID.AddPointer(NNS);
|
||||
ID.AddBoolean(true);
|
||||
ID.AddInteger(Operator);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -81,6 +81,7 @@ namespace clang {
|
||||
class SourceLocation;
|
||||
class StmtIteratorBase;
|
||||
class TemplateArgument;
|
||||
class TemplateArgumentLoc;
|
||||
class QualifiedNameType;
|
||||
struct PrintingPolicy;
|
||||
|
||||
@ -2275,12 +2276,19 @@ class TemplateSpecializationType
|
||||
static bool anyDependentTemplateArguments(const TemplateArgument *Args,
|
||||
unsigned NumArgs);
|
||||
|
||||
static bool anyDependentTemplateArguments(const TemplateArgumentLoc *Args,
|
||||
unsigned NumArgs);
|
||||
|
||||
/// \brief Print a template argument list, including the '<' and '>'
|
||||
/// enclosing the template arguments.
|
||||
static std::string PrintTemplateArgumentList(const TemplateArgument *Args,
|
||||
unsigned NumArgs,
|
||||
const PrintingPolicy &Policy);
|
||||
|
||||
static std::string PrintTemplateArgumentList(const TemplateArgumentLoc *Args,
|
||||
unsigned NumArgs,
|
||||
const PrintingPolicy &Policy);
|
||||
|
||||
typedef const TemplateArgument * iterator;
|
||||
|
||||
iterator begin() const { return getArgs(); }
|
||||
|
@ -15,6 +15,7 @@
|
||||
#define LLVM_CLANG_AST_TYPELOC_H
|
||||
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/AST/TemplateBase.h"
|
||||
|
||||
namespace clang {
|
||||
class ParmVarDecl;
|
||||
@ -82,6 +83,19 @@ class TypeLoc {
|
||||
return Data;
|
||||
}
|
||||
|
||||
/// \brief Get the full source range.
|
||||
SourceRange getFullSourceRange() const {
|
||||
SourceLocation End = getSourceRange().getEnd();
|
||||
TypeLoc Cur = *this;
|
||||
while (true) {
|
||||
TypeLoc Next = Cur.getNextTypeLoc();
|
||||
if (Next.isNull()) break;
|
||||
Cur = Next;
|
||||
}
|
||||
return SourceRange(Cur.getSourceRange().getBegin(), End);
|
||||
}
|
||||
|
||||
/// \brief Get the local source range.
|
||||
SourceRange getSourceRange() const {
|
||||
return getSourceRangeImpl(*this);
|
||||
}
|
||||
@ -761,6 +775,10 @@ class ArrayTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
|
||||
getLocalData()->RBracketLoc = Loc;
|
||||
}
|
||||
|
||||
SourceRange getBracketsRange() const {
|
||||
return SourceRange(getLBracketLoc(), getRBracketLoc());
|
||||
}
|
||||
|
||||
Expr *getSizeExpr() const {
|
||||
return getLocalData()->Size;
|
||||
}
|
||||
@ -810,6 +828,118 @@ class VariableArrayTypeLoc :
|
||||
VariableArrayType> {
|
||||
};
|
||||
|
||||
|
||||
// Location information for a TemplateName. Rudimentary for now.
|
||||
struct TemplateNameLocInfo {
|
||||
SourceLocation NameLoc;
|
||||
};
|
||||
|
||||
struct TemplateSpecializationLocInfo : TemplateNameLocInfo {
|
||||
SourceLocation LAngleLoc;
|
||||
SourceLocation RAngleLoc;
|
||||
};
|
||||
|
||||
class TemplateSpecializationTypeLoc :
|
||||
public ConcreteTypeLoc<UnqualTypeLoc,
|
||||
TemplateSpecializationTypeLoc,
|
||||
TemplateSpecializationType,
|
||||
TemplateSpecializationLocInfo> {
|
||||
public:
|
||||
SourceLocation getLAngleLoc() const {
|
||||
return getLocalData()->LAngleLoc;
|
||||
}
|
||||
void setLAngleLoc(SourceLocation Loc) {
|
||||
getLocalData()->LAngleLoc = Loc;
|
||||
}
|
||||
|
||||
SourceLocation getRAngleLoc() const {
|
||||
return getLocalData()->RAngleLoc;
|
||||
}
|
||||
void setRAngleLoc(SourceLocation Loc) {
|
||||
getLocalData()->RAngleLoc = Loc;
|
||||
}
|
||||
|
||||
unsigned getNumArgs() const {
|
||||
return getTypePtr()->getNumArgs();
|
||||
}
|
||||
void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) {
|
||||
#ifndef NDEBUG
|
||||
AI.validateForArgument(getTypePtr()->getArg(i));
|
||||
#endif
|
||||
getArgInfos()[i] = AI;
|
||||
}
|
||||
TemplateArgumentLocInfo getArgLocInfo(unsigned i) const {
|
||||
return getArgInfos()[i];
|
||||
}
|
||||
|
||||
TemplateArgumentLoc getArgLoc(unsigned i) const {
|
||||
return TemplateArgumentLoc(getTypePtr()->getArg(i), getArgLocInfo(i));
|
||||
}
|
||||
|
||||
SourceLocation getTemplateNameLoc() const {
|
||||
return getLocalData()->NameLoc;
|
||||
}
|
||||
void setTemplateNameLoc(SourceLocation Loc) {
|
||||
getLocalData()->NameLoc = Loc;
|
||||
}
|
||||
|
||||
/// \brief - Copy the location information from the given info.
|
||||
void copy(TemplateSpecializationTypeLoc Loc) {
|
||||
unsigned size = getFullDataSize();
|
||||
assert(size == Loc.getFullDataSize());
|
||||
|
||||
// We're potentially copying Expr references here. We don't
|
||||
// bother retaining them because DeclaratorInfos live forever, so
|
||||
// as long as the Expr was retained when originally written into
|
||||
// the TypeLoc, we're okay.
|
||||
memcpy(Data, Loc.Data, size);
|
||||
}
|
||||
|
||||
SourceRange getSourceRange() const {
|
||||
return SourceRange(getTemplateNameLoc(), getRAngleLoc());
|
||||
}
|
||||
|
||||
void initializeLocal(SourceLocation Loc) {
|
||||
setLAngleLoc(Loc);
|
||||
setRAngleLoc(Loc);
|
||||
setTemplateNameLoc(Loc);
|
||||
|
||||
for (unsigned i = 0, e = getNumArgs(); i != e; ++i) {
|
||||
TemplateArgumentLocInfo Info;
|
||||
#ifndef NDEBUG
|
||||
// If asserts are enabled, be sure to initialize the argument
|
||||
// loc with the right kind of pointer.
|
||||
switch (getTypePtr()->getArg(i).getKind()) {
|
||||
case TemplateArgument::Expression:
|
||||
case TemplateArgument::Declaration:
|
||||
Info = TemplateArgumentLocInfo((Expr*) 0);
|
||||
break;
|
||||
|
||||
case TemplateArgument::Type:
|
||||
Info = TemplateArgumentLocInfo((DeclaratorInfo*) 0);
|
||||
break;
|
||||
|
||||
case TemplateArgument::Integral:
|
||||
case TemplateArgument::Pack:
|
||||
case TemplateArgument::Null:
|
||||
// K_None is fine.
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
getArgInfos()[i] = Info;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned getExtraLocalDataSize() const {
|
||||
return getNumArgs() * sizeof(TemplateArgumentLocInfo);
|
||||
}
|
||||
|
||||
private:
|
||||
TemplateArgumentLocInfo *getArgInfos() const {
|
||||
return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData());
|
||||
}
|
||||
};
|
||||
|
||||
// None of these types have proper implementations yet.
|
||||
|
||||
class VectorTypeLoc : public TypeSpecTypeLoc<VectorTypeLoc, VectorType> {
|
||||
@ -861,11 +991,6 @@ class ElaboratedTypeLoc : public TypeSpecTypeLoc<ElaboratedTypeLoc,
|
||||
ElaboratedType> {
|
||||
};
|
||||
|
||||
class TemplateSpecializationTypeLoc
|
||||
: public TypeSpecTypeLoc<TemplateSpecializationTypeLoc,
|
||||
TemplateSpecializationType> {
|
||||
};
|
||||
|
||||
class QualifiedNameTypeLoc : public TypeSpecTypeLoc<QualifiedNameTypeLoc,
|
||||
QualifiedNameType> {
|
||||
};
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include "clang/Index/ASTLocation.h"
|
||||
#include "clang/Index/Entity.h"
|
||||
#include "clang/Index/Program.h"
|
||||
#include "clang/Frontend/ASTUnit.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/GraphTraits.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
@ -87,7 +86,7 @@ class CallGraph {
|
||||
|
||||
CallGraphNode *getExternalCallingNode() { return ExternalCallingNode; }
|
||||
|
||||
void addTU(ASTUnit &AST);
|
||||
void addTU(ASTContext &AST);
|
||||
|
||||
idx::Program &getProgram() { return Prog; }
|
||||
|
||||
|
@ -80,6 +80,8 @@ class LocationContext : public llvm::FoldingSetNode {
|
||||
: Kind(k), Ctx(ctx), Parent(parent) {}
|
||||
|
||||
public:
|
||||
virtual ~LocationContext() {}
|
||||
|
||||
ContextKind getKind() const { return Kind; }
|
||||
|
||||
AnalysisContext *getAnalysisContext() const { return Ctx; }
|
||||
@ -102,7 +104,7 @@ class LocationContext : public llvm::FoldingSetNode {
|
||||
return Ctx->getSelfDecl();
|
||||
}
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
virtual void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
Profile(ID, Kind, Ctx, Parent);
|
||||
}
|
||||
|
||||
@ -119,10 +121,13 @@ class StackFrameContext : public LocationContext {
|
||||
StackFrameContext(AnalysisContext *ctx, const LocationContext *parent,
|
||||
const Stmt *s)
|
||||
: LocationContext(StackFrame, ctx, parent), CallSite(s) {}
|
||||
|
||||
virtual ~StackFrameContext() {}
|
||||
|
||||
|
||||
Stmt const *getCallSite() const { return CallSite; }
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
virtual void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
Profile(ID, getAnalysisContext(), getParent(), CallSite);
|
||||
}
|
||||
|
||||
@ -141,8 +146,10 @@ class ScopeContext : public LocationContext {
|
||||
ScopeContext(AnalysisContext *ctx, const LocationContext *parent,
|
||||
const Stmt *s)
|
||||
: LocationContext(Scope, ctx, parent), Enter(s) {}
|
||||
|
||||
virtual ~ScopeContext() {}
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
virtual void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
Profile(ID, getAnalysisContext(), getParent(), Enter);
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "clang/Analysis/PathSensitive/GRState.h"
|
||||
#include "clang/Analysis/PathSensitive/ExplodedGraph.h"
|
||||
#include "clang/Analysis/PathSensitive/BugType.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/SmallSet.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
@ -183,38 +184,6 @@ class BugReportEquivClass : public llvm::FoldingSetNode {
|
||||
const_iterator end() const { return const_iterator(Reports.end()); }
|
||||
};
|
||||
|
||||
class BugType {
|
||||
private:
|
||||
const std::string Name;
|
||||
const std::string Category;
|
||||
llvm::FoldingSet<BugReportEquivClass> EQClasses;
|
||||
friend class BugReporter;
|
||||
bool SuppressonSink;
|
||||
public:
|
||||
BugType(const char *name, const char* cat)
|
||||
: Name(name), Category(cat), SuppressonSink(false) {}
|
||||
virtual ~BugType();
|
||||
|
||||
// FIXME: Should these be made strings as well?
|
||||
const std::string& getName() const { return Name; }
|
||||
const std::string& getCategory() const { return Category; }
|
||||
|
||||
/// isSuppressOnSink - Returns true if bug reports associated with this bug
|
||||
/// type should be suppressed if the end node of the report is post-dominated
|
||||
/// by a sink node.
|
||||
bool isSuppressOnSink() const { return SuppressonSink; }
|
||||
void setSuppressOnSink(bool x) { SuppressonSink = x; }
|
||||
|
||||
virtual void FlushReports(BugReporter& BR);
|
||||
|
||||
typedef llvm::FoldingSet<BugReportEquivClass>::iterator iterator;
|
||||
iterator begin() { return EQClasses.begin(); }
|
||||
iterator end() { return EQClasses.end(); }
|
||||
|
||||
typedef llvm::FoldingSet<BugReportEquivClass>::const_iterator const_iterator;
|
||||
const_iterator begin() const { return EQClasses.begin(); }
|
||||
const_iterator end() const { return EQClasses.end(); }
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Specialized subclasses of BugReport.
|
||||
|
86
include/clang/Analysis/PathSensitive/BugType.h
Normal file
86
include/clang/Analysis/PathSensitive/BugType.h
Normal file
@ -0,0 +1,86 @@
|
||||
//===--- BugType.h - Bug Information Desciption ----------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines BugType, a class representing a bug type.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_ANALYSIS_BUGTYPE
|
||||
#define LLVM_CLANG_ANALYSIS_BUGTYPE
|
||||
|
||||
#include <llvm/ADT/FoldingSet.h>
|
||||
#include <string>
|
||||
|
||||
namespace clang {
|
||||
|
||||
class BugReportEquivClass;
|
||||
class BugReporter;
|
||||
class BuiltinBugReport;
|
||||
class BugReporterContext;
|
||||
class GRExprEngine;
|
||||
|
||||
class BugType {
|
||||
private:
|
||||
const std::string Name;
|
||||
const std::string Category;
|
||||
llvm::FoldingSet<BugReportEquivClass> EQClasses;
|
||||
friend class BugReporter;
|
||||
bool SuppressonSink;
|
||||
public:
|
||||
BugType(const char *name, const char* cat)
|
||||
: Name(name), Category(cat), SuppressonSink(false) {}
|
||||
virtual ~BugType();
|
||||
|
||||
// FIXME: Should these be made strings as well?
|
||||
const std::string& getName() const { return Name; }
|
||||
const std::string& getCategory() const { return Category; }
|
||||
|
||||
/// isSuppressOnSink - Returns true if bug reports associated with this bug
|
||||
/// type should be suppressed if the end node of the report is post-dominated
|
||||
/// by a sink node.
|
||||
bool isSuppressOnSink() const { return SuppressonSink; }
|
||||
void setSuppressOnSink(bool x) { SuppressonSink = x; }
|
||||
|
||||
virtual void FlushReports(BugReporter& BR);
|
||||
|
||||
typedef llvm::FoldingSet<BugReportEquivClass>::iterator iterator;
|
||||
iterator begin() { return EQClasses.begin(); }
|
||||
iterator end() { return EQClasses.end(); }
|
||||
|
||||
typedef llvm::FoldingSet<BugReportEquivClass>::const_iterator const_iterator;
|
||||
const_iterator begin() const { return EQClasses.begin(); }
|
||||
const_iterator end() const { return EQClasses.end(); }
|
||||
};
|
||||
|
||||
class BuiltinBug : public BugType {
|
||||
GRExprEngine &Eng;
|
||||
protected:
|
||||
const std::string desc;
|
||||
public:
|
||||
BuiltinBug(GRExprEngine *eng, const char* n, const char* d)
|
||||
: BugType(n, "Logic errors"), Eng(*eng), desc(d) {}
|
||||
|
||||
BuiltinBug(GRExprEngine *eng, const char* n)
|
||||
: BugType(n, "Logic errors"), 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); }
|
||||
|
||||
virtual void registerInitialVisitors(BugReporterContext& BRC,
|
||||
const ExplodedNode* N,
|
||||
BuiltinBugReport *R) {}
|
||||
|
||||
template <typename ITER> void Emit(BugReporter& BR, ITER I, ITER E);
|
||||
};
|
||||
|
||||
} // end clang namespace
|
||||
#endif
|
@ -72,6 +72,10 @@ class CheckerContext {
|
||||
ASTContext &getASTContext() {
|
||||
return Eng.getContext();
|
||||
}
|
||||
|
||||
BugReporter &getBugReporter() {
|
||||
return Eng.getBugReporter();
|
||||
}
|
||||
|
||||
ExplodedNode *GenerateNode(const Stmt *S, bool markAsSink = false) {
|
||||
return GenerateNode(S, getState(), markAsSink);
|
||||
@ -104,16 +108,42 @@ class Checker {
|
||||
GRStmtNodeBuilder &Builder,
|
||||
GRExprEngine &Eng,
|
||||
const Stmt *stmt,
|
||||
ExplodedNode *Pred, bool isPrevisit) {
|
||||
CheckerContext C(Dst, Builder, Eng, Pred, getTag(), isPrevisit);
|
||||
ExplodedNode *Pred, void *tag, bool isPrevisit) {
|
||||
CheckerContext C(Dst, Builder, Eng, Pred, tag, isPrevisit);
|
||||
assert(isPrevisit && "Only previsit supported for now.");
|
||||
_PreVisit(C, stmt);
|
||||
}
|
||||
|
||||
void GR_VisitBind(ExplodedNodeSet &Dst,
|
||||
GRStmtNodeBuilder &Builder, GRExprEngine &Eng,
|
||||
const Stmt *stmt, ExplodedNode *Pred, void *tag,
|
||||
SVal location, SVal val,
|
||||
bool isPrevisit) {
|
||||
CheckerContext C(Dst, Builder, Eng, Pred, tag, isPrevisit);
|
||||
assert(isPrevisit && "Only previsit supported for now.");
|
||||
PreVisitBind(C, stmt, location, val);
|
||||
}
|
||||
|
||||
public:
|
||||
virtual ~Checker() {}
|
||||
virtual void _PreVisit(CheckerContext &C, const Stmt *stmt) = 0;
|
||||
virtual const void *getTag() = 0;
|
||||
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 *ST,
|
||||
SVal location, SVal val) {}
|
||||
|
||||
virtual ExplodedNode *CheckType(QualType T, ExplodedNode *Pred,
|
||||
const GRState *state, Stmt *S,
|
||||
GRExprEngine &Eng) {
|
||||
return Pred;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // end clang namespace
|
||||
|
@ -0,0 +1,28 @@
|
||||
//===--- AttrNonNullChecker.h - Undefined arguments checker ----*- C++ -*--===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This defines AttrNonNullChecker, a builtin check in GRExprEngine that
|
||||
// performs checks for arguments declared to have nonnull attribute.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
class AttrNonNullChecker : public CheckerVisitor<AttrNonNullChecker> {
|
||||
BugType *BT;
|
||||
|
||||
public:
|
||||
AttrNonNullChecker() : BT(0) {}
|
||||
static void *getTag();
|
||||
void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
|
||||
};
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
//===--- BadCallChecker.h - Bad call checker --------------------*- C++ -*--==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This defines BadCallChecker, a builtin check in GRExprEngine that performs
|
||||
// checks for bad callee at call sites.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
class BadCallChecker : public CheckerVisitor<BadCallChecker> {
|
||||
BuiltinBug *BT;
|
||||
|
||||
public:
|
||||
BadCallChecker() : BT(0) {}
|
||||
|
||||
static void *getTag();
|
||||
|
||||
void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
|
||||
};
|
||||
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
//== NullDerefChecker.h - Null dereference checker --------------*- C++ -*--==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This defines NullDerefChecker and UndefDerefChecker, two builtin checks
|
||||
// in GRExprEngine that check for null and undefined pointers at loads
|
||||
// and stores.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_DEREFCHECKER
|
||||
#define LLVM_CLANG_DEREFCHECKER
|
||||
|
||||
#include "clang/Analysis/PathSensitive/Checker.h"
|
||||
#include "clang/Analysis/PathSensitive/BugType.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
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();
|
||||
};
|
||||
|
||||
} // end clang namespace
|
||||
#endif
|
@ -0,0 +1,28 @@
|
||||
//== DivZeroChecker.h - Division by zero checker ----------------*- C++ -*--==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This defines DivZeroChecker, a builtin check in GRExprEngine that performs
|
||||
// checks for division by zeros.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
class DivZeroChecker : public CheckerVisitor<DivZeroChecker> {
|
||||
BuiltinBug *BT;
|
||||
public:
|
||||
DivZeroChecker() : BT(0) {}
|
||||
|
||||
static void *getTag();
|
||||
void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
|
||||
};
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
//===--- UndefinedArgChecker.h - Undefined arguments checker ----*- C++ -*--==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This defines BadCallChecker, a builtin check in GRExprEngine that performs
|
||||
// checks for undefined arguments.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_UNDEFARGCHECKER
|
||||
#define LLVM_CLANG_UNDEFARGCHECKER
|
||||
|
||||
#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
class UndefinedArgChecker : public CheckerVisitor<UndefinedArgChecker> {
|
||||
BugType *BT;
|
||||
|
||||
public:
|
||||
UndefinedArgChecker() : BT(0) {}
|
||||
|
||||
static void *getTag();
|
||||
|
||||
void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
@ -0,0 +1,32 @@
|
||||
//===--- UndefinedAssignmentChecker.h ---------------------------*- C++ -*--==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This defines UndefinedAssginmentChecker, a builtin check in GRExprEngine that
|
||||
// checks for assigning undefined values.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_UNDEFASSIGNMENTCHECKER
|
||||
#define LLVM_CLANG_UNDEFASSIGNMENTCHECKER
|
||||
|
||||
#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
|
||||
|
||||
namespace clang {
|
||||
class UndefinedAssignmentChecker
|
||||
: public CheckerVisitor<UndefinedAssignmentChecker> {
|
||||
BugType *BT;
|
||||
public:
|
||||
UndefinedAssignmentChecker() : BT(0) {}
|
||||
static void *getTag();
|
||||
virtual void PreVisitBind(CheckerContext &C, const Stmt *S, SVal location,
|
||||
SVal val);
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
@ -0,0 +1,39 @@
|
||||
//=== VLASizeChecker.h - Undefined dereference checker ----------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This defines two VLASizeCheckers, a builtin check in GRExprEngine that
|
||||
// performs checks for declaration of VLA of undefined or zero size.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Analysis/PathSensitive/Checker.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
class UndefSizedVLAChecker : public Checker {
|
||||
BugType *BT;
|
||||
|
||||
public:
|
||||
UndefSizedVLAChecker() : BT(0) {}
|
||||
static void *getTag();
|
||||
ExplodedNode *CheckType(QualType T, ExplodedNode *Pred,
|
||||
const GRState *state, Stmt *S, GRExprEngine &Eng);
|
||||
};
|
||||
|
||||
class ZeroSizedVLAChecker : public Checker {
|
||||
BugType *BT;
|
||||
|
||||
public:
|
||||
ZeroSizedVLAChecker() : BT(0) {}
|
||||
static void *getTag();
|
||||
ExplodedNode *CheckType(QualType T, ExplodedNode *Pred,
|
||||
const GRState *state, Stmt *S, GRExprEngine &Eng);
|
||||
};
|
||||
|
||||
}
|
@ -75,7 +75,12 @@ class GRExprEngine : public GRSubEngine {
|
||||
Selector RaiseSel;
|
||||
|
||||
llvm::OwningPtr<GRSimpleAPICheck> BatchAuditor;
|
||||
std::vector<Checker*> Checkers;
|
||||
|
||||
typedef llvm::DenseMap<void *, unsigned> CheckerMap;
|
||||
CheckerMap CheckerM;
|
||||
|
||||
typedef std::vector<std::pair<void *, Checker*> >CheckersOrdered;
|
||||
CheckersOrdered Checkers;
|
||||
|
||||
/// BR - The BugReporter associated with this engine. It is important that
|
||||
// this object be placed at the very end of member variables so that its
|
||||
@ -126,18 +131,6 @@ class GRExprEngine : public GRSubEngine {
|
||||
// calling a function with the attribute "noreturn".
|
||||
ErrorNodes NoReturnCalls;
|
||||
|
||||
/// ImplicitNullDeref - Nodes in the ExplodedGraph that result from
|
||||
/// taking a dereference on a symbolic pointer that MAY be NULL.
|
||||
ErrorNodes ImplicitNullDeref;
|
||||
|
||||
/// ExplicitNullDeref - Nodes in the ExplodedGraph that result from
|
||||
/// taking a dereference on a symbolic pointer that MUST be NULL.
|
||||
ErrorNodes ExplicitNullDeref;
|
||||
|
||||
/// UndefDeref - Nodes in the ExplodedGraph that result from
|
||||
/// taking a dereference on an undefined value.
|
||||
ErrorNodes UndefDeref;
|
||||
|
||||
/// ImplicitBadSizedVLA - Nodes in the ExplodedGraph that result from
|
||||
/// constructing a zero-sized VLA where the size may be zero.
|
||||
ErrorNodes ImplicitBadSizedVLA;
|
||||
@ -158,10 +151,6 @@ class GRExprEngine : public GRSubEngine {
|
||||
/// ObjC message expressions where the receiver is undefined (uninitialized).
|
||||
ErrorNodes UndefReceivers;
|
||||
|
||||
/// UndefArg - Nodes in the ExplodedGraph resulting from calls to functions
|
||||
/// where a pass-by-value argument has an undefined value.
|
||||
UndefArgsTy UndefArgs;
|
||||
|
||||
/// MsgExprUndefArgs - Nodes in the ExplodedGraph resulting from
|
||||
/// message expressions where a pass-by-value argument has an undefined
|
||||
/// value.
|
||||
@ -195,6 +184,8 @@ class GRExprEngine : public GRSubEngine {
|
||||
|
||||
BugReporter& getBugReporter() { return BR; }
|
||||
|
||||
GRStmtNodeBuilder &getBuilder() { assert(Builder); return *Builder; }
|
||||
|
||||
/// setTransferFunctions
|
||||
void setTransferFunctions(GRTransferFuncs* tf);
|
||||
|
||||
@ -217,8 +208,19 @@ class GRExprEngine : public GRSubEngine {
|
||||
|
||||
void RegisterInternalChecks();
|
||||
|
||||
void registerCheck(Checker *check) {
|
||||
Checkers.push_back(check);
|
||||
template <typename CHECKER>
|
||||
void registerCheck(CHECKER *check) {
|
||||
unsigned entry = Checkers.size();
|
||||
void *tag = CHECKER::getTag();
|
||||
Checkers.push_back(std::make_pair(tag, check));
|
||||
CheckerM[tag] = entry;
|
||||
}
|
||||
|
||||
Checker *lookupChecker(void *tag) const;
|
||||
|
||||
template <typename CHECKER>
|
||||
CHECKER *getChecker() const {
|
||||
return static_cast<CHECKER*>(lookupChecker(CHECKER::getTag()));
|
||||
}
|
||||
|
||||
bool isRetStackAddr(const ExplodedNode* N) const {
|
||||
@ -234,15 +236,15 @@ class GRExprEngine : public GRSubEngine {
|
||||
}
|
||||
|
||||
bool isImplicitNullDeref(const ExplodedNode* N) const {
|
||||
return N->isSink() && ImplicitNullDeref.count(const_cast<ExplodedNode*>(N)) != 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isExplicitNullDeref(const ExplodedNode* N) const {
|
||||
return N->isSink() && ExplicitNullDeref.count(const_cast<ExplodedNode*>(N)) != 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isUndefDeref(const ExplodedNode* N) const {
|
||||
return N->isSink() && UndefDeref.count(const_cast<ExplodedNode*>(N)) != 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isNoReturnCall(const ExplodedNode* N) const {
|
||||
@ -254,13 +256,11 @@ class GRExprEngine : public GRSubEngine {
|
||||
}
|
||||
|
||||
bool isBadCall(const ExplodedNode* N) const {
|
||||
return N->isSink() && BadCalls.count(const_cast<ExplodedNode*>(N)) != 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isUndefArg(const ExplodedNode* N) const {
|
||||
return N->isSink() &&
|
||||
(UndefArgs.find(const_cast<ExplodedNode*>(N)) != UndefArgs.end() ||
|
||||
MsgExprUndefArgs.find(const_cast<ExplodedNode*>(N)) != MsgExprUndefArgs.end());
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isUndefReceiver(const ExplodedNode* N) const {
|
||||
@ -279,17 +279,6 @@ class GRExprEngine : public GRSubEngine {
|
||||
undef_branch_iterator undef_branches_begin() { return UndefBranches.begin(); }
|
||||
undef_branch_iterator undef_branches_end() { return UndefBranches.end(); }
|
||||
|
||||
typedef ErrorNodes::iterator null_deref_iterator;
|
||||
null_deref_iterator null_derefs_begin() { return ExplicitNullDeref.begin(); }
|
||||
null_deref_iterator null_derefs_end() { return ExplicitNullDeref.end(); }
|
||||
|
||||
null_deref_iterator implicit_null_derefs_begin() {
|
||||
return ImplicitNullDeref.begin();
|
||||
}
|
||||
null_deref_iterator implicit_null_derefs_end() {
|
||||
return ImplicitNullDeref.end();
|
||||
}
|
||||
|
||||
typedef ErrorNodes::iterator nil_receiver_struct_ret_iterator;
|
||||
|
||||
nil_receiver_struct_ret_iterator nil_receiver_struct_ret_begin() {
|
||||
@ -312,10 +301,6 @@ class GRExprEngine : public GRSubEngine {
|
||||
return NilReceiverLargerThanVoidPtrRetExplicit.end();
|
||||
}
|
||||
|
||||
typedef ErrorNodes::iterator undef_deref_iterator;
|
||||
undef_deref_iterator undef_derefs_begin() { return UndefDeref.begin(); }
|
||||
undef_deref_iterator undef_derefs_end() { return UndefDeref.end(); }
|
||||
|
||||
typedef ErrorNodes::iterator undef_result_iterator;
|
||||
undef_result_iterator undef_results_begin() { return UndefResults.begin(); }
|
||||
undef_result_iterator undef_results_end() { return UndefResults.end(); }
|
||||
@ -325,9 +310,6 @@ class GRExprEngine : public GRSubEngine {
|
||||
bad_calls_iterator bad_calls_end() { return BadCalls.end(); }
|
||||
|
||||
typedef UndefArgsTy::iterator undef_arg_iterator;
|
||||
undef_arg_iterator undef_arg_begin() { return UndefArgs.begin(); }
|
||||
undef_arg_iterator undef_arg_end() { return UndefArgs.end(); }
|
||||
|
||||
undef_arg_iterator msg_expr_undef_arg_begin() {
|
||||
return MsgExprUndefArgs.begin();
|
||||
}
|
||||
@ -427,7 +409,12 @@ class GRExprEngine : public GRSubEngine {
|
||||
protected:
|
||||
/// CheckerVisit - Dispatcher for performing checker-specific logic
|
||||
/// at specific statements.
|
||||
void CheckerVisit(Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src, bool isPrevisit);
|
||||
void CheckerVisit(Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
|
||||
bool isPrevisit);
|
||||
|
||||
void CheckerVisitBind(Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
|
||||
SVal location, SVal val, bool isPrevisit);
|
||||
|
||||
|
||||
/// Visit - Transfer function logic for all statements. Dispatches to
|
||||
/// other functions that handle specific kinds of statements.
|
||||
@ -456,7 +443,8 @@ class GRExprEngine : public GRSubEngine {
|
||||
ExplodedNode* Pred, ExplodedNodeSet& Dst);
|
||||
|
||||
/// VisitBinaryOperator - Transfer function logic for binary operators.
|
||||
void VisitBinaryOperator(BinaryOperator* B, ExplodedNode* Pred, ExplodedNodeSet& Dst);
|
||||
void VisitBinaryOperator(BinaryOperator* B, ExplodedNode* Pred,
|
||||
ExplodedNodeSet& Dst, bool asLValue);
|
||||
|
||||
|
||||
/// VisitCall - Transfer function for function calls.
|
||||
@ -578,8 +566,9 @@ class GRExprEngine : public GRSubEngine {
|
||||
|
||||
/// EvalBind - Handle the semantics of binding a value to a specific location.
|
||||
/// This method is used by EvalStore, VisitDeclStmt, and others.
|
||||
void EvalBind(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred,
|
||||
const GRState* St, SVal location, SVal Val);
|
||||
void EvalBind(ExplodedNodeSet& Dst, Stmt* Ex, ExplodedNode* Pred,
|
||||
const GRState* St, SVal location, SVal Val,
|
||||
bool atDeclInit = false);
|
||||
|
||||
public:
|
||||
void EvalLoad(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred,
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/Analysis/Analyses/LiveVariables.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/System/DataTypes.h"
|
||||
#include "llvm/ADT/APSInt.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/ADT/ImmutableMap.h"
|
||||
@ -219,11 +219,9 @@ class GRState : public llvm::FoldingSetNode {
|
||||
|
||||
const GRState *BindExpr(const Stmt *S, SVal V, bool Invalidate = true) const;
|
||||
|
||||
const GRState *bindDecl(const VarDecl *VD, const LocationContext *LC,
|
||||
SVal V) const;
|
||||
const GRState *bindDecl(const VarRegion *VR, SVal V) const;
|
||||
|
||||
const GRState *bindDeclWithNoInit(const VarDecl *VD,
|
||||
const LocationContext *LC) const;
|
||||
const GRState *bindDeclWithNoInit(const VarRegion *VR) const;
|
||||
|
||||
const GRState *bindLoc(Loc location, SVal V) const;
|
||||
|
||||
@ -602,15 +600,12 @@ inline const GRState *GRState::bindCompoundLiteral(const CompoundLiteralExpr* CL
|
||||
return getStateManager().StoreMgr->BindCompoundLiteral(this, CL, V);
|
||||
}
|
||||
|
||||
inline const GRState *GRState::bindDecl(const VarDecl* VD,
|
||||
const LocationContext *LC,
|
||||
SVal IVal) const {
|
||||
return getStateManager().StoreMgr->BindDecl(this, VD, LC, IVal);
|
||||
inline const GRState *GRState::bindDecl(const VarRegion* VR, SVal IVal) const {
|
||||
return getStateManager().StoreMgr->BindDecl(this, VR, IVal);
|
||||
}
|
||||
|
||||
inline const GRState *GRState::bindDeclWithNoInit(const VarDecl* VD,
|
||||
const LocationContext *LC) const {
|
||||
return getStateManager().StoreMgr->BindDeclWithNoInit(this, VD, LC);
|
||||
inline const GRState *GRState::bindDeclWithNoInit(const VarRegion* VR) const {
|
||||
return getStateManager().StoreMgr->BindDeclWithNoInit(this, VR);
|
||||
}
|
||||
|
||||
inline const GRState *GRState::bindLoc(Loc LV, SVal V) const {
|
||||
|
@ -23,7 +23,6 @@
|
||||
namespace clang {
|
||||
|
||||
class GRExprEngine;
|
||||
class BugReporter;
|
||||
class ObjCMessageExpr;
|
||||
class GRStmtNodeBuilderRef;
|
||||
|
||||
@ -33,7 +32,7 @@ class GRTransferFuncs {
|
||||
virtual ~GRTransferFuncs() {}
|
||||
|
||||
virtual void RegisterPrinters(std::vector<GRState::Printer*>& Printers) {}
|
||||
virtual void RegisterChecks(BugReporter& BR) {}
|
||||
virtual void RegisterChecks(GRExprEngine& Eng) {}
|
||||
|
||||
|
||||
// Calls.
|
||||
@ -78,7 +77,7 @@ class GRTransferFuncs {
|
||||
virtual const GRState* EvalAssume(const GRState *state,
|
||||
SVal Cond, bool Assumption) {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
GRTransferFuncs *CreateCallInliner(ASTContext &ctx);
|
||||
|
@ -134,12 +134,11 @@ class StoreManager {
|
||||
SymbolReaper& SymReaper,
|
||||
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots) = 0;
|
||||
|
||||
virtual const GRState *BindDecl(const GRState *ST, const VarDecl *VD,
|
||||
const LocationContext *LC, SVal initVal) = 0;
|
||||
virtual const GRState *BindDecl(const GRState *ST, const VarRegion *VR,
|
||||
SVal initVal) = 0;
|
||||
|
||||
virtual const GRState *BindDeclWithNoInit(const GRState *ST,
|
||||
const VarDecl *VD,
|
||||
const LocationContext *LC) = 0;
|
||||
const VarRegion *VR) = 0;
|
||||
|
||||
typedef llvm::DenseSet<SymbolRef> InvalidatedSymbols;
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/Analysis/Analyses/LiveVariables.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/System/DataTypes.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
|
@ -16,7 +16,7 @@
|
||||
#define LLVM_CLANG_ANALYSIS_PROGRAM_POINT
|
||||
|
||||
#include "clang/Analysis/CFG.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/System/DataTypes.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
|
@ -57,7 +57,6 @@ class CFGRecStmtDeclVisitor : public CFGRecStmtVisitor<ImplClass> {
|
||||
DISPATCH_CASE(Function,FunctionDecl)
|
||||
DISPATCH_CASE(Var,VarDecl)
|
||||
DISPATCH_CASE(ParmVar,ParmVarDecl) // FIXME: (same)
|
||||
DISPATCH_CASE(OriginalParmVar,OriginalParmVarDecl) // FIXME: (same)
|
||||
DISPATCH_CASE(ImplicitParam,ImplicitParamDecl)
|
||||
DISPATCH_CASE(EnumConstant,EnumConstantDecl)
|
||||
DISPATCH_CASE(Typedef,TypedefDecl)
|
||||
@ -70,7 +69,6 @@ class CFGRecStmtDeclVisitor : public CFGRecStmtVisitor<ImplClass> {
|
||||
|
||||
DEFAULT_DISPATCH(VarDecl)
|
||||
DEFAULT_DISPATCH(FunctionDecl)
|
||||
DEFAULT_DISPATCH_VARDECL(OriginalParmVarDecl)
|
||||
DEFAULT_DISPATCH_VARDECL(ParmVarDecl)
|
||||
DEFAULT_DISPATCH(ImplicitParamDecl)
|
||||
DEFAULT_DISPATCH(EnumConstantDecl)
|
||||
|
@ -329,7 +329,7 @@ BUILTIN(__builtin___printf_chk, "iicC*.", "Fp:1:")
|
||||
BUILTIN(__builtin___vfprintf_chk, "iP*icC*a", "FP:2:")
|
||||
BUILTIN(__builtin___vprintf_chk, "iicC*a", "FP:1:")
|
||||
|
||||
BUILTIN(__builtin_expect, "iii" , "nc")
|
||||
BUILTIN(__builtin_expect, "LiLiLi" , "nc")
|
||||
BUILTIN(__builtin_prefetch, "vvC*.", "nc")
|
||||
BUILTIN(__builtin_abort, "v", "Fnr")
|
||||
BUILTIN(__builtin_trap, "v", "nr")
|
||||
|
@ -52,8 +52,4 @@ def warn_integer_too_large_for_signed : Warning<
|
||||
def note_invalid_subexpr_in_ice : Note<
|
||||
"subexpression not valid in an integer constant expression">;
|
||||
|
||||
// clang-cc
|
||||
def err_pp_I_dash_not_supported : Error<
|
||||
"-I- not supported, please use -iquote instead">;
|
||||
|
||||
}
|
||||
|
@ -55,6 +55,8 @@ def err_drv_command_signalled : Error<
|
||||
"%0 command failed due to signal %1 (use -v to see invocation)">;
|
||||
def err_drv_invalid_mfloat_abi : Error<
|
||||
"invalid float ABI '%0'">;
|
||||
def err_drv_I_dash_not_supported : Error<
|
||||
"'%0' not supported, please use -iquote instead">;
|
||||
|
||||
def warn_drv_input_file_unused : Warning<
|
||||
"%0: '%1' input unused when '%2' is present">;
|
||||
|
@ -12,6 +12,7 @@ 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;
|
||||
@ -19,6 +20,8 @@ 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
|
||||
: 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 note_fixit_applied : Note<"FIX-IT applied suggested code changes">;
|
||||
def note_fixit_in_macro : Note<
|
||||
|
@ -194,7 +194,8 @@ def err_pp_expected_eol : Error<
|
||||
"expected end of line in preprocessor expression">;
|
||||
def err_pp_defined_requires_identifier : Error<
|
||||
"operator 'defined' requires an identifier">;
|
||||
def err_pp_missing_rparen : Error<"missing ')' after 'defined'">;
|
||||
def err_pp_missing_lparen : Error<"missing '(' after '%0'">;
|
||||
def err_pp_missing_rparen : Error<"missing ')' after '%0'">;
|
||||
def err_pp_colon_without_question : Error<"':' without preceding '?'">;
|
||||
def err_pp_division_by_zero : Error<
|
||||
"division by zero in preprocessor expression">;
|
||||
|
@ -117,6 +117,8 @@ def err_expected_semi_after_static_assert : Error<
|
||||
"expected ';' after static_assert">;
|
||||
def err_expected_semi_for : Error<"expected ';' in 'for' statement specifier">;
|
||||
def err_expected_colon_after : Error<"expected ':' after %0">;
|
||||
def err_pointer_to_member_type : Error<
|
||||
"invalid use of pointer to member type after %0">;
|
||||
def err_label_end_of_compound_statement : Error<
|
||||
"label at end of compound statement: expected statement">;
|
||||
def err_expected_string_literal : Error<"expected string literal">;
|
||||
@ -124,6 +126,7 @@ def err_expected_asm_operand : Error<
|
||||
"expected string literal or '[' for asm operand">;
|
||||
def err_expected_selector_for_method : Error<
|
||||
"expected selector for Objective-C method">;
|
||||
def err_expected_property_name : Error<"expected property name">;
|
||||
|
||||
def err_unexpected_at : Error<"unexpected '@' in program">;
|
||||
|
||||
@ -213,7 +216,8 @@ def err_declaration_does_not_declare_param : Error<
|
||||
def err_no_matching_param : Error<"parameter named %0 is missing">;
|
||||
|
||||
/// C++ parser diagnostics
|
||||
def err_expected_unqualified_id : Error<"expected unqualified-id">;
|
||||
def err_expected_unqualified_id : Error<
|
||||
"expected %select{identifier|unqualified-id}0">;
|
||||
def err_func_def_no_params : Error<
|
||||
"function definition does not declare parameters">;
|
||||
def err_expected_lparen_after_type : Error<
|
||||
@ -230,6 +234,8 @@ 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">;
|
||||
def err_ident_in_pseudo_dtor_not_a_type : Error<
|
||||
"identifier %0 in pseudo-destructor expression does not name a type">;
|
||||
|
||||
// C++ derived classes
|
||||
def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">;
|
||||
@ -279,6 +285,9 @@ def err_typename_refers_to_non_type_template : Error<
|
||||
"typename specifier refers to a non-template">;
|
||||
def err_expected_type_name_after_typename : Error<
|
||||
"expected an identifier or template-id after '::'">;
|
||||
def err_explicit_spec_non_template : Error<
|
||||
"explicit %select{specialization|instantiation}0 of non-template "
|
||||
"%select{class|struct|union}1 %2">;
|
||||
|
||||
def err_variadic_templates : Error<
|
||||
"variadic templates are only allowed in C++0x">;
|
||||
@ -286,7 +295,7 @@ def err_variadic_templates : Error<
|
||||
// C++ declarations
|
||||
def err_friend_decl_defines_class : Error<
|
||||
"cannot define a type in a friend declaration">;
|
||||
|
||||
|
||||
// Language specific pragmas
|
||||
// - Generic warnings
|
||||
def warn_pragma_expected_lparen : Warning<
|
||||
|
@ -264,13 +264,19 @@ 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 err_use_continuation_class : Error<
|
||||
"attribute of property in continuation class of %0 can only be 'readwrite'">;
|
||||
"property declaration in continuation class of %0 is to change a 'readonly' "
|
||||
"property to 'readwrite'">;
|
||||
def err_continuation_class : Error<"continuation class has no primary class">;
|
||||
def err_property_type : Error<"property cannot have array or function type %0">;
|
||||
def error_missing_property_context : Error<
|
||||
"missing context for property implementation declaration">;
|
||||
def error_bad_property_decl : Error<
|
||||
"property implementation must have its declaration in interface %0">;
|
||||
def error_category_property : Error<
|
||||
"property declared in category %0 cannot be implemented in "
|
||||
"class implementation">;
|
||||
def note_property_declare : Note<
|
||||
"property declared here">;
|
||||
def error_synthesize_category_decl : Error<
|
||||
"@synthesize not allowed in a category's implementation">;
|
||||
def error_missing_property_interface : Error<
|
||||
@ -613,6 +619,10 @@ def warn_attribute_wrong_decl_type : Warning<
|
||||
def warn_gnu_inline_attribute_requires_inline : Warning<
|
||||
"'gnu_inline' attribute requires function to be marked 'inline',"
|
||||
" attribute ignored">;
|
||||
def err_cconv_knr : Error<
|
||||
"function with no prototype cannot use '%0' calling convention">;
|
||||
def err_cconv_varargs : Error<
|
||||
"variadic function cannot use '%0' calling convention">;
|
||||
|
||||
def warn_attribute_ignored_for_field_of_type : Warning<
|
||||
"%0 attribute ignored for field of type %1">;
|
||||
@ -1014,7 +1024,11 @@ def note_partial_spec_unused_parameter : Note<
|
||||
def err_partial_spec_ordering_ambiguous : Error<
|
||||
"ambiguous partial specializations of %0">;
|
||||
def note_partial_spec_match : Note<"partial specialization matches %0">;
|
||||
|
||||
def err_partial_spec_redeclared : Error<
|
||||
"class template partial specialization %0 cannot be redeclared">;
|
||||
def note_prev_partial_spec_here : Note<
|
||||
"previous declaration of class template partial specialization %0 is here">;
|
||||
|
||||
// C++ Function template specializations
|
||||
def err_function_template_spec_no_match : Error<
|
||||
"no function template matches function template specialization %0">;
|
||||
@ -1326,17 +1340,17 @@ def err_flexible_array_init_nonempty : Error<
|
||||
def err_flexible_array_init_needs_braces : Error<
|
||||
"flexible array requires brace-enclosed initializer">;
|
||||
def err_illegal_decl_array_of_functions : Error<
|
||||
"'%0' declared as array of functions">;
|
||||
"'%0' declared as array of functions of type %1">;
|
||||
def err_illegal_decl_array_incomplete_type : Error<
|
||||
"array has incomplete element type %0">;
|
||||
def err_illegal_decl_array_of_references : Error<
|
||||
"'%0' declared as array of references">;
|
||||
"'%0' declared as array of references of type %1">;
|
||||
def err_array_star_outside_prototype : Error<
|
||||
"star modifier used outside of function prototype">;
|
||||
def err_illegal_decl_pointer_to_reference : Error<
|
||||
"'%0' declared as a pointer to a reference">;
|
||||
"'%0' declared as a pointer to a reference of type %1">;
|
||||
def err_illegal_decl_mempointer_to_reference : Error<
|
||||
"'%0' declared as a member pointer to a reference">;
|
||||
"'%0' declared as a member pointer to a reference of type %1">;
|
||||
def err_illegal_decl_mempointer_to_void : Error<
|
||||
"'%0' declared as a member pointer to void">;
|
||||
def err_illegal_decl_mempointer_in_nonclass : Error<
|
||||
@ -1368,6 +1382,8 @@ def err_alignof_incomplete_type : Error<
|
||||
"invalid application of '__alignof' to an incomplete type %0">;
|
||||
def err_sizeof_alignof_bitfield : Error<
|
||||
"invalid application of '%select{sizeof|__alignof}0' to bit-field">;
|
||||
def err_offsetof_incomplete_type : Error<
|
||||
"offsetof of incomplete type %0">;
|
||||
def err_offsetof_record_type : Error<
|
||||
"offsetof requires struct, union, or class type, %0 invalid">;
|
||||
def err_offsetof_array_type : Error<"offsetof requires array type, %0 invalid">;
|
||||
@ -1385,6 +1401,10 @@ def warn_shift_negative : Warning<
|
||||
def warn_shift_gt_typewidth : Warning<
|
||||
"shift count >= width of type">;
|
||||
|
||||
def warn_precedence_bitwise_rel : Warning<
|
||||
"%0 has lower precedence than %1; %1 will be evaluated first">,
|
||||
InGroup<Parentheses>;
|
||||
|
||||
def err_sizeof_nonfragile_interface : Error<
|
||||
"invalid application of '%select{alignof|sizeof}1' to interface %0 in "
|
||||
"non-fragile ABI">;
|
||||
@ -1661,7 +1681,9 @@ def err_bad_new_type : Error<
|
||||
def err_new_incomplete_type : Error<
|
||||
"allocation of incomplete type %0">;
|
||||
def err_new_array_nonconst : Error<
|
||||
"only the first dimension of an allocated array may be non-const">;
|
||||
"only the first dimension of an allocated array may have dynamic size">;
|
||||
def err_new_paren_array_nonconst : Error<
|
||||
"when type is in parentheses, array cannot have dynamic size">;
|
||||
def err_array_size_not_integral : Error<
|
||||
"array size expression must have integral or enumerated type, not %0">;
|
||||
def err_new_uninitialized_const : Error<
|
||||
@ -1709,8 +1731,6 @@ def err_throw_incomplete_ptr : Error<
|
||||
def err_return_in_constructor_handler : Error<
|
||||
"return in the catch of a function try block of a constructor is illegal">;
|
||||
|
||||
def err_ident_in_pseudo_dtor_not_a_type : Error<
|
||||
"identifier %0 in pseudo-destructor expression does not name a type">;
|
||||
def err_operator_arrow_circular : Error<
|
||||
"circular pointer delegation detected">;
|
||||
def err_pseudo_dtor_base_not_scalar : Error<
|
||||
@ -2130,6 +2150,10 @@ def warn_ret_stack_addr : Warning<
|
||||
"address of stack memory associated with local variable %0 returned">;
|
||||
def warn_ret_stack_ref : Warning<
|
||||
"reference to stack memory associated with local variable %0 returned">;
|
||||
def warn_ret_addr_label : Warning<
|
||||
"returning address of label, which is local">;
|
||||
def err_ret_local_block : Error<
|
||||
"returning block that lives on the local stack">;
|
||||
|
||||
|
||||
// For non-floating point, expressions of the form x == x or x != x
|
||||
@ -2153,8 +2177,6 @@ def err_return_in_block_expression : Error<
|
||||
def err_block_returns_array : Error<
|
||||
"block declared as returning an array">;
|
||||
|
||||
def err_ret_local_block : Error<
|
||||
"returning block that lives on the local stack">;
|
||||
|
||||
// CFString checking
|
||||
def err_cfstring_literal_not_string_constant : Error<
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/System/DataTypes.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/System/Host.h"
|
||||
|
@ -26,7 +26,10 @@ enum OverloadedOperatorKind {
|
||||
NUM_OVERLOADED_OPERATORS
|
||||
};
|
||||
|
||||
|
||||
/// \brief Retrieve the spelling of the given overloaded operator, without
|
||||
/// the preceding "operator" keyword.
|
||||
const char *getOperatorSpelling(OverloadedOperatorKind Operator);
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
||||
|
@ -109,7 +109,7 @@ class PartialDiagnostic {
|
||||
// Add all arguments.
|
||||
for (unsigned i = 0, e = DiagStorage->NumDiagArgs; i != e; ++i) {
|
||||
DB.AddTaggedVal(DiagStorage->DiagArgumentsVal[i],
|
||||
(Diagnostic::ArgumentKind)DiagStorage->DiagArgumentsKind[i]);
|
||||
(Diagnostic::ArgumentKind)DiagStorage->DiagArgumentsKind[i]);
|
||||
}
|
||||
|
||||
// Add all ranges.
|
||||
@ -129,13 +129,25 @@ class PartialDiagnostic {
|
||||
PD.AddTaggedVal(I, Diagnostic::ak_uint);
|
||||
return PD;
|
||||
}
|
||||
|
||||
|
||||
friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
|
||||
int I) {
|
||||
PD.AddTaggedVal(I, Diagnostic::ak_sint);
|
||||
return PD;
|
||||
}
|
||||
|
||||
friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
|
||||
const char *S) {
|
||||
PD.AddTaggedVal(reinterpret_cast<intptr_t>(S), Diagnostic::ak_c_string);
|
||||
return PD;
|
||||
}
|
||||
|
||||
friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
|
||||
const SourceRange &R) {
|
||||
PD.AddSourceRange(R);
|
||||
return PD;
|
||||
}
|
||||
|
||||
|
||||
friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
|
||||
DeclarationName N);
|
||||
};
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/System/DataTypes.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
|
@ -17,7 +17,7 @@
|
||||
// FIXME: Daniel isn't smart enough to use a prototype for this.
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/System/DataTypes.h"
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
@ -103,9 +103,9 @@ class TargetInfo {
|
||||
/// enum. For example, SignedInt -> getIntWidth().
|
||||
unsigned getTypeWidth(IntType T) const;
|
||||
|
||||
/// getTypeSigned - Return whether an integer types is signed. Returns true if
|
||||
/// isTypeSigned - Return whether an integer types is signed. Returns true if
|
||||
/// the type is signed; false otherwise.
|
||||
bool getTypeSigned(IntType T) const;
|
||||
bool isTypeSigned(IntType T) const;
|
||||
|
||||
/// getPointerWidth - Return the width of pointers on this target, for the
|
||||
/// specified address space.
|
||||
|
@ -404,6 +404,7 @@ OPTION("-flax-vector-conversions", flax_vector_conversions, Flag, f_Group, INVAL
|
||||
OPTION("-flimited-precision=", flimited_precision_EQ, Joined, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-flto", flto, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fmath-errno", fmath_errno, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fmerge-all-constants", fmerge_all_constants, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fmessage-length=", fmessage_length_EQ, Joined, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fms-extensions", fms_extensions, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-fmudflapth", fmudflapth, Flag, f_Group, INVALID, "", 0, 0, 0)
|
||||
@ -428,6 +429,7 @@ OPTION("-fno-inline-functions", fno_inline_functions, Flag, clang_ignored_f_Grou
|
||||
OPTION("-fno-inline", fno_inline, Flag, clang_ignored_f_Group, INVALID, "", 0, 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-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)
|
||||
@ -559,6 +561,7 @@ OPTION("-m", m_Joined, Joined, m_Group, INVALID, "", 0, 0, 0)
|
||||
OPTION("-no-cpp-precomp", no_cpp_precomp, Flag, INVALID, INVALID, "", 0, 0, 0)
|
||||
OPTION("-no-integrated-cpp", no_integrated_cpp, Flag, INVALID, INVALID, "d", 0, 0, 0)
|
||||
OPTION("-no_dead_strip_inits_and_terms", no__dead__strip__inits__and__terms, Flag, INVALID, INVALID, "", 0, 0, 0)
|
||||
OPTION("-nobuiltininc", nobuiltininc, Flag, INVALID, INVALID, "", 0, 0, 0)
|
||||
OPTION("-nodefaultlibs", nodefaultlibs, Flag, INVALID, INVALID, "", 0, 0, 0)
|
||||
OPTION("-nofixprebinding", nofixprebinding, Flag, INVALID, INVALID, "", 0, 0, 0)
|
||||
OPTION("-nolibc", nolibc, Flag, INVALID, INVALID, "", 0, 0, 0)
|
||||
@ -566,7 +569,6 @@ OPTION("-nomultidefs", nomultidefs, Flag, INVALID, INVALID, "", 0, 0, 0)
|
||||
OPTION("-noprebind", noprebind, Flag, INVALID, INVALID, "", 0, 0, 0)
|
||||
OPTION("-noseglinkedit", noseglinkedit, Flag, INVALID, INVALID, "", 0, 0, 0)
|
||||
OPTION("-nostartfiles", nostartfiles, Flag, INVALID, INVALID, "", 0, 0, 0)
|
||||
OPTION("-nostdclanginc", nostdclanginc, Flag, INVALID, INVALID, "", 0, 0, 0)
|
||||
OPTION("-nostdinc", nostdinc, Flag, INVALID, INVALID, "", 0, 0, 0)
|
||||
OPTION("-nostdlib", nostdlib, Flag, INVALID, INVALID, "", 0, 0, 0)
|
||||
OPTION("-object", object, Flag, INVALID, INVALID, "", 0, 0, 0)
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
#include "clang/Frontend/TextDiagnosticBuffer.h"
|
||||
#include "clang/Basic/FileManager.h"
|
||||
#include "clang/Index/ASTLocation.h"
|
||||
#include <string>
|
||||
|
||||
namespace clang {
|
||||
@ -32,6 +33,8 @@ namespace clang {
|
||||
class ASTContext;
|
||||
class Decl;
|
||||
|
||||
using namespace idx;
|
||||
|
||||
/// \brief Utility class for loading a ASTContext from a PCH file.
|
||||
///
|
||||
class ASTUnit {
|
||||
@ -50,9 +53,11 @@ class ASTUnit {
|
||||
// FIXME: This is temporary; eventually, CIndex will always do this.
|
||||
bool OnlyLocalDecls;
|
||||
|
||||
// Critical optimization when using clang_getCursor().
|
||||
ASTLocation LastLoc;
|
||||
|
||||
ASTUnit(const ASTUnit&); // DO NOT IMPLEMENT
|
||||
ASTUnit &operator=(const ASTUnit &); // DO NOT IMPLEMENT
|
||||
ASTUnit();
|
||||
|
||||
public:
|
||||
ASTUnit(DiagnosticClient *diagClient = NULL);
|
||||
@ -80,6 +85,9 @@ class ASTUnit {
|
||||
|
||||
bool getOnlyLocalDecls() const { return OnlyLocalDecls; }
|
||||
|
||||
void setLastASTLocation(ASTLocation ALoc) { LastLoc = ALoc; }
|
||||
ASTLocation getLastASTLocation() const { return LastLoc; }
|
||||
|
||||
/// \brief Create a ASTUnit from a PCH file.
|
||||
///
|
||||
/// \param Filename - The PCH file to load.
|
||||
|
@ -43,7 +43,8 @@ class CompileOptions {
|
||||
unsigned NoCommon : 1; /// Set when -fno-common or C++ is enabled.
|
||||
unsigned DisableRedZone : 1; /// Set when -mno-red-zone is enabled.
|
||||
unsigned NoImplicitFloat : 1; /// Set when -mno-implicit-float is enabled.
|
||||
|
||||
unsigned MergeAllConstants : 1; // Merge identical constants.
|
||||
|
||||
/// Inlining - The kind of inlining to perform.
|
||||
InliningMethod Inlining;
|
||||
|
||||
@ -67,6 +68,7 @@ class CompileOptions {
|
||||
Inlining = NoInlining;
|
||||
DisableRedZone = 0;
|
||||
NoImplicitFloat = 0;
|
||||
MergeAllConstants = 1;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -99,7 +99,7 @@ NODE_XML(FunctionDecl, "Function")
|
||||
ENUM_XML(FunctionDecl::Static, "static")
|
||||
ENUM_XML(FunctionDecl::PrivateExtern, "__private_extern__")
|
||||
END_ENUM_XML
|
||||
ATTRIBUTE_OPT_XML(isInline(), "inline")
|
||||
ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline")
|
||||
//ATTRIBUTE_OPT_XML(isVariadic(), "variadic") // in the type reference
|
||||
ATTRIBUTE_XML(getNumParams(), "num_args")
|
||||
SUB_NODE_SEQUENCE_XML(ParmVarDecl)
|
||||
@ -113,7 +113,7 @@ NODE_XML(CXXMethodDecl, "CXXMethodDecl")
|
||||
ATTRIBUTE_XML(getNameAsString(), "name")
|
||||
TYPE_ATTRIBUTE_XML(getType()->getAs<FunctionType>()->getResultType())
|
||||
ATTRIBUTE_XML(getType()->getAs<FunctionType>(), "function_type")
|
||||
ATTRIBUTE_OPT_XML(isInline(), "inline")
|
||||
ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline")
|
||||
ATTRIBUTE_OPT_XML(isStatic(), "static")
|
||||
ATTRIBUTE_OPT_XML(isVirtual(), "virtual")
|
||||
ATTRIBUTE_XML(getNumParams(), "num_args")
|
||||
|
49
include/clang/Frontend/DiagnosticOptions.h
Normal file
49
include/clang/Frontend/DiagnosticOptions.h
Normal file
@ -0,0 +1,49 @@
|
||||
//===--- DiagnosticOptions.h ------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_FRONTEND_DIAGNOSTICOPTIONS_H
|
||||
#define LLVM_CLANG_FRONTEND_DIAGNOSTICOPTIONS_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace clang {
|
||||
|
||||
/// DiagnosticOptions - Options for controlling the compiler diagnostics
|
||||
/// engine.
|
||||
class DiagnosticOptions {
|
||||
public:
|
||||
unsigned ShowColumn : 1; /// Show column number on diagnostics.
|
||||
unsigned ShowLocation : 1; /// Show source location information.
|
||||
unsigned ShowCarets : 1; /// Show carets in diagnostics.
|
||||
unsigned ShowFixits : 1; /// Show fixit information.
|
||||
unsigned ShowSourceRanges : 1; /// Show source ranges in numeric form.
|
||||
unsigned ShowOptionNames : 1; /// Show the diagnostic name for mappable
|
||||
/// diagnostics.
|
||||
unsigned ShowColors : 1; /// Show diagnostics with ANSI color sequences.
|
||||
|
||||
/// Column limit for formatting message diagnostics, or 0 if unused.
|
||||
unsigned MessageLength;
|
||||
|
||||
public:
|
||||
DiagnosticOptions() {
|
||||
ShowColumn = 1;
|
||||
ShowLocation = 1;
|
||||
ShowCarets = 1;
|
||||
ShowFixits = 1;
|
||||
ShowSourceRanges = 0;
|
||||
ShowOptionNames = 0;
|
||||
ShowColors = 0;
|
||||
MessageLength = 0;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
@ -73,6 +73,16 @@ class InitHeaderSearch {
|
||||
/// variables such as CPATH.
|
||||
void AddDefaultEnvVarPaths(const LangOptions &Lang);
|
||||
|
||||
// AddDefaultCIncludePaths - Add paths that should always be searched.
|
||||
void AddDefaultCIncludePaths(const llvm::Triple &triple);
|
||||
|
||||
// AddDefaultCPlusPlusIncludePaths - Add paths that should be searched when
|
||||
// compiling c++.
|
||||
void AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple);
|
||||
|
||||
// AddDefaultFrameworkIncludePaths - Add the framework paths. Used on darwin.
|
||||
void AddDefaultFrameworkIncludePaths(const llvm::Triple &triple);
|
||||
|
||||
/// AddDefaultSystemIncludePaths - Adds the default system include paths so
|
||||
/// that e.g. stdio.h is found.
|
||||
void AddDefaultSystemIncludePaths(const LangOptions &Lang,
|
||||
|
@ -63,7 +63,8 @@ class PreprocessorInitOptions {
|
||||
/// environment ready to process a single file. This returns true on error.
|
||||
///
|
||||
bool InitializePreprocessor(Preprocessor &PP,
|
||||
const PreprocessorInitOptions& InitOptions);
|
||||
const PreprocessorInitOptions& InitOptions,
|
||||
bool undef_macros);
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
#define LLVM_CLANG_FRONTEND_PCHBITCODES_H
|
||||
|
||||
#include "llvm/Bitcode/BitCodes.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/System/DataTypes.h"
|
||||
|
||||
namespace clang {
|
||||
namespace pch {
|
||||
@ -496,8 +496,6 @@ namespace clang {
|
||||
DECL_IMPLICIT_PARAM,
|
||||
/// \brief A ParmVarDecl record.
|
||||
DECL_PARM_VAR,
|
||||
/// \brief An OriginalParmVarDecl record.
|
||||
DECL_ORIGINAL_PARM_VAR,
|
||||
/// \brief A FileScopeAsmDecl record.
|
||||
DECL_FILE_SCOPE_ASM,
|
||||
/// \brief A BlockDecl record.
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "clang/Sema/ExternalSemaSource.h"
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/AST/TemplateBase.h"
|
||||
#include "clang/Basic/Diagnostic.h"
|
||||
#include "clang/Basic/IdentifierTable.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
@ -29,7 +30,7 @@
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Bitcode/BitstreamReader.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/System/DataTypes.h"
|
||||
#include <deque>
|
||||
#include <map>
|
||||
#include <string>
|
||||
@ -542,6 +543,12 @@ class PCHReader
|
||||
/// comments in the source code.
|
||||
virtual void ReadComments(std::vector<SourceRange> &Comments);
|
||||
|
||||
/// \brief Reads a TemplateArgumentLocInfo appropriate for the
|
||||
/// given TemplateArgument kind.
|
||||
TemplateArgumentLocInfo
|
||||
GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
|
||||
const RecordData &Record, unsigned &Idx);
|
||||
|
||||
/// \brief Reads a declarator info from the given record.
|
||||
virtual DeclaratorInfo *GetDeclaratorInfo(const RecordData &Record,
|
||||
unsigned &Idx);
|
||||
|
@ -275,6 +275,10 @@ class PCHWriter {
|
||||
/// \brief Emits a reference to a declarator info.
|
||||
void AddDeclaratorInfo(DeclaratorInfo *DInfo, RecordData &Record);
|
||||
|
||||
/// \brief Emits a template argument location.
|
||||
void AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg,
|
||||
RecordData &Record);
|
||||
|
||||
/// \brief Emit a reference to a declaration.
|
||||
void AddDeclRef(const Decl *D, RecordData &Record);
|
||||
|
||||
|
@ -23,42 +23,21 @@ namespace llvm {
|
||||
}
|
||||
|
||||
namespace clang {
|
||||
class SourceManager;
|
||||
class DiagnosticOptions;
|
||||
class LangOptions;
|
||||
class SourceManager;
|
||||
|
||||
class TextDiagnosticPrinter : public DiagnosticClient {
|
||||
llvm::raw_ostream &OS;
|
||||
const LangOptions *LangOpts;
|
||||
const DiagnosticOptions *DiagOpts;
|
||||
|
||||
SourceLocation LastWarningLoc;
|
||||
FullSourceLoc LastLoc;
|
||||
bool LastCaretDiagnosticWasNote;
|
||||
|
||||
bool ShowColumn;
|
||||
bool CaretDiagnostics;
|
||||
bool ShowLocation;
|
||||
bool PrintRangeInfo;
|
||||
bool PrintDiagnosticOption;
|
||||
bool PrintFixItInfo;
|
||||
unsigned MessageLength;
|
||||
bool UseColors;
|
||||
|
||||
public:
|
||||
TextDiagnosticPrinter(llvm::raw_ostream &os,
|
||||
bool showColumn = true,
|
||||
bool caretDiagnistics = true, bool showLocation = true,
|
||||
bool printRangeInfo = true,
|
||||
bool printDiagnosticOption = true,
|
||||
bool printFixItInfo = true,
|
||||
unsigned messageLength = 0,
|
||||
bool useColors = false)
|
||||
: OS(os), LangOpts(0),
|
||||
LastCaretDiagnosticWasNote(false), ShowColumn(showColumn),
|
||||
CaretDiagnostics(caretDiagnistics), ShowLocation(showLocation),
|
||||
PrintRangeInfo(printRangeInfo),
|
||||
PrintDiagnosticOption(printDiagnosticOption),
|
||||
PrintFixItInfo(printFixItInfo),
|
||||
MessageLength(messageLength),
|
||||
UseColors(useColors) {}
|
||||
TextDiagnosticPrinter(llvm::raw_ostream &os, const DiagnosticOptions &diags);
|
||||
|
||||
void setLangOptions(const LangOptions *LO) {
|
||||
LangOpts = LO;
|
||||
|
@ -18,7 +18,6 @@
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
class SourceLocation;
|
||||
class Decl;
|
||||
|
||||
namespace idx {
|
||||
class ASTLocation;
|
||||
@ -28,7 +27,7 @@ namespace idx {
|
||||
/// \returns the resolved ASTLocation or an invalid ASTLocation if the source
|
||||
/// location could not be resolved.
|
||||
ASTLocation ResolveLocationInAST(ASTContext &Ctx, SourceLocation Loc,
|
||||
Decl *RelativeToDecl = 0);
|
||||
ASTLocation *LastLoc = 0);
|
||||
|
||||
} // end namespace idx
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
#include <string>
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/System/DataTypes.h"
|
||||
|
||||
namespace llvm {
|
||||
class APInt;
|
||||
|
@ -75,6 +75,8 @@ class Preprocessor {
|
||||
IdentifierInfo *Ident_Pragma, *Ident__VA_ARGS__; // _Pragma, __VA_ARGS__
|
||||
IdentifierInfo *Ident__has_feature; // __has_feature
|
||||
IdentifierInfo *Ident__has_builtin; // __has_builtin
|
||||
IdentifierInfo *Ident__has_include; // __has_include
|
||||
IdentifierInfo *Ident__has_include_next; // __has_include_next
|
||||
|
||||
SourceLocation DATELoc, TIMELoc;
|
||||
unsigned CounterValue; // Next __COUNTER__ value.
|
||||
@ -244,7 +246,12 @@ class Preprocessor {
|
||||
return CurPPLexer == L;
|
||||
}
|
||||
|
||||
/// getCurrentLexer - Return the current file lexer being lexed from. Note
|
||||
/// getCurrentLexer - Return the current lexer being lexed from. Note
|
||||
/// that this ignores any potentially active macro expansions and _Pragma
|
||||
/// expansions going on at the time.
|
||||
PreprocessorLexer *getCurrentLexer() const { return CurPPLexer; }
|
||||
|
||||
/// getCurrentFileLexer - Return the current file lexer being lexed from. Note
|
||||
/// that this ignores any potentially active macro expansions and _Pragma
|
||||
/// expansions going on at the time.
|
||||
PreprocessorLexer *getCurrentFileLexer() const;
|
||||
@ -622,6 +629,43 @@ class Preprocessor {
|
||||
/// SourceLocation.
|
||||
MacroInfo* AllocateMacroInfo(SourceLocation L);
|
||||
|
||||
/// GetIncludeFilenameSpelling - Turn the specified lexer token into a fully
|
||||
/// checked and spelled filename, e.g. as an operand of #include. This returns
|
||||
/// true if the input filename was in <>'s or false if it were in ""'s. The
|
||||
/// caller is expected to provide a buffer that is large enough to hold the
|
||||
/// spelling of the filename, but is also expected to handle the case when
|
||||
/// this method decides to use a different buffer.
|
||||
bool GetIncludeFilenameSpelling(SourceLocation Loc,
|
||||
const char *&BufStart, const char *&BufEnd);
|
||||
|
||||
/// LookupFile - Given a "foo" or <foo> reference, look up the indicated file,
|
||||
/// return null on failure. isAngled indicates whether the file reference is
|
||||
/// for system #include's or not (i.e. using <> instead of "").
|
||||
const FileEntry *LookupFile(const char *FilenameStart,const char *FilenameEnd,
|
||||
bool isAngled, const DirectoryLookup *FromDir,
|
||||
const DirectoryLookup *&CurDir);
|
||||
|
||||
/// GetCurLookup - The DirectoryLookup structure used to find the current
|
||||
/// FileEntry, if CurLexer is non-null and if applicable. This allows us to
|
||||
/// implement #include_next and find directory-specific properties.
|
||||
const DirectoryLookup *GetCurDirLookup() { return CurDirLookup; }
|
||||
|
||||
/// isInPrimaryFile - Return true if we're in the top-level file, not in a
|
||||
/// #include.
|
||||
bool isInPrimaryFile() const;
|
||||
|
||||
/// ConcatenateIncludeName - Handle cases where the #include name is expanded
|
||||
/// from a macro as multiple tokens, which need to be glued together. This
|
||||
/// occurs for code like:
|
||||
/// #define FOO <a/b.h>
|
||||
/// #include FOO
|
||||
/// because in this case, "<a/b.h>" is returned as 7 tokens, not one.
|
||||
///
|
||||
/// This code concatenates and consumes tokens up to the '>' token. It returns
|
||||
/// false if the > was found, otherwise it returns true if it finds and consumes
|
||||
/// the EOM marker.
|
||||
bool ConcatenateIncludeName(llvm::SmallVector<char, 128> &FilenameBuffer);
|
||||
|
||||
private:
|
||||
|
||||
void PushIncludeMacroStack() {
|
||||
@ -646,10 +690,6 @@ class Preprocessor {
|
||||
/// be reused for allocating new MacroInfo objects.
|
||||
void ReleaseMacroInfo(MacroInfo* MI);
|
||||
|
||||
/// isInPrimaryFile - Return true if we're in the top-level file, not in a
|
||||
/// #include.
|
||||
bool isInPrimaryFile() const;
|
||||
|
||||
/// ReadMacroName - Lex and validate a macro name, which occurs after a
|
||||
/// #define or #undef. This emits a diagnostic, sets the token kind to eom,
|
||||
/// and discards the rest of the macro line if the macro name is invalid.
|
||||
@ -722,24 +762,6 @@ class Preprocessor {
|
||||
/// start getting tokens from it using the PTH cache.
|
||||
void EnterSourceFileWithPTH(PTHLexer *PL, const DirectoryLookup *Dir);
|
||||
|
||||
/// GetIncludeFilenameSpelling - Turn the specified lexer token into a fully
|
||||
/// checked and spelled filename, e.g. as an operand of #include. This returns
|
||||
/// true if the input filename was in <>'s or false if it were in ""'s. The
|
||||
/// caller is expected to provide a buffer that is large enough to hold the
|
||||
/// spelling of the filename, but is also expected to handle the case when
|
||||
/// this method decides to use a different buffer.
|
||||
bool GetIncludeFilenameSpelling(SourceLocation Loc,
|
||||
const char *&BufStart, const char *&BufEnd);
|
||||
|
||||
/// LookupFile - Given a "foo" or <foo> reference, look up the indicated file,
|
||||
/// return null on failure. isAngled indicates whether the file reference is
|
||||
/// for system #include's or not (i.e. using <> instead of "").
|
||||
const FileEntry *LookupFile(const char *FilenameStart,const char *FilenameEnd,
|
||||
bool isAngled, const DirectoryLookup *FromDir,
|
||||
const DirectoryLookup *&CurDir);
|
||||
|
||||
|
||||
|
||||
/// IsFileLexer - Returns true if we are lexing from a file and not a
|
||||
/// pragma or a macro.
|
||||
static bool IsFileLexer(const Lexer* L, const PreprocessorLexer* P) {
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "clang/Basic/TemplateKinds.h"
|
||||
#include "clang/Basic/TokenKinds.h"
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "clang/Basic/OperatorKinds.h"
|
||||
#include <cstdlib>
|
||||
|
||||
namespace clang {
|
||||
@ -62,12 +63,12 @@ class Token {
|
||||
|
||||
/// Kind - The actual flavor of token this is.
|
||||
///
|
||||
unsigned Kind : 8; // DON'T make Kind a 'tok::TokenKind';
|
||||
unsigned char Kind; // DON'T make Kind a 'tok::TokenKind';
|
||||
// MSVC will treat it as a signed char and
|
||||
// TokenKinds > 127 won't be handled correctly.
|
||||
|
||||
/// Flags - Bits we track about this token, members of the TokenFlags enum.
|
||||
unsigned Flags : 8;
|
||||
unsigned char Flags;
|
||||
public:
|
||||
|
||||
// Various flags set per token:
|
||||
@ -261,6 +262,9 @@ struct TemplateIdAnnotation {
|
||||
/// 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;
|
||||
|
@ -161,6 +161,23 @@ class Action : public ActionBase {
|
||||
// Declaration Tracking Callbacks.
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
typedef uintptr_t ParsingDeclStackState;
|
||||
|
||||
/// PushParsingDeclaration - Notes that the parser has begun
|
||||
/// processing a declaration of some sort. Guaranteed to be matched
|
||||
/// by a call to PopParsingDeclaration with the value returned by
|
||||
/// this method.
|
||||
virtual ParsingDeclStackState PushParsingDeclaration() {
|
||||
return ParsingDeclStackState();
|
||||
}
|
||||
|
||||
/// PopParsingDeclaration - Notes that the parser has completed
|
||||
/// processing a declaration of some sort. The decl will be empty
|
||||
/// if the declaration didn't correspond to a full declaration (or
|
||||
/// if the actions module returned an empty decl for it).
|
||||
virtual void PopParsingDeclaration(ParsingDeclStackState S, DeclPtrTy D) {
|
||||
}
|
||||
|
||||
/// ConvertDeclToDeclGroup - If the parser has one decl in a context where it
|
||||
/// needs a decl group, it calls this to convert between the two
|
||||
/// representations.
|
||||
@ -236,30 +253,36 @@ class Action : public ActionBase {
|
||||
virtual bool isCurrentClassName(const IdentifierInfo &II, Scope *S,
|
||||
const CXXScopeSpec *SS = 0) = 0;
|
||||
|
||||
/// \brief Determine whether the given identifier refers to the name of a
|
||||
/// \brief Determine whether the given name refers to a template.
|
||||
///
|
||||
/// This callback is used by the parser after it has seen a '<' to determine
|
||||
/// whether the given name refers to a template and, if so, what kind of
|
||||
/// template.
|
||||
///
|
||||
/// \param S the scope in which name lookup occurs
|
||||
/// \param S the scope in which the name occurs.
|
||||
///
|
||||
/// \param II the identifier that we are querying to determine whether it
|
||||
/// is a template.
|
||||
/// \param SS the C++ nested-name-specifier that precedes the template name,
|
||||
/// if any.
|
||||
///
|
||||
/// \param IdLoc the source location of the identifier
|
||||
/// \param Name the name that we are querying to determine whether it is
|
||||
/// a template.
|
||||
///
|
||||
/// \param SS the C++ scope specifier that precedes the template name, if
|
||||
/// any.
|
||||
/// \param ObjectType if we are determining whether the given name is a
|
||||
/// template name in the context of a member access expression (e.g.,
|
||||
/// \c p->X<int>), this is the type of the object referred to by the
|
||||
/// member access (e.g., \c p).
|
||||
///
|
||||
/// \param EnteringContext whether we are potentially entering the context
|
||||
/// referred to by the scope specifier \p SS
|
||||
/// referred to by the nested-name-specifier \p SS, which allows semantic
|
||||
/// analysis to look into uninstantiated templates.
|
||||
///
|
||||
/// \param Template if the name does refer to a template, the declaration
|
||||
/// of the template that the name refers to.
|
||||
///
|
||||
/// \returns the kind of template that this name refers to.
|
||||
virtual TemplateNameKind isTemplateName(Scope *S,
|
||||
const IdentifierInfo &II,
|
||||
SourceLocation IdLoc,
|
||||
const CXXScopeSpec *SS,
|
||||
const CXXScopeSpec &SS,
|
||||
UnqualifiedId &Name,
|
||||
TypeTy *ObjectType,
|
||||
bool EnteringContext,
|
||||
TemplateTy &Template) = 0;
|
||||
@ -854,47 +877,33 @@ class Action : public ActionBase {
|
||||
virtual SourceRange getExprRange(ExprTy *E) const {
|
||||
return SourceRange();
|
||||
}
|
||||
|
||||
/// ActOnIdentifierExpr - Parse an identifier in expression context.
|
||||
/// 'HasTrailingLParen' indicates whether or not the identifier has a '('
|
||||
/// token immediately after it.
|
||||
/// An optional CXXScopeSpec can be passed to indicate the C++ scope (class or
|
||||
/// namespace) that the identifier must be a member of.
|
||||
/// i.e. for "foo::bar", 'II' will be "bar" and 'SS' will be "foo::".
|
||||
virtual OwningExprResult ActOnIdentifierExpr(Scope *S, SourceLocation Loc,
|
||||
IdentifierInfo &II,
|
||||
bool HasTrailingLParen,
|
||||
const CXXScopeSpec *SS = 0,
|
||||
bool isAddressOfOperand = false){
|
||||
|
||||
/// \brief Parsed an id-expression (C++) or identifier (C) in expression
|
||||
/// context, e.g., the expression "x" that refers to a variable named "x".
|
||||
///
|
||||
/// \param S the scope in which this id-expression or identifier occurs.
|
||||
///
|
||||
/// \param SS the C++ nested-name-specifier that qualifies the name of the
|
||||
/// value, e.g., "std::" in "std::sort".
|
||||
///
|
||||
/// \param Name the name to which the id-expression refers. In C, this will
|
||||
/// always be an identifier. In C++, it may also be an overloaded operator,
|
||||
/// destructor name (if there is a nested-name-specifier), or template-id.
|
||||
///
|
||||
/// \param HasTrailingLParen whether the next token following the
|
||||
/// id-expression or identifier is a left parentheses ('(').
|
||||
///
|
||||
/// \param IsAddressOfOperand whether the token that precedes this
|
||||
/// id-expression or identifier was an ampersand ('&'), indicating that
|
||||
/// we will be taking the address of this expression.
|
||||
virtual OwningExprResult ActOnIdExpression(Scope *S,
|
||||
const CXXScopeSpec &SS,
|
||||
UnqualifiedId &Name,
|
||||
bool HasTrailingLParen,
|
||||
bool IsAddressOfOperand) {
|
||||
return ExprEmpty();
|
||||
}
|
||||
|
||||
/// ActOnOperatorFunctionIdExpr - Parse a C++ overloaded operator
|
||||
/// name (e.g., @c operator+ ) as an expression. This is very
|
||||
/// similar to ActOnIdentifierExpr, except that instead of providing
|
||||
/// an identifier the parser provides the kind of overloaded
|
||||
/// operator that was parsed.
|
||||
virtual OwningExprResult ActOnCXXOperatorFunctionIdExpr(
|
||||
Scope *S, SourceLocation OperatorLoc,
|
||||
OverloadedOperatorKind Op,
|
||||
bool HasTrailingLParen, const CXXScopeSpec &SS,
|
||||
bool isAddressOfOperand = false) {
|
||||
return ExprEmpty();
|
||||
}
|
||||
|
||||
/// ActOnCXXConversionFunctionExpr - Parse a C++ conversion function
|
||||
/// name (e.g., @c operator void const *) as an expression. This is
|
||||
/// very similar to ActOnIdentifierExpr, except that instead of
|
||||
/// providing an identifier the parser provides the type of the
|
||||
/// conversion function.
|
||||
virtual OwningExprResult ActOnCXXConversionFunctionExpr(
|
||||
Scope *S, SourceLocation OperatorLoc,
|
||||
TypeTy *Type, bool HasTrailingLParen,
|
||||
const CXXScopeSpec &SS,
|
||||
bool isAddressOfOperand = false) {
|
||||
return ExprEmpty();
|
||||
}
|
||||
|
||||
|
||||
virtual OwningExprResult ActOnPredefinedExpr(SourceLocation Loc,
|
||||
tok::TokenKind Kind) {
|
||||
return ExprEmpty();
|
||||
@ -936,16 +945,42 @@ class Action : public ActionBase {
|
||||
SourceLocation RLoc) {
|
||||
return ExprEmpty();
|
||||
}
|
||||
virtual OwningExprResult ActOnMemberReferenceExpr(Scope *S, ExprArg Base,
|
||||
SourceLocation OpLoc,
|
||||
tok::TokenKind OpKind,
|
||||
SourceLocation MemberLoc,
|
||||
IdentifierInfo &Member,
|
||||
DeclPtrTy ObjCImpDecl,
|
||||
const CXXScopeSpec *SS = 0) {
|
||||
|
||||
/// \brief Parsed a member access expresion (C99 6.5.2.3, C++ [expr.ref])
|
||||
/// of the form \c x.m or \c p->m.
|
||||
///
|
||||
/// \param S the scope in which the member access expression occurs.
|
||||
///
|
||||
/// \param Base the class or pointer to class into which this member
|
||||
/// access expression refers, e.g., \c x in \c x.m.
|
||||
///
|
||||
/// \param OpLoc the location of the "." or "->" operator.
|
||||
///
|
||||
/// \param OpKind the kind of member access operator, which will be either
|
||||
/// tok::arrow ("->") or tok::period (".").
|
||||
///
|
||||
/// \param SS in C++, the nested-name-specifier that precedes the member
|
||||
/// name, if any.
|
||||
///
|
||||
/// \param Member the name of the member that we are referring to. In C,
|
||||
/// this will always store an identifier; in C++, we may also have operator
|
||||
/// names, conversion function names, destructors, and template names.
|
||||
///
|
||||
/// \param ObjCImpDecl the Objective-C implementation declaration.
|
||||
/// FIXME: Do we really need this?
|
||||
///
|
||||
/// \param HasTrailingLParen whether this member name is immediately followed
|
||||
/// by a left parentheses ('(').
|
||||
virtual OwningExprResult ActOnMemberAccessExpr(Scope *S, ExprArg Base,
|
||||
SourceLocation OpLoc,
|
||||
tok::TokenKind OpKind,
|
||||
const CXXScopeSpec &SS,
|
||||
UnqualifiedId &Member,
|
||||
DeclPtrTy ObjCImpDecl,
|
||||
bool HasTrailingLParen) {
|
||||
return ExprEmpty();
|
||||
}
|
||||
|
||||
|
||||
/// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
|
||||
/// This provides the location of the left/right parens and a list of comma
|
||||
/// locations. There are guaranteed to be one fewer commas than arguments,
|
||||
@ -1245,8 +1280,7 @@ class Action : public ActionBase {
|
||||
}
|
||||
|
||||
/// ActOnFriendTypeDecl - Parsed a friend type declaration.
|
||||
virtual DeclPtrTy ActOnFriendTypeDecl(Scope *S,
|
||||
const DeclSpec &DS,
|
||||
virtual DeclPtrTy ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
|
||||
MultiTemplateParamsArg TParams) {
|
||||
return DeclPtrTy();
|
||||
}
|
||||
@ -1376,123 +1410,6 @@ class Action : public ActionBase {
|
||||
return ExprEmpty();
|
||||
}
|
||||
|
||||
/// ActOnDestructorReferenceExpr - Parsed a destructor reference, for example:
|
||||
///
|
||||
/// t->~T();
|
||||
virtual OwningExprResult
|
||||
ActOnDestructorReferenceExpr(Scope *S, ExprArg Base,
|
||||
SourceLocation OpLoc,
|
||||
tok::TokenKind OpKind,
|
||||
SourceLocation ClassNameLoc,
|
||||
IdentifierInfo *ClassName,
|
||||
const CXXScopeSpec &SS,
|
||||
bool HasTrailingLParen) {
|
||||
return ExprEmpty();
|
||||
}
|
||||
|
||||
/// \brief Parsed a C++ destructor reference that refers to a type.
|
||||
///
|
||||
/// This action is used when parsing a destructor reference that uses a
|
||||
/// template-id, e.g.,
|
||||
///
|
||||
/// \code
|
||||
/// t->~Tmpl<T1, T2>
|
||||
/// \endcode
|
||||
///
|
||||
/// \param S the scope in which the destructor reference occurs.
|
||||
/// \param Base the base object of the destructor reference expression.
|
||||
/// \param OpLoc the location of the operator ('.' or '->').
|
||||
/// \param OpKind the kind of the destructor reference operator ('.' or '->').
|
||||
/// \param TypeRange the source range that covers the destructor type.
|
||||
/// \param Type the type that is being destroyed.
|
||||
/// \param SS the scope specifier that precedes the destructor name.
|
||||
/// \param HasTrailingLParen whether the destructor name is followed by a '('.
|
||||
virtual OwningExprResult
|
||||
ActOnDestructorReferenceExpr(Scope *S, ExprArg Base,
|
||||
SourceLocation OpLoc,
|
||||
tok::TokenKind OpKind,
|
||||
SourceRange TypeRange,
|
||||
TypeTy *Type,
|
||||
const CXXScopeSpec &SS,
|
||||
bool HasTrailingLParen) {
|
||||
return ExprEmpty();
|
||||
}
|
||||
|
||||
/// ActOnOverloadedOperatorReferenceExpr - Parsed an overloaded operator
|
||||
/// reference, for example:
|
||||
///
|
||||
/// t.operator++();
|
||||
virtual OwningExprResult
|
||||
ActOnOverloadedOperatorReferenceExpr(Scope *S, ExprArg Base,
|
||||
SourceLocation OpLoc,
|
||||
tok::TokenKind OpKind,
|
||||
SourceLocation ClassNameLoc,
|
||||
OverloadedOperatorKind OverOpKind,
|
||||
const CXXScopeSpec *SS = 0) {
|
||||
return ExprEmpty();
|
||||
}
|
||||
|
||||
/// ActOnConversionOperatorReferenceExpr - Parsed an overloaded conversion
|
||||
/// function reference, for example:
|
||||
///
|
||||
/// t.operator int();
|
||||
virtual OwningExprResult
|
||||
ActOnConversionOperatorReferenceExpr(Scope *S, ExprArg Base,
|
||||
SourceLocation OpLoc,
|
||||
tok::TokenKind OpKind,
|
||||
SourceLocation ClassNameLoc,
|
||||
TypeTy *Ty,
|
||||
const CXXScopeSpec *SS = 0) {
|
||||
return ExprEmpty();
|
||||
}
|
||||
|
||||
/// \brief Parsed a reference to a member template-id.
|
||||
///
|
||||
/// This callback will occur instead of ActOnMemberReferenceExpr() when the
|
||||
/// member in question is a template for which the code provides an
|
||||
/// explicitly-specified template argument list, e.g.,
|
||||
///
|
||||
/// \code
|
||||
/// x.f<int>()
|
||||
/// \endcode
|
||||
///
|
||||
/// \param S the scope in which the member reference expression occurs
|
||||
///
|
||||
/// \param Base the expression to the left of the "." or "->".
|
||||
///
|
||||
/// \param OpLoc the location of the "." or "->".
|
||||
///
|
||||
/// \param OpKind the kind of operator, which will be "." or "->".
|
||||
///
|
||||
/// \param SS the scope specifier that precedes the template-id in, e.g.,
|
||||
/// \c x.Base::f<int>().
|
||||
///
|
||||
/// \param Template the declaration of the template that is being referenced.
|
||||
///
|
||||
/// \param TemplateNameLoc the location of the template name referred to by
|
||||
/// \p Template.
|
||||
///
|
||||
/// \param LAngleLoc the location of the left angle bracket ('<')
|
||||
///
|
||||
/// \param TemplateArgs the (possibly-empty) template argument list provided
|
||||
/// as part of the member reference.
|
||||
///
|
||||
/// \param RAngleLoc the location of the right angle bracket ('>')
|
||||
virtual OwningExprResult
|
||||
ActOnMemberTemplateIdReferenceExpr(Scope *S, ExprArg Base,
|
||||
SourceLocation OpLoc,
|
||||
tok::TokenKind OpKind,
|
||||
const CXXScopeSpec &SS,
|
||||
// FIXME: "template" keyword?
|
||||
TemplateTy Template,
|
||||
SourceLocation TemplateNameLoc,
|
||||
SourceLocation LAngleLoc,
|
||||
ASTTemplateArgsPtr TemplateArgs,
|
||||
SourceLocation *TemplateArgLocs,
|
||||
SourceLocation RAngleLoc) {
|
||||
return ExprEmpty();
|
||||
}
|
||||
|
||||
/// ActOnFinishFullExpr - Called whenever a full expression has been parsed.
|
||||
/// (C++ [intro.execution]p12).
|
||||
virtual OwningExprResult ActOnFinishFullExpr(ExprArg Expr) {
|
||||
@ -1712,40 +1629,6 @@ class Action : public ActionBase {
|
||||
return TypeResult();
|
||||
}
|
||||
|
||||
/// \brief Form a reference to a template-id (that will refer to a function)
|
||||
/// from a template and a list of template arguments.
|
||||
///
|
||||
/// This action forms an expression that references the given template-id,
|
||||
/// possibly checking well-formedness of the template arguments. It does not
|
||||
/// imply the declaration of any entity.
|
||||
///
|
||||
/// \param SS The scope specifier that may precede the template name.
|
||||
///
|
||||
/// \param Template A template whose specialization results in a
|
||||
/// function or a dependent template.
|
||||
///
|
||||
/// \param TemplateNameLoc The location of the template name.
|
||||
///
|
||||
/// \param LAngleLoc The location of the left angle bracket ('<') that starts
|
||||
/// the template argument list.
|
||||
///
|
||||
/// \param TemplateArgs The template arguments in the template argument list,
|
||||
/// which may be empty.
|
||||
///
|
||||
/// \param TemplateArgLocs The locations of the template arguments.
|
||||
///
|
||||
/// \param RAngleLoc The location of the right angle bracket ('>') that
|
||||
/// closes the template argument list.
|
||||
virtual OwningExprResult ActOnTemplateIdExpr(const CXXScopeSpec &SS,
|
||||
TemplateTy Template,
|
||||
SourceLocation TemplateNameLoc,
|
||||
SourceLocation LAngleLoc,
|
||||
ASTTemplateArgsPtr TemplateArgs,
|
||||
SourceLocation *TemplateArgLocs,
|
||||
SourceLocation RAngleLoc) {
|
||||
return ExprError();
|
||||
}
|
||||
|
||||
/// \brief Form a dependent template name.
|
||||
///
|
||||
/// This action forms a dependent template name given the template
|
||||
@ -1756,22 +1639,19 @@ class Action : public ActionBase {
|
||||
///
|
||||
/// \param TemplateKWLoc the location of the "template" keyword (if any).
|
||||
///
|
||||
/// \param Name the name of the template (an identifier)
|
||||
///
|
||||
/// \param NameLoc the location of the identifier
|
||||
///
|
||||
/// \param SS the nested-name-specifier that precedes the "template" keyword
|
||||
/// or the template name. FIXME: If the dependent template name occurs in
|
||||
/// or the template name. If the dependent template name occurs in
|
||||
/// a member access expression, e.g., "x.template f<T>", this
|
||||
/// nested-name-specifier will be empty.
|
||||
///
|
||||
/// \param Name the name of the template.
|
||||
///
|
||||
/// \param ObjectType if this dependent template name occurs in the
|
||||
/// context of a member access expression, the type of the object being
|
||||
/// accessed.
|
||||
virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
|
||||
const IdentifierInfo &Name,
|
||||
SourceLocation NameLoc,
|
||||
const CXXScopeSpec &SS,
|
||||
UnqualifiedId &Name,
|
||||
TypeTy *ObjectType) {
|
||||
return TemplateTy();
|
||||
}
|
||||
@ -2473,13 +2353,12 @@ class MinimalAction : public Action {
|
||||
const CXXScopeSpec *SS);
|
||||
|
||||
virtual TemplateNameKind isTemplateName(Scope *S,
|
||||
const IdentifierInfo &II,
|
||||
SourceLocation IdLoc,
|
||||
const CXXScopeSpec *SS,
|
||||
const CXXScopeSpec &SS,
|
||||
UnqualifiedId &Name,
|
||||
TypeTy *ObjectType,
|
||||
bool EnteringContext,
|
||||
TemplateTy &Template);
|
||||
|
||||
|
||||
/// ActOnDeclarator - If this is a typedef declarator, we modify the
|
||||
/// IdentifierInfo::FETokenInfo field to keep track of this fact, until S is
|
||||
/// popped.
|
||||
|
@ -390,17 +390,20 @@ class ObjCDeclSpec {
|
||||
};
|
||||
|
||||
|
||||
ObjCDeclSpec() : objcDeclQualifier(DQ_None), PropertyAttributes(DQ_PR_noattr),
|
||||
GetterName(0), SetterName(0) { }
|
||||
ObjCDeclSpec()
|
||||
: objcDeclQualifier(DQ_None), PropertyAttributes(DQ_PR_noattr),
|
||||
GetterName(0), SetterName(0) { }
|
||||
ObjCDeclQualifier getObjCDeclQualifier() const { return objcDeclQualifier; }
|
||||
void setObjCDeclQualifier(ObjCDeclQualifier DQVal)
|
||||
{ objcDeclQualifier = (ObjCDeclQualifier) (objcDeclQualifier | DQVal); }
|
||||
void setObjCDeclQualifier(ObjCDeclQualifier DQVal) {
|
||||
objcDeclQualifier = (ObjCDeclQualifier) (objcDeclQualifier | DQVal);
|
||||
}
|
||||
|
||||
ObjCPropertyAttributeKind getPropertyAttributes() const
|
||||
{ return ObjCPropertyAttributeKind(PropertyAttributes); }
|
||||
ObjCPropertyAttributeKind getPropertyAttributes() const {
|
||||
return ObjCPropertyAttributeKind(PropertyAttributes);
|
||||
}
|
||||
void setPropertyAttributes(ObjCPropertyAttributeKind PRVal) {
|
||||
PropertyAttributes =
|
||||
(ObjCPropertyAttributeKind) (PropertyAttributes | PRVal);
|
||||
(ObjCPropertyAttributeKind)(PropertyAttributes | PRVal);
|
||||
}
|
||||
|
||||
const IdentifierInfo *getGetterName() const { return GetterName; }
|
||||
@ -456,6 +459,193 @@ class CXXScopeSpec {
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Represents a C++ unqualified-id that has been parsed.
|
||||
class UnqualifiedId {
|
||||
private:
|
||||
const UnqualifiedId &operator=(const UnqualifiedId &); // DO NOT IMPLEMENT
|
||||
|
||||
public:
|
||||
/// \brief Describes the kind of unqualified-id parsed.
|
||||
enum IdKind {
|
||||
/// \brief An identifier.
|
||||
IK_Identifier,
|
||||
/// \brief An overloaded operator name, e.g., operator+.
|
||||
IK_OperatorFunctionId,
|
||||
/// \brief A conversion function name, e.g., operator int.
|
||||
IK_ConversionFunctionId,
|
||||
/// \brief A constructor name.
|
||||
IK_ConstructorName,
|
||||
/// \brief A destructor name.
|
||||
IK_DestructorName,
|
||||
/// \brief A template-id, e.g., f<int>.
|
||||
IK_TemplateId
|
||||
} Kind;
|
||||
|
||||
/// \brief Anonymous union that holds extra data associated with the
|
||||
/// parsed unqualified-id.
|
||||
union {
|
||||
/// \brief When Kind == IK_Identifier, the parsed identifier.
|
||||
IdentifierInfo *Identifier;
|
||||
|
||||
/// \brief When Kind == IK_OperatorFunctionId, the overloaded operator
|
||||
/// that we parsed.
|
||||
struct {
|
||||
/// \brief The kind of overloaded operator.
|
||||
OverloadedOperatorKind Operator;
|
||||
|
||||
/// \brief The source locations of the individual tokens that name
|
||||
/// the operator, e.g., the "new", "[", and "]" tokens in
|
||||
/// operator new [].
|
||||
///
|
||||
/// Different operators have different numbers of tokens in their name,
|
||||
/// up to three. Any remaining source locations in this array will be
|
||||
/// set to an invalid value for operators with fewer than three tokens.
|
||||
unsigned SymbolLocations[3];
|
||||
} OperatorFunctionId;
|
||||
|
||||
/// \brief When Kind == IK_ConversionFunctionId, the type that the
|
||||
/// conversion function names.
|
||||
ActionBase::TypeTy *ConversionFunctionId;
|
||||
|
||||
/// \brief When Kind == IK_ConstructorName, the class-name of the type
|
||||
/// whose constructor is being referenced.
|
||||
ActionBase::TypeTy *ConstructorName;
|
||||
|
||||
/// \brief When Kind == IK_DestructorName, the type referred to by the
|
||||
/// class-name.
|
||||
ActionBase::TypeTy *DestructorName;
|
||||
|
||||
/// \brief When Kind == IK_TemplateId, the template-id annotation that
|
||||
/// contains the template name and template arguments.
|
||||
TemplateIdAnnotation *TemplateId;
|
||||
};
|
||||
|
||||
/// \brief The location of the first token that describes this unqualified-id,
|
||||
/// which will be the location of the identifier, "operator" keyword,
|
||||
/// tilde (for a destructor), or the template name of a template-id.
|
||||
SourceLocation StartLocation;
|
||||
|
||||
/// \brief The location of the last token that describes this unqualified-id.
|
||||
SourceLocation EndLocation;
|
||||
|
||||
UnqualifiedId() : Kind(IK_Identifier), Identifier(0) { }
|
||||
|
||||
/// \brief Do not use this copy constructor. It is temporary, and only
|
||||
/// exists because we are holding FieldDeclarators in a SmallVector when we
|
||||
/// don't actually need them.
|
||||
///
|
||||
/// FIXME: Kill this copy constructor.
|
||||
UnqualifiedId(const UnqualifiedId &Other)
|
||||
: Kind(IK_Identifier), Identifier(Other.Identifier),
|
||||
StartLocation(Other.StartLocation), EndLocation(Other.EndLocation) {
|
||||
assert(Other.Kind == IK_Identifier && "Cannot copy non-identifiers");
|
||||
}
|
||||
|
||||
/// \brief Destroy this unqualified-id.
|
||||
~UnqualifiedId() { clear(); }
|
||||
|
||||
/// \brief Clear out this unqualified-id, setting it to default (invalid)
|
||||
/// state.
|
||||
void clear();
|
||||
|
||||
/// \brief Determine whether this unqualified-id refers to a valid name.
|
||||
bool isValid() const { return StartLocation.isValid(); }
|
||||
|
||||
/// \brief Determine whether this unqualified-id refers to an invalid name.
|
||||
bool isInvalid() const { return !isValid(); }
|
||||
|
||||
/// \brief Determine what kind of name we have.
|
||||
IdKind getKind() const { return Kind; }
|
||||
|
||||
/// \brief Specify that this unqualified-id was parsed as an identifier.
|
||||
///
|
||||
/// \param Id the parsed identifier.
|
||||
/// \param IdLoc the location of the parsed identifier.
|
||||
void setIdentifier(const IdentifierInfo *Id, SourceLocation IdLoc) {
|
||||
Kind = IK_Identifier;
|
||||
Identifier = const_cast<IdentifierInfo *>(Id);
|
||||
StartLocation = EndLocation = IdLoc;
|
||||
}
|
||||
|
||||
/// \brief Specify that this unqualified-id was parsed as an
|
||||
/// operator-function-id.
|
||||
///
|
||||
/// \param OperatorLoc the location of the 'operator' keyword.
|
||||
///
|
||||
/// \param Op the overloaded operator.
|
||||
///
|
||||
/// \param SymbolLocations the locations of the individual operator symbols
|
||||
/// in the operator.
|
||||
void setOperatorFunctionId(SourceLocation OperatorLoc,
|
||||
OverloadedOperatorKind Op,
|
||||
SourceLocation SymbolLocations[3]);
|
||||
|
||||
/// \brief Specify that this unqualified-id was parsed as a
|
||||
/// conversion-function-id.
|
||||
///
|
||||
/// \param OperatorLoc the location of the 'operator' keyword.
|
||||
///
|
||||
/// \param Ty the type to which this conversion function is converting.
|
||||
///
|
||||
/// \param EndLoc the location of the last token that makes up the type name.
|
||||
void setConversionFunctionId(SourceLocation OperatorLoc,
|
||||
ActionBase::TypeTy *Ty,
|
||||
SourceLocation EndLoc) {
|
||||
Kind = IK_ConversionFunctionId;
|
||||
StartLocation = OperatorLoc;
|
||||
EndLocation = EndLoc;
|
||||
ConversionFunctionId = Ty;
|
||||
}
|
||||
|
||||
/// \brief Specify that this unqualified-id was parsed as a constructor name.
|
||||
///
|
||||
/// \param ClassType the class type referred to by the constructor name.
|
||||
///
|
||||
/// \param ClassNameLoc the location of the class name.
|
||||
///
|
||||
/// \param EndLoc the location of the last token that makes up the type name.
|
||||
void setConstructorName(ActionBase::TypeTy *ClassType,
|
||||
SourceLocation ClassNameLoc,
|
||||
SourceLocation EndLoc) {
|
||||
Kind = IK_ConstructorName;
|
||||
StartLocation = ClassNameLoc;
|
||||
EndLocation = EndLoc;
|
||||
ConstructorName = ClassType;
|
||||
}
|
||||
|
||||
/// \brief Specify that this unqualified-id was parsed as a destructor name.
|
||||
///
|
||||
/// \param TildeLoc the location of the '~' that introduces the destructor
|
||||
/// name.
|
||||
///
|
||||
/// \param ClassType the name of the class referred to by the destructor name.
|
||||
void setDestructorName(SourceLocation TildeLoc, ActionBase::TypeTy *ClassType,
|
||||
SourceLocation EndLoc) {
|
||||
Kind = IK_DestructorName;
|
||||
StartLocation = TildeLoc;
|
||||
EndLocation = EndLoc;
|
||||
DestructorName = ClassType;
|
||||
}
|
||||
|
||||
/// \brief Specify that this unqualified-id was parsed as a template-id.
|
||||
///
|
||||
/// \param TemplateId the template-id annotation that describes the parsed
|
||||
/// template-id. This UnqualifiedId instance will take ownership of the
|
||||
/// \p TemplateId and will free it on destruction.
|
||||
void setTemplateId(TemplateIdAnnotation *TemplateId) {
|
||||
assert(TemplateId && "NULL template-id annotation?");
|
||||
Kind = IK_TemplateId;
|
||||
this->TemplateId = TemplateId;
|
||||
StartLocation = TemplateId->TemplateNameLoc;
|
||||
EndLocation = TemplateId->RAngleLoc;
|
||||
}
|
||||
|
||||
/// \brief Return the source range that covers this unqualified-id.
|
||||
SourceRange getSourceRange() const {
|
||||
return SourceRange(StartLocation, EndLocation);
|
||||
}
|
||||
};
|
||||
|
||||
/// CachedTokens - A set of tokens that has been cached for later
|
||||
/// parsing.
|
||||
typedef llvm::SmallVector<Token, 4> CachedTokens;
|
||||
@ -790,33 +980,16 @@ class Declarator {
|
||||
BlockLiteralContext // Block literal declarator.
|
||||
};
|
||||
|
||||
/// DeclaratorKind - The kind of declarator this represents.
|
||||
enum DeclaratorKind {
|
||||
DK_Abstract, // An abstract declarator (has no identifier)
|
||||
DK_Normal, // A normal declarator (has an identifier).
|
||||
DK_Constructor, // A C++ constructor (identifier is the class name)
|
||||
DK_Destructor, // A C++ destructor (identifier is ~class name)
|
||||
DK_Operator, // A C++ overloaded operator name
|
||||
DK_Conversion, // A C++ conversion function (identifier is
|
||||
// "operator " then the type name)
|
||||
DK_TemplateId // A C++ template-id naming a function template
|
||||
// specialization.
|
||||
};
|
||||
|
||||
private:
|
||||
const DeclSpec &DS;
|
||||
CXXScopeSpec SS;
|
||||
IdentifierInfo *Identifier;
|
||||
SourceLocation IdentifierLoc;
|
||||
UnqualifiedId Name;
|
||||
SourceRange Range;
|
||||
|
||||
/// Context - Where we are parsing this declarator.
|
||||
///
|
||||
TheContext Context;
|
||||
|
||||
/// Kind - What kind of declarator this is.
|
||||
DeclaratorKind Kind;
|
||||
|
||||
/// DeclTypeInfo - This holds each type that the declarator includes as it is
|
||||
/// parsed. This is pushed from the identifier out, which means that element
|
||||
/// #0 will be the most closely bound to the identifier, and
|
||||
@ -835,21 +1008,6 @@ class Declarator {
|
||||
/// AsmLabel - The asm label, if specified.
|
||||
ActionBase::ExprTy *AsmLabel;
|
||||
|
||||
union {
|
||||
// When Kind is DK_Constructor, DK_Destructor, or DK_Conversion, the
|
||||
// type associated with the constructor, destructor, or conversion
|
||||
// operator.
|
||||
ActionBase::TypeTy *Type;
|
||||
|
||||
/// When Kind is DK_Operator, this is the actual overloaded
|
||||
/// operator that this declarator names.
|
||||
OverloadedOperatorKind OperatorKind;
|
||||
|
||||
/// When Kind is DK_TemplateId, this is the template-id annotation that
|
||||
/// contains the template and its template arguments.
|
||||
TemplateIdAnnotation *TemplateId;
|
||||
};
|
||||
|
||||
/// InlineParams - This is a local array used for the first function decl
|
||||
/// chunk to avoid going to the heap for the common case when we have one
|
||||
/// function chunk in the declarator.
|
||||
@ -863,10 +1021,9 @@ class Declarator {
|
||||
|
||||
public:
|
||||
Declarator(const DeclSpec &ds, TheContext C)
|
||||
: DS(ds), Identifier(0), Range(ds.getSourceRange()), Context(C),
|
||||
Kind(DK_Abstract),
|
||||
: DS(ds), Range(ds.getSourceRange()), Context(C),
|
||||
InvalidType(DS.getTypeSpecType() == DeclSpec::TST_error),
|
||||
GroupingParens(false), AttrList(0), AsmLabel(0), Type(0),
|
||||
GroupingParens(false), AttrList(0), AsmLabel(0),
|
||||
InlineParamsUsed(false), Extension(false) {
|
||||
}
|
||||
|
||||
@ -890,8 +1047,10 @@ class Declarator {
|
||||
const CXXScopeSpec &getCXXScopeSpec() const { return SS; }
|
||||
CXXScopeSpec &getCXXScopeSpec() { return SS; }
|
||||
|
||||
/// \brief Retrieve the name specified by this declarator.
|
||||
UnqualifiedId &getName() { return Name; }
|
||||
|
||||
TheContext getContext() const { return Context; }
|
||||
DeclaratorKind getKind() const { return Kind; }
|
||||
|
||||
/// getSourceRange - Get the source range that spans this declarator.
|
||||
const SourceRange &getSourceRange() const { return Range; }
|
||||
@ -922,22 +1081,15 @@ class Declarator {
|
||||
/// clear - Reset the contents of this Declarator.
|
||||
void clear() {
|
||||
SS.clear();
|
||||
Identifier = 0;
|
||||
IdentifierLoc = SourceLocation();
|
||||
Name.clear();
|
||||
Range = DS.getSourceRange();
|
||||
|
||||
if (Kind == DK_TemplateId)
|
||||
TemplateId->Destroy();
|
||||
|
||||
Kind = DK_Abstract;
|
||||
|
||||
for (unsigned i = 0, e = DeclTypeInfo.size(); i != e; ++i)
|
||||
DeclTypeInfo[i].destroy();
|
||||
DeclTypeInfo.clear();
|
||||
delete AttrList;
|
||||
AttrList = 0;
|
||||
AsmLabel = 0;
|
||||
Type = 0;
|
||||
InlineParamsUsed = false;
|
||||
}
|
||||
|
||||
@ -968,84 +1120,28 @@ class Declarator {
|
||||
|
||||
/// isPastIdentifier - Return true if we have parsed beyond the point where
|
||||
/// the
|
||||
bool isPastIdentifier() const { return IdentifierLoc.isValid(); }
|
||||
bool isPastIdentifier() const { return Name.isValid(); }
|
||||
|
||||
/// hasName - Whether this declarator has a name, which might be an
|
||||
/// identifier (accessible via getIdentifier()) or some kind of
|
||||
/// special C++ name (constructor, destructor, etc.).
|
||||
bool hasName() const { return getKind() != DK_Abstract; }
|
||||
|
||||
IdentifierInfo *getIdentifier() const { return Identifier; }
|
||||
SourceLocation getIdentifierLoc() const { return IdentifierLoc; }
|
||||
|
||||
void SetIdentifier(IdentifierInfo *ID, SourceLocation Loc) {
|
||||
Identifier = ID;
|
||||
IdentifierLoc = Loc;
|
||||
if (ID)
|
||||
Kind = DK_Normal;
|
||||
else
|
||||
Kind = DK_Abstract;
|
||||
SetRangeEnd(Loc);
|
||||
bool hasName() const {
|
||||
return Name.getKind() != UnqualifiedId::IK_Identifier || Name.Identifier;
|
||||
}
|
||||
|
||||
/// setConstructor - Set this declarator to be a C++ constructor
|
||||
/// declarator. Also extends the range.
|
||||
void setConstructor(ActionBase::TypeTy *Ty, SourceLocation Loc) {
|
||||
IdentifierLoc = Loc;
|
||||
Kind = DK_Constructor;
|
||||
Type = Ty;
|
||||
SetRangeEnd(Loc);
|
||||
IdentifierInfo *getIdentifier() const {
|
||||
if (Name.getKind() == UnqualifiedId::IK_Identifier)
|
||||
return Name.Identifier;
|
||||
|
||||
return 0;
|
||||
}
|
||||
SourceLocation getIdentifierLoc() const { return Name.StartLocation; }
|
||||
|
||||
/// setDestructor - Set this declarator to be a C++ destructor
|
||||
/// declarator. Also extends the range to End, which should be the identifier
|
||||
/// token.
|
||||
void setDestructor(ActionBase::TypeTy *Ty, SourceLocation Loc,
|
||||
SourceLocation EndLoc) {
|
||||
IdentifierLoc = Loc;
|
||||
Kind = DK_Destructor;
|
||||
Type = Ty;
|
||||
if (!EndLoc.isInvalid())
|
||||
SetRangeEnd(EndLoc);
|
||||
/// \brief Set the name of this declarator to be the given identifier.
|
||||
void SetIdentifier(IdentifierInfo *Id, SourceLocation IdLoc) {
|
||||
Name.setIdentifier(Id, IdLoc);
|
||||
}
|
||||
|
||||
/// setConversionFunction - Set this declarator to be a C++
|
||||
/// conversion function declarator (e.g., @c operator int const *).
|
||||
/// Also extends the range to EndLoc, which should be the last token of the
|
||||
/// type name.
|
||||
void setConversionFunction(ActionBase::TypeTy *Ty, SourceLocation Loc,
|
||||
SourceLocation EndLoc) {
|
||||
Identifier = 0;
|
||||
IdentifierLoc = Loc;
|
||||
Kind = DK_Conversion;
|
||||
Type = Ty;
|
||||
if (!EndLoc.isInvalid())
|
||||
SetRangeEnd(EndLoc);
|
||||
}
|
||||
|
||||
/// setOverloadedOperator - Set this declaration to be a C++
|
||||
/// overloaded operator declarator (e.g., @c operator+).
|
||||
/// Also extends the range to EndLoc, which should be the last token of the
|
||||
/// operator.
|
||||
void setOverloadedOperator(OverloadedOperatorKind Op, SourceLocation Loc,
|
||||
SourceLocation EndLoc) {
|
||||
IdentifierLoc = Loc;
|
||||
Kind = DK_Operator;
|
||||
OperatorKind = Op;
|
||||
if (!EndLoc.isInvalid())
|
||||
SetRangeEnd(EndLoc);
|
||||
}
|
||||
|
||||
/// \brief Set this declaration to be a C++ template-id, which includes the
|
||||
/// template (or set of function templates) along with template arguments.
|
||||
void setTemplateId(TemplateIdAnnotation *TemplateId) {
|
||||
assert(TemplateId && "NULL template-id provided to declarator?");
|
||||
IdentifierLoc = TemplateId->TemplateNameLoc;
|
||||
Kind = DK_TemplateId;
|
||||
SetRangeEnd(TemplateId->RAngleLoc);
|
||||
this->TemplateId = TemplateId;
|
||||
}
|
||||
|
||||
|
||||
/// AddTypeInfo - Add a chunk to this declarator. Also extend the range to
|
||||
/// EndLoc, which should be the last token of the chunk.
|
||||
void AddTypeInfo(const DeclaratorChunk &TI, SourceLocation EndLoc) {
|
||||
@ -1069,6 +1165,13 @@ class Declarator {
|
||||
return DeclTypeInfo[i];
|
||||
}
|
||||
|
||||
void DropFirstTypeObject()
|
||||
{
|
||||
assert(!DeclTypeInfo.empty() && "No type chunks to drop.");
|
||||
DeclTypeInfo.front().destroy();
|
||||
DeclTypeInfo.erase(DeclTypeInfo.begin());
|
||||
}
|
||||
|
||||
/// isFunctionDeclarator - Once this declarator is fully parsed and formed,
|
||||
/// this method returns true if the identifier is a function declarator.
|
||||
bool isFunctionDeclarator() const {
|
||||
@ -1108,22 +1211,6 @@ class Declarator {
|
||||
void setExtension(bool Val = true) { Extension = Val; }
|
||||
bool getExtension() const { return Extension; }
|
||||
|
||||
ActionBase::TypeTy *getDeclaratorIdType() const {
|
||||
assert((Kind == DK_Constructor || Kind == DK_Destructor ||
|
||||
Kind == DK_Conversion) && "Declarator kind does not have a type");
|
||||
return Type;
|
||||
}
|
||||
|
||||
OverloadedOperatorKind getOverloadedOperator() const {
|
||||
assert(Kind == DK_Operator && "Declarator is not an overloaded operator");
|
||||
return OperatorKind;
|
||||
}
|
||||
|
||||
TemplateIdAnnotation *getTemplateId() {
|
||||
assert(Kind == DK_TemplateId && "Declarator is not a template-id");
|
||||
return TemplateId;
|
||||
}
|
||||
|
||||
void setInvalidType(bool Val = true) { InvalidType = Val; }
|
||||
bool isInvalidType() const {
|
||||
return InvalidType || DS.getTypeSpecType() == DeclSpec::TST_error;
|
||||
@ -1142,7 +1229,7 @@ struct FieldDeclarator {
|
||||
BitfieldSize = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
||||
|
@ -571,6 +571,99 @@ class Parser {
|
||||
return *ClassStack.top();
|
||||
}
|
||||
|
||||
/// \brief RAII object used to inform the actions that we're
|
||||
/// currently parsing a declaration. This is active when parsing a
|
||||
/// variable's initializer, but not when parsing the body of a
|
||||
/// class or function definition.
|
||||
class ParsingDeclRAIIObject {
|
||||
Action &Actions;
|
||||
Action::ParsingDeclStackState State;
|
||||
bool Popped;
|
||||
|
||||
public:
|
||||
ParsingDeclRAIIObject(Parser &P) : Actions(P.Actions) {
|
||||
push();
|
||||
}
|
||||
|
||||
~ParsingDeclRAIIObject() {
|
||||
abort();
|
||||
}
|
||||
|
||||
/// Resets the RAII object for a new declaration.
|
||||
void reset() {
|
||||
abort();
|
||||
push();
|
||||
}
|
||||
|
||||
/// Signals that the context was completed without an appropriate
|
||||
/// declaration being parsed.
|
||||
void abort() {
|
||||
pop(DeclPtrTy());
|
||||
}
|
||||
|
||||
void complete(DeclPtrTy D) {
|
||||
assert(!Popped && "ParsingDeclaration has already been popped!");
|
||||
pop(D);
|
||||
}
|
||||
|
||||
private:
|
||||
void push() {
|
||||
State = Actions.PushParsingDeclaration();
|
||||
Popped = false;
|
||||
}
|
||||
|
||||
void pop(DeclPtrTy D) {
|
||||
if (!Popped) {
|
||||
Actions.PopParsingDeclaration(State, D);
|
||||
Popped = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// A class for parsing a DeclSpec.
|
||||
class ParsingDeclSpec : public DeclSpec {
|
||||
ParsingDeclRAIIObject ParsingRAII;
|
||||
|
||||
public:
|
||||
ParsingDeclSpec(Parser &P) : ParsingRAII(P) {
|
||||
}
|
||||
|
||||
void complete(DeclPtrTy D) {
|
||||
ParsingRAII.complete(D);
|
||||
}
|
||||
|
||||
void abort() {
|
||||
ParsingRAII.abort();
|
||||
}
|
||||
};
|
||||
|
||||
/// A class for parsing a declarator.
|
||||
class ParsingDeclarator : public Declarator {
|
||||
ParsingDeclRAIIObject ParsingRAII;
|
||||
|
||||
public:
|
||||
ParsingDeclarator(Parser &P, const ParsingDeclSpec &DS, TheContext C)
|
||||
: Declarator(DS, C), ParsingRAII(P) {
|
||||
}
|
||||
|
||||
const ParsingDeclSpec &getDeclSpec() const {
|
||||
return static_cast<const ParsingDeclSpec&>(Declarator::getDeclSpec());
|
||||
}
|
||||
|
||||
ParsingDeclSpec &getMutableDeclSpec() const {
|
||||
return const_cast<ParsingDeclSpec&>(getDeclSpec());
|
||||
}
|
||||
|
||||
void clear() {
|
||||
Declarator::clear();
|
||||
ParsingRAII.reset();
|
||||
}
|
||||
|
||||
void complete(DeclPtrTy D) {
|
||||
ParsingRAII.complete(D);
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief RAII object used to
|
||||
class ParsingClassDefinition {
|
||||
Parser &P;
|
||||
@ -603,14 +696,17 @@ class Parser {
|
||||
: Kind(NonTemplate), TemplateParams(0), TemplateLoc() { }
|
||||
|
||||
ParsedTemplateInfo(TemplateParameterLists *TemplateParams,
|
||||
bool isSpecialization)
|
||||
bool isSpecialization,
|
||||
bool lastParameterListWasEmpty = false)
|
||||
: Kind(isSpecialization? ExplicitSpecialization : Template),
|
||||
TemplateParams(TemplateParams) { }
|
||||
TemplateParams(TemplateParams),
|
||||
LastParameterListWasEmpty(lastParameterListWasEmpty) { }
|
||||
|
||||
explicit ParsedTemplateInfo(SourceLocation ExternLoc,
|
||||
SourceLocation TemplateLoc)
|
||||
: Kind(ExplicitInstantiation), TemplateParams(0),
|
||||
ExternLoc(ExternLoc), TemplateLoc(TemplateLoc) { }
|
||||
ExternLoc(ExternLoc), TemplateLoc(TemplateLoc),
|
||||
LastParameterListWasEmpty(false){ }
|
||||
|
||||
/// \brief The kind of template we are parsing.
|
||||
enum {
|
||||
@ -635,6 +731,9 @@ class Parser {
|
||||
/// \brief The location of the 'template' keyword, for an explicit
|
||||
/// instantiation.
|
||||
SourceLocation TemplateLoc;
|
||||
|
||||
/// \brief Whether the last template parameter list was empty.
|
||||
bool LastParameterListWasEmpty;
|
||||
};
|
||||
|
||||
void PushParsingClass(DeclPtrTy TagOrTemplate, bool TopLevelClass);
|
||||
@ -658,7 +757,7 @@ class Parser {
|
||||
DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(
|
||||
AccessSpecifier AS = AS_none);
|
||||
|
||||
DeclPtrTy ParseFunctionDefinition(Declarator &D,
|
||||
DeclPtrTy ParseFunctionDefinition(ParsingDeclarator &D,
|
||||
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo());
|
||||
void ParseKNRParamDeclarations(Declarator &D);
|
||||
// EndLoc, if non-NULL, is filled with the location of the last token of
|
||||
@ -944,11 +1043,12 @@ class Parser {
|
||||
|
||||
DeclGroupPtrTy ParseDeclaration(unsigned Context, SourceLocation &DeclEnd);
|
||||
DeclGroupPtrTy ParseSimpleDeclaration(unsigned Context,
|
||||
SourceLocation &DeclEnd,
|
||||
bool RequireSemi = true);
|
||||
SourceLocation &DeclEnd);
|
||||
DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, unsigned Context,
|
||||
bool AllowFunctionDefinitions,
|
||||
SourceLocation *DeclEnd = 0);
|
||||
DeclPtrTy ParseDeclarationAfterDeclarator(Declarator &D,
|
||||
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo());
|
||||
DeclGroupPtrTy ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D);
|
||||
DeclPtrTy ParseFunctionStatementBody(DeclPtrTy Decl);
|
||||
DeclPtrTy ParseFunctionTryBlock(DeclPtrTy Decl);
|
||||
|
||||
@ -973,8 +1073,16 @@ class Parser {
|
||||
void ParseEnumBody(SourceLocation StartLoc, DeclPtrTy TagDecl);
|
||||
void ParseStructUnionBody(SourceLocation StartLoc, unsigned TagType,
|
||||
DeclPtrTy TagDecl);
|
||||
void ParseStructDeclaration(DeclSpec &DS,
|
||||
llvm::SmallVectorImpl<FieldDeclarator> &Fields);
|
||||
|
||||
struct FieldCallback {
|
||||
virtual DeclPtrTy invoke(FieldDeclarator &Field) = 0;
|
||||
virtual ~FieldCallback() {}
|
||||
|
||||
private:
|
||||
virtual void _anchor();
|
||||
};
|
||||
|
||||
void ParseStructDeclaration(DeclSpec &DS, FieldCallback &Callback);
|
||||
|
||||
bool isDeclarationSpecifier();
|
||||
bool isTypeSpecifierQualifier();
|
||||
@ -1197,6 +1305,21 @@ class Parser {
|
||||
BaseResult ParseBaseSpecifier(DeclPtrTy ClassDecl);
|
||||
AccessSpecifier getAccessSpecifierIfPresent() const;
|
||||
|
||||
bool ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
|
||||
IdentifierInfo *Name,
|
||||
SourceLocation NameLoc,
|
||||
bool EnteringContext,
|
||||
TypeTy *ObjectType,
|
||||
UnqualifiedId &Id);
|
||||
bool ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
|
||||
TypeTy *ObjectType,
|
||||
UnqualifiedId &Result);
|
||||
bool ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
|
||||
bool AllowDestructorName,
|
||||
bool AllowConstructorName,
|
||||
TypeTy *ObjectType,
|
||||
UnqualifiedId &Result);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// C++ 13.5: Overloaded operators [over.oper]
|
||||
// EndLoc, if non-NULL, is filled with the location of the last token of
|
||||
@ -1247,6 +1370,7 @@ class Parser {
|
||||
|
||||
bool AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
|
||||
const CXXScopeSpec *SS,
|
||||
UnqualifiedId &TemplateName,
|
||||
SourceLocation TemplateKWLoc = SourceLocation(),
|
||||
bool AllowTypeAnnotation = true);
|
||||
void AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS = 0);
|
||||
|
@ -26,6 +26,7 @@ namespace clang {
|
||||
class FunctionDecl;
|
||||
class FunctionType;
|
||||
class FunctionTemplateDecl;
|
||||
class IdentifierInfo;
|
||||
class NamedDecl;
|
||||
class NestedNameSpecifier;
|
||||
class Sema;
|
||||
@ -150,7 +151,8 @@ class CodeCompleteConsumer {
|
||||
/// \brief Describes the kind of result generated.
|
||||
enum ResultKind {
|
||||
RK_Declaration = 0, //< Refers to a declaration
|
||||
RK_Keyword //< Refers to a keyword or symbol.
|
||||
RK_Keyword, //< Refers to a keyword or symbol.
|
||||
RK_Macro //< Refers to a macro
|
||||
};
|
||||
|
||||
/// \brief The kind of result stored here.
|
||||
@ -164,6 +166,9 @@ class CodeCompleteConsumer {
|
||||
/// \brief When Kind == RK_Keyword, the string representing the keyword
|
||||
/// or symbol's spelling.
|
||||
const char *Keyword;
|
||||
|
||||
/// \brief When Kind == RK_Macro, the identifier that refers to a macro.
|
||||
IdentifierInfo *Macro;
|
||||
};
|
||||
|
||||
/// \brief Describes how good this result is, with zero being the best
|
||||
@ -199,6 +204,12 @@ class CodeCompleteConsumer {
|
||||
QualifierIsInformative(0), StartsNestedNameSpecifier(false),
|
||||
Qualifier(0) { }
|
||||
|
||||
/// \brief Build a result that refers to a macro.
|
||||
Result(IdentifierInfo *Macro, unsigned Rank)
|
||||
: Kind(RK_Macro), Macro(Macro), Rank(Rank), Hidden(false),
|
||||
QualifierIsInformative(0), StartsNestedNameSpecifier(false),
|
||||
Qualifier(0) { }
|
||||
|
||||
/// \brief Retrieve the declaration stored in this result.
|
||||
NamedDecl *getDeclaration() const {
|
||||
assert(Kind == RK_Declaration && "Not a declaration result");
|
||||
|
@ -22,9 +22,10 @@
|
||||
#include "clang/Basic/Builtins.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "RecordLayoutBuilder.h"
|
||||
|
||||
using namespace clang;
|
||||
@ -138,9 +139,9 @@ void ASTContext::PrintStats() const {
|
||||
}
|
||||
|
||||
|
||||
void ASTContext::InitBuiltinType(QualType &R, BuiltinType::Kind K) {
|
||||
void ASTContext::InitBuiltinType(CanQualType &R, BuiltinType::Kind K) {
|
||||
BuiltinType *Ty = new (*this, TypeAlignment) BuiltinType(K);
|
||||
R = QualType(Ty, 0);
|
||||
R = CanQualType::CreateUnsafe(QualType(Ty, 0));
|
||||
Types.push_back(Ty);
|
||||
}
|
||||
|
||||
@ -872,6 +873,55 @@ void ASTContext::CollectSynthesizedIvars(const ObjCInterfaceDecl *OI,
|
||||
}
|
||||
}
|
||||
|
||||
/// CollectInheritedProtocols - Collect all protocols in current class and
|
||||
/// those inherited by it.
|
||||
void ASTContext::CollectInheritedProtocols(const Decl *CDecl,
|
||||
llvm::SmallVectorImpl<ObjCProtocolDecl*> &Protocols) {
|
||||
if (const ObjCInterfaceDecl *OI = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
|
||||
for (ObjCInterfaceDecl::protocol_iterator P = OI->protocol_begin(),
|
||||
PE = OI->protocol_end(); P != PE; ++P) {
|
||||
ObjCProtocolDecl *Proto = (*P);
|
||||
Protocols.push_back(Proto);
|
||||
for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(),
|
||||
PE = Proto->protocol_end(); P != PE; ++P)
|
||||
CollectInheritedProtocols(*P, Protocols);
|
||||
}
|
||||
|
||||
// Categories of this Interface.
|
||||
for (const ObjCCategoryDecl *CDeclChain = OI->getCategoryList();
|
||||
CDeclChain; CDeclChain = CDeclChain->getNextClassCategory())
|
||||
CollectInheritedProtocols(CDeclChain, Protocols);
|
||||
if (ObjCInterfaceDecl *SD = OI->getSuperClass())
|
||||
while (SD) {
|
||||
CollectInheritedProtocols(SD, Protocols);
|
||||
SD = SD->getSuperClass();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (const ObjCCategoryDecl *OC = dyn_cast<ObjCCategoryDecl>(CDecl)) {
|
||||
for (ObjCInterfaceDecl::protocol_iterator P = OC->protocol_begin(),
|
||||
PE = OC->protocol_end(); P != PE; ++P) {
|
||||
ObjCProtocolDecl *Proto = (*P);
|
||||
Protocols.push_back(Proto);
|
||||
for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(),
|
||||
PE = Proto->protocol_end(); P != PE; ++P)
|
||||
CollectInheritedProtocols(*P, Protocols);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (const ObjCProtocolDecl *OP = dyn_cast<ObjCProtocolDecl>(CDecl)) {
|
||||
for (ObjCProtocolDecl::protocol_iterator P = OP->protocol_begin(),
|
||||
PE = OP->protocol_end(); P != PE; ++P) {
|
||||
ObjCProtocolDecl *Proto = (*P);
|
||||
Protocols.push_back(Proto);
|
||||
for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(),
|
||||
PE = Proto->protocol_end(); P != PE; ++P)
|
||||
CollectInheritedProtocols(*P, Protocols);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned ASTContext::CountProtocolSynthesizedIvars(const ObjCProtocolDecl *PD) {
|
||||
unsigned count = 0;
|
||||
for (ObjCContainerDecl::prop_iterator I = PD->prop_begin(),
|
||||
@ -955,6 +1005,13 @@ DeclaratorInfo *ASTContext::CreateDeclaratorInfo(QualType T,
|
||||
return DInfo;
|
||||
}
|
||||
|
||||
DeclaratorInfo *ASTContext::getTrivialDeclaratorInfo(QualType T,
|
||||
SourceLocation L) {
|
||||
DeclaratorInfo *DI = CreateDeclaratorInfo(T);
|
||||
DI->getTypeLoc().initialize(L);
|
||||
return DI;
|
||||
}
|
||||
|
||||
/// getInterfaceLayoutImpl - Get or compute information about the
|
||||
/// layout of the given interface.
|
||||
///
|
||||
@ -1755,6 +1812,19 @@ QualType ASTContext::getTemplateTypeParmType(unsigned Depth, unsigned Index,
|
||||
return QualType(TypeParm, 0);
|
||||
}
|
||||
|
||||
QualType
|
||||
ASTContext::getTemplateSpecializationType(TemplateName Template,
|
||||
const TemplateArgumentLoc *Args,
|
||||
unsigned NumArgs,
|
||||
QualType Canon) {
|
||||
llvm::SmallVector<TemplateArgument, 4> ArgVec;
|
||||
ArgVec.reserve(NumArgs);
|
||||
for (unsigned i = 0; i != NumArgs; ++i)
|
||||
ArgVec.push_back(Args[i].getArgument());
|
||||
|
||||
return getTemplateSpecializationType(Template, ArgVec.data(), NumArgs, Canon);
|
||||
}
|
||||
|
||||
QualType
|
||||
ASTContext::getTemplateSpecializationType(TemplateName Template,
|
||||
const TemplateArgument *Args,
|
||||
@ -2235,7 +2305,7 @@ CanQualType ASTContext::getCanonicalType(QualType T) {
|
||||
DSAT->getSizeExpr()->Retain() : 0,
|
||||
DSAT->getSizeModifier(),
|
||||
DSAT->getIndexTypeCVRQualifiers(),
|
||||
DSAT->getBracketsRange()));
|
||||
DSAT->getBracketsRange())->getCanonicalTypeInternal());
|
||||
|
||||
VariableArrayType *VAT = cast<VariableArrayType>(AT);
|
||||
return CanQualType::CreateUnsafe(getVariableArrayType(NewEltTy,
|
||||
@ -2290,17 +2360,14 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) {
|
||||
return Arg;
|
||||
|
||||
case TemplateArgument::Declaration:
|
||||
return TemplateArgument(SourceLocation(),
|
||||
Arg.getAsDecl()->getCanonicalDecl());
|
||||
return TemplateArgument(Arg.getAsDecl()->getCanonicalDecl());
|
||||
|
||||
case TemplateArgument::Integral:
|
||||
return TemplateArgument(SourceLocation(),
|
||||
*Arg.getAsIntegral(),
|
||||
return TemplateArgument(*Arg.getAsIntegral(),
|
||||
getCanonicalType(Arg.getIntegralType()));
|
||||
|
||||
case TemplateArgument::Type:
|
||||
return TemplateArgument(SourceLocation(),
|
||||
getCanonicalType(Arg.getAsType()));
|
||||
return TemplateArgument(getCanonicalType(Arg.getAsType()));
|
||||
|
||||
case TemplateArgument::Pack: {
|
||||
// FIXME: Allocate in ASTContext
|
||||
@ -2847,12 +2914,13 @@ QualType ASTContext::BuildByRefType(const char *DeclName, QualType Ty) {
|
||||
bool HasCopyAndDispose = BlockRequiresCopying(Ty);
|
||||
|
||||
// FIXME: Move up
|
||||
static int UniqueBlockByRefTypeID = 0;
|
||||
char Name[36];
|
||||
sprintf(Name, "__Block_byref_%d_%s", ++UniqueBlockByRefTypeID, DeclName);
|
||||
static unsigned int UniqueBlockByRefTypeID = 0;
|
||||
llvm::SmallString<36> Name;
|
||||
llvm::raw_svector_ostream(Name) << "__Block_byref_" <<
|
||||
++UniqueBlockByRefTypeID << '_' << DeclName;
|
||||
RecordDecl *T;
|
||||
T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
|
||||
&Idents.get(Name));
|
||||
&Idents.get(Name.str()));
|
||||
T->startDefinition();
|
||||
QualType Int32Ty = IntTy;
|
||||
assert(getIntWidth(IntTy) == 32 && "non-32bit int not supported");
|
||||
@ -2896,12 +2964,13 @@ QualType ASTContext::getBlockParmType(
|
||||
bool BlockHasCopyDispose,
|
||||
llvm::SmallVector<const Expr *, 8> &BlockDeclRefDecls) {
|
||||
// FIXME: Move up
|
||||
static int UniqueBlockParmTypeID = 0;
|
||||
char Name[36];
|
||||
sprintf(Name, "__block_literal_%u", ++UniqueBlockParmTypeID);
|
||||
static unsigned int UniqueBlockParmTypeID = 0;
|
||||
llvm::SmallString<36> Name;
|
||||
llvm::raw_svector_ostream(Name) << "__block_literal_"
|
||||
<< ++UniqueBlockParmTypeID;
|
||||
RecordDecl *T;
|
||||
T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(),
|
||||
&Idents.get(Name));
|
||||
&Idents.get(Name.str()));
|
||||
QualType FieldTypes[] = {
|
||||
getPointerType(VoidPtrTy),
|
||||
IntTy,
|
||||
@ -3409,7 +3478,10 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
|
||||
return;
|
||||
}
|
||||
|
||||
if (OPT->isObjCClassType()) {
|
||||
if (OPT->isObjCClassType() || OPT->isObjCQualifiedClassType()) {
|
||||
// FIXME: Consider if we need to output qualifiers for 'Class<p>'.
|
||||
// Since this is a binary compatibility issue, need to consult with runtime
|
||||
// folks. Fortunately, this is a *very* obsure construct.
|
||||
S += '#';
|
||||
return;
|
||||
}
|
||||
@ -3447,9 +3519,9 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
|
||||
}
|
||||
|
||||
S += '@';
|
||||
if (FD || EncodingProperty) {
|
||||
if (OPT->getInterfaceDecl() && (FD || EncodingProperty)) {
|
||||
S += '"';
|
||||
S += OPT->getInterfaceDecl()->getNameAsCString();
|
||||
S += OPT->getInterfaceDecl()->getIdentifier()->getName();
|
||||
for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(),
|
||||
E = OPT->qual_end(); I != E; ++I) {
|
||||
S += '<';
|
||||
@ -3590,12 +3662,42 @@ TemplateName ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS,
|
||||
return TemplateName(QTN);
|
||||
}
|
||||
|
||||
/// \brief Retrieve the template name that represents a dependent
|
||||
/// template name such as \c MetaFun::template operator+.
|
||||
TemplateName
|
||||
ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS,
|
||||
OverloadedOperatorKind Operator) {
|
||||
assert((!NNS || NNS->isDependent()) &&
|
||||
"Nested name specifier must be dependent");
|
||||
|
||||
llvm::FoldingSetNodeID ID;
|
||||
DependentTemplateName::Profile(ID, NNS, Operator);
|
||||
|
||||
void *InsertPos = 0;
|
||||
DependentTemplateName *QTN =
|
||||
DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
|
||||
|
||||
if (QTN)
|
||||
return TemplateName(QTN);
|
||||
|
||||
NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
|
||||
if (CanonNNS == NNS) {
|
||||
QTN = new (*this,4) DependentTemplateName(NNS, Operator);
|
||||
} else {
|
||||
TemplateName Canon = getDependentTemplateName(CanonNNS, Operator);
|
||||
QTN = new (*this,4) DependentTemplateName(NNS, Operator, Canon);
|
||||
}
|
||||
|
||||
DependentTemplateNames.InsertNode(QTN, InsertPos);
|
||||
return TemplateName(QTN);
|
||||
}
|
||||
|
||||
/// getFromTargetType - Given one of the integer types provided by
|
||||
/// TargetInfo, produce the corresponding type. The unsigned @p Type
|
||||
/// is actually a value of type @c TargetInfo::IntType.
|
||||
QualType ASTContext::getFromTargetType(unsigned Type) const {
|
||||
CanQualType ASTContext::getFromTargetType(unsigned Type) const {
|
||||
switch (Type) {
|
||||
case TargetInfo::NoInt: return QualType();
|
||||
case TargetInfo::NoInt: return CanQualType();
|
||||
case TargetInfo::SignedShort: return ShortTy;
|
||||
case TargetInfo::UnsignedShort: return UnsignedShortTy;
|
||||
case TargetInfo::SignedInt: return IntTy;
|
||||
@ -3607,7 +3709,7 @@ QualType ASTContext::getFromTargetType(unsigned Type) const {
|
||||
}
|
||||
|
||||
assert(false && "Unhandled TargetInfo::IntType value");
|
||||
return QualType();
|
||||
return CanQualType();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -3836,6 +3938,79 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT,
|
||||
return false;
|
||||
}
|
||||
|
||||
/// getIntersectionOfProtocols - This routine finds the intersection of set
|
||||
/// of protocols inherited from two distinct objective-c pointer objects.
|
||||
/// It is used to build composite qualifier list of the composite type of
|
||||
/// the conditional expression involving two objective-c pointer objects.
|
||||
static
|
||||
void getIntersectionOfProtocols(ASTContext &Context,
|
||||
const ObjCObjectPointerType *LHSOPT,
|
||||
const ObjCObjectPointerType *RHSOPT,
|
||||
llvm::SmallVectorImpl<ObjCProtocolDecl *> &IntersectionOfProtocols) {
|
||||
|
||||
const ObjCInterfaceType* LHS = LHSOPT->getInterfaceType();
|
||||
const ObjCInterfaceType* RHS = RHSOPT->getInterfaceType();
|
||||
|
||||
llvm::SmallPtrSet<ObjCProtocolDecl *, 8> InheritedProtocolSet;
|
||||
unsigned LHSNumProtocols = LHS->getNumProtocols();
|
||||
if (LHSNumProtocols > 0)
|
||||
InheritedProtocolSet.insert(LHS->qual_begin(), LHS->qual_end());
|
||||
else {
|
||||
llvm::SmallVector<ObjCProtocolDecl *, 8> LHSInheritedProtocols;
|
||||
Context.CollectInheritedProtocols(LHS->getDecl(), LHSInheritedProtocols);
|
||||
InheritedProtocolSet.insert(LHSInheritedProtocols.begin(),
|
||||
LHSInheritedProtocols.end());
|
||||
}
|
||||
|
||||
unsigned RHSNumProtocols = RHS->getNumProtocols();
|
||||
if (RHSNumProtocols > 0) {
|
||||
ObjCProtocolDecl **RHSProtocols = (ObjCProtocolDecl **)RHS->qual_begin();
|
||||
for (unsigned i = 0; i < RHSNumProtocols; ++i)
|
||||
if (InheritedProtocolSet.count(RHSProtocols[i]))
|
||||
IntersectionOfProtocols.push_back(RHSProtocols[i]);
|
||||
}
|
||||
else {
|
||||
llvm::SmallVector<ObjCProtocolDecl *, 8> RHSInheritedProtocols;
|
||||
Context.CollectInheritedProtocols(RHS->getDecl(), RHSInheritedProtocols);
|
||||
// FIXME. This may cause duplication of protocols in the list, but should
|
||||
// be harmless.
|
||||
for (unsigned i = 0, len = RHSInheritedProtocols.size(); i < len; ++i)
|
||||
if (InheritedProtocolSet.count(RHSInheritedProtocols[i]))
|
||||
IntersectionOfProtocols.push_back(RHSInheritedProtocols[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/// areCommonBaseCompatible - Returns common base class of the two classes if
|
||||
/// one found. Note that this is O'2 algorithm. But it will be called as the
|
||||
/// last type comparison in a ?-exp of ObjC pointer types before a
|
||||
/// warning is issued. So, its invokation is extremely rare.
|
||||
QualType ASTContext::areCommonBaseCompatible(
|
||||
const ObjCObjectPointerType *LHSOPT,
|
||||
const ObjCObjectPointerType *RHSOPT) {
|
||||
const ObjCInterfaceType* LHS = LHSOPT->getInterfaceType();
|
||||
const ObjCInterfaceType* RHS = RHSOPT->getInterfaceType();
|
||||
if (!LHS || !RHS)
|
||||
return QualType();
|
||||
|
||||
while (const ObjCInterfaceDecl *LHSIDecl = LHS->getDecl()->getSuperClass()) {
|
||||
QualType LHSTy = getObjCInterfaceType(LHSIDecl);
|
||||
LHS = LHSTy->getAs<ObjCInterfaceType>();
|
||||
if (canAssignObjCInterfaces(LHS, RHS)) {
|
||||
llvm::SmallVector<ObjCProtocolDecl *, 8> IntersectionOfProtocols;
|
||||
getIntersectionOfProtocols(*this,
|
||||
LHSOPT, RHSOPT, IntersectionOfProtocols);
|
||||
if (IntersectionOfProtocols.empty())
|
||||
LHSTy = getObjCObjectPointerType(LHSTy);
|
||||
else
|
||||
LHSTy = getObjCObjectPointerType(LHSTy, &IntersectionOfProtocols[0],
|
||||
IntersectionOfProtocols.size());
|
||||
return LHSTy;
|
||||
}
|
||||
}
|
||||
|
||||
return QualType();
|
||||
}
|
||||
|
||||
bool ASTContext::canAssignObjCInterfaces(const ObjCInterfaceType *LHS,
|
||||
const ObjCInterfaceType *RHS) {
|
||||
// Verify that the base decls are compatible: the RHS must be a subclass of
|
||||
|
@ -26,6 +26,7 @@ add_clang_library(clangAST
|
||||
StmtPrinter.cpp
|
||||
StmtProfile.cpp
|
||||
StmtViz.cpp
|
||||
TemplateBase.cpp
|
||||
TemplateName.cpp
|
||||
Type.cpp
|
||||
TypeLoc.cpp
|
||||
|
125
lib/AST/Decl.cpp
125
lib/AST/Decl.cpp
@ -91,13 +91,6 @@ ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC,
|
||||
return new (C) ParmVarDecl(ParmVar, DC, L, Id, T, DInfo, S, DefArg);
|
||||
}
|
||||
|
||||
QualType ParmVarDecl::getOriginalType() const {
|
||||
if (const OriginalParmVarDecl *PVD =
|
||||
dyn_cast<OriginalParmVarDecl>(this))
|
||||
return PVD->OriginalType;
|
||||
return getType();
|
||||
}
|
||||
|
||||
SourceRange ParmVarDecl::getDefaultArgRange() const {
|
||||
if (const Expr *E = getInit())
|
||||
return E->getSourceRange();
|
||||
@ -140,14 +133,6 @@ bool VarDecl::isExternC() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
OriginalParmVarDecl *OriginalParmVarDecl::Create(
|
||||
ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L, IdentifierInfo *Id,
|
||||
QualType T, DeclaratorInfo *DInfo,
|
||||
QualType OT, StorageClass S, Expr *DefArg) {
|
||||
return new (C) OriginalParmVarDecl(DC, L, Id, T, DInfo, OT, S, DefArg);
|
||||
}
|
||||
|
||||
FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L,
|
||||
DeclarationName N, QualType T,
|
||||
@ -193,9 +178,9 @@ void EnumConstantDecl::Destroy(ASTContext& C) {
|
||||
}
|
||||
|
||||
TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L,
|
||||
IdentifierInfo *Id, QualType T) {
|
||||
return new (C) TypedefDecl(DC, L, Id, T);
|
||||
SourceLocation L, IdentifierInfo *Id,
|
||||
DeclaratorInfo *DInfo) {
|
||||
return new (C) TypedefDecl(DC, L, Id, DInfo);
|
||||
}
|
||||
|
||||
EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
|
||||
@ -398,6 +383,19 @@ bool VarDecl::isOutOfLine() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
VarDecl *VarDecl::getOutOfLineDefinition() {
|
||||
if (!isStaticDataMember())
|
||||
return 0;
|
||||
|
||||
for (VarDecl::redecl_iterator RD = redecls_begin(), RDEnd = redecls_end();
|
||||
RD != RDEnd; ++RD) {
|
||||
if (RD->getLexicalDeclContext()->isFileContext())
|
||||
return *RD;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
VarDecl *VarDecl::getInstantiatedFromStaticDataMember() const {
|
||||
if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
|
||||
return cast<VarDecl>(MSI->getInstantiatedFrom());
|
||||
@ -644,7 +642,34 @@ unsigned FunctionDecl::getMinRequiredArguments() const {
|
||||
return NumRequiredArgs;
|
||||
}
|
||||
|
||||
/// \brief For an inline function definition in C, determine whether the
|
||||
bool FunctionDecl::isInlined() const {
|
||||
if (isInlineSpecified() || (isa<CXXMethodDecl>(this) && !isOutOfLine()))
|
||||
return true;
|
||||
|
||||
switch (getTemplateSpecializationKind()) {
|
||||
case TSK_Undeclared:
|
||||
case TSK_ExplicitSpecialization:
|
||||
return false;
|
||||
|
||||
case TSK_ImplicitInstantiation:
|
||||
case TSK_ExplicitInstantiationDeclaration:
|
||||
case TSK_ExplicitInstantiationDefinition:
|
||||
// Handle below.
|
||||
break;
|
||||
}
|
||||
|
||||
const FunctionDecl *PatternDecl = getTemplateInstantiationPattern();
|
||||
Stmt *Pattern = 0;
|
||||
if (PatternDecl)
|
||||
Pattern = PatternDecl->getBody(PatternDecl);
|
||||
|
||||
if (Pattern && PatternDecl)
|
||||
return PatternDecl->isInlined();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief For an inline function definition in C or C++, determine whether the
|
||||
/// definition will be externally visible.
|
||||
///
|
||||
/// Inline function definitions are always available for inlining optimizations.
|
||||
@ -663,9 +688,10 @@ unsigned FunctionDecl::getMinRequiredArguments() const {
|
||||
/// externally visible symbol.
|
||||
bool FunctionDecl::isInlineDefinitionExternallyVisible() const {
|
||||
assert(isThisDeclarationADefinition() && "Must have the function definition");
|
||||
assert(isInline() && "Function must be inline");
|
||||
assert(isInlined() && "Function must be inline");
|
||||
ASTContext &Context = getASTContext();
|
||||
|
||||
if (!getASTContext().getLangOptions().C99 || hasAttr<GNUInlineAttr>()) {
|
||||
if (!Context.getLangOptions().C99 || hasAttr<GNUInlineAttr>()) {
|
||||
// GNU inline semantics. Based on a number of examples, we came up with the
|
||||
// following heuristic: if the "inline" keyword is present on a
|
||||
// declaration of the function but "extern" is not present on that
|
||||
@ -675,7 +701,7 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const {
|
||||
for (redecl_iterator Redecl = redecls_begin(), RedeclEnd = redecls_end();
|
||||
Redecl != RedeclEnd;
|
||||
++Redecl) {
|
||||
if (Redecl->isInline() && Redecl->getStorageClass() != Extern)
|
||||
if (Redecl->isInlineSpecified() && Redecl->getStorageClass() != Extern)
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -694,7 +720,7 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const {
|
||||
if (!Redecl->getLexicalDeclContext()->isTranslationUnit())
|
||||
continue;
|
||||
|
||||
if (!Redecl->isInline() || Redecl->getStorageClass() == Extern)
|
||||
if (!Redecl->isInlineSpecified() || Redecl->getStorageClass() == Extern)
|
||||
return true; // Not an inline definition
|
||||
}
|
||||
|
||||
@ -755,6 +781,59 @@ FunctionDecl::setInstantiationOfMemberFunction(FunctionDecl *FD,
|
||||
TemplateOrSpecialization = Info;
|
||||
}
|
||||
|
||||
bool FunctionDecl::isImplicitlyInstantiable() const {
|
||||
// If this function already has a definition or is invalid, it can't be
|
||||
// implicitly instantiated.
|
||||
if (isInvalidDecl() || getBody())
|
||||
return false;
|
||||
|
||||
switch (getTemplateSpecializationKind()) {
|
||||
case TSK_Undeclared:
|
||||
case TSK_ExplicitSpecialization:
|
||||
case TSK_ExplicitInstantiationDefinition:
|
||||
return false;
|
||||
|
||||
case TSK_ImplicitInstantiation:
|
||||
return true;
|
||||
|
||||
case TSK_ExplicitInstantiationDeclaration:
|
||||
// Handled below.
|
||||
break;
|
||||
}
|
||||
|
||||
// Find the actual template from which we will instantiate.
|
||||
const FunctionDecl *PatternDecl = getTemplateInstantiationPattern();
|
||||
Stmt *Pattern = 0;
|
||||
if (PatternDecl)
|
||||
Pattern = PatternDecl->getBody(PatternDecl);
|
||||
|
||||
// C++0x [temp.explicit]p9:
|
||||
// Except for inline functions, other explicit instantiation declarations
|
||||
// have the effect of suppressing the implicit instantiation of the entity
|
||||
// to which they refer.
|
||||
if (!Pattern || !PatternDecl)
|
||||
return true;
|
||||
|
||||
return PatternDecl->isInlined();
|
||||
}
|
||||
|
||||
FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const {
|
||||
if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) {
|
||||
while (Primary->getInstantiatedFromMemberTemplate()) {
|
||||
// If we have hit a point where the user provided a specialization of
|
||||
// this template, we're done looking.
|
||||
if (Primary->isMemberSpecialization())
|
||||
break;
|
||||
|
||||
Primary = Primary->getInstantiatedFromMemberTemplate();
|
||||
}
|
||||
|
||||
return Primary->getTemplatedDecl();
|
||||
}
|
||||
|
||||
return getInstantiatedFromMemberFunction();
|
||||
}
|
||||
|
||||
FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const {
|
||||
if (FunctionTemplateSpecializationInfo *Info
|
||||
= TemplateOrSpecialization
|
||||
|
@ -199,7 +199,6 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
|
||||
case Var:
|
||||
case ImplicitParam:
|
||||
case ParmVar:
|
||||
case OriginalParmVar:
|
||||
case NonTypeTemplateParm:
|
||||
case Using:
|
||||
case UnresolvedUsing:
|
||||
|
@ -189,7 +189,10 @@ bool CXXRecordDecl::hasConstCopyAssignment(ASTContext &Context,
|
||||
// A user-declared copy assignment operator is a non-static non-template
|
||||
// member function of class X with exactly one parameter of type X, X&,
|
||||
// const X&, volatile X& or const volatile X&.
|
||||
const CXXMethodDecl* Method = cast<CXXMethodDecl>(*Op);
|
||||
const CXXMethodDecl* Method = dyn_cast<CXXMethodDecl>(*Op);
|
||||
if (!Method)
|
||||
continue;
|
||||
|
||||
if (Method->isStatic())
|
||||
continue;
|
||||
if (Method->getPrimaryTemplate())
|
||||
@ -364,34 +367,36 @@ CXXRecordDecl::getNestedVisibleConversionFunctions(CXXRecordDecl *RD,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (getNumBases() == 0 && getNumVBases() == 0)
|
||||
return;
|
||||
|
||||
|
||||
llvm::SmallPtrSet<CanQualType, 8> ConversionFunctions;
|
||||
if (!inTopClass)
|
||||
collectConversionFunctions(ConversionFunctions);
|
||||
|
||||
|
||||
for (CXXRecordDecl::base_class_iterator VBase = vbases_begin(),
|
||||
E = vbases_end(); VBase != E; ++VBase) {
|
||||
CXXRecordDecl *VBaseClassDecl
|
||||
= cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl());
|
||||
VBaseClassDecl->getNestedVisibleConversionFunctions(RD,
|
||||
TopConversionsTypeSet,
|
||||
(inTopClass ? TopConversionsTypeSet : ConversionFunctions));
|
||||
|
||||
if (const RecordType *RT = VBase->getType()->getAs<RecordType>()) {
|
||||
CXXRecordDecl *VBaseClassDecl
|
||||
= cast<CXXRecordDecl>(RT->getDecl());
|
||||
VBaseClassDecl->getNestedVisibleConversionFunctions(RD,
|
||||
TopConversionsTypeSet,
|
||||
(inTopClass ? TopConversionsTypeSet : ConversionFunctions));
|
||||
}
|
||||
}
|
||||
for (CXXRecordDecl::base_class_iterator Base = bases_begin(),
|
||||
E = bases_end(); Base != E; ++Base) {
|
||||
if (Base->isVirtual())
|
||||
continue;
|
||||
CXXRecordDecl *BaseClassDecl
|
||||
= cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
|
||||
|
||||
BaseClassDecl->getNestedVisibleConversionFunctions(RD,
|
||||
TopConversionsTypeSet,
|
||||
(inTopClass ? TopConversionsTypeSet : ConversionFunctions));
|
||||
|
||||
if (const RecordType *RT = Base->getType()->getAs<RecordType>()) {
|
||||
CXXRecordDecl *BaseClassDecl
|
||||
= cast<CXXRecordDecl>(RT->getDecl());
|
||||
|
||||
BaseClassDecl->getNestedVisibleConversionFunctions(RD,
|
||||
TopConversionsTypeSet,
|
||||
(inTopClass ? TopConversionsTypeSet : ConversionFunctions));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,6 +118,27 @@ ObjCContainerDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// FindPropertyVisibleInPrimaryClass - Finds declaration of the property
|
||||
/// with name 'PropertyId' in the primary class; including those in protocols
|
||||
/// (direct or indirect) used by the promary class.
|
||||
/// FIXME: Convert to DeclContext lookup...
|
||||
///
|
||||
ObjCPropertyDecl *
|
||||
ObjCContainerDecl::FindPropertyVisibleInPrimaryClass(
|
||||
IdentifierInfo *PropertyId) const {
|
||||
assert(isa<ObjCInterfaceDecl>(this) && "FindPropertyVisibleInPrimaryClass");
|
||||
for (prop_iterator I = prop_begin(), E = prop_end(); I != E; ++I)
|
||||
if ((*I)->getIdentifier() == PropertyId)
|
||||
return *I;
|
||||
const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(this);
|
||||
// Look through protocols.
|
||||
for (ObjCInterfaceDecl::protocol_iterator I = OID->protocol_begin(),
|
||||
E = OID->protocol_end(); I != E; ++I)
|
||||
if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId))
|
||||
return P;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
|
||||
ObjCProtocolDecl *const* ExtList, unsigned ExtNum,
|
||||
ASTContext &C)
|
||||
@ -288,7 +309,7 @@ ObjCMethodDecl *ObjCMethodDecl::getNextRedeclaration() {
|
||||
|
||||
} else if (ObjCCategoryImplDecl *CImplD =
|
||||
dyn_cast<ObjCCategoryImplDecl>(CtxD)) {
|
||||
if (ObjCCategoryDecl *CatD = CImplD->getCategoryClass())
|
||||
if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl())
|
||||
Redecl = CatD->getMethod(getSelector(), isInstanceMethod());
|
||||
}
|
||||
|
||||
@ -306,7 +327,7 @@ ObjCMethodDecl *ObjCMethodDecl::getCanonicalDecl() {
|
||||
|
||||
} else if (ObjCCategoryImplDecl *CImplD =
|
||||
dyn_cast<ObjCCategoryImplDecl>(CtxD)) {
|
||||
if (ObjCCategoryDecl *CatD = CImplD->getCategoryClass())
|
||||
if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl())
|
||||
if (ObjCMethodDecl *MD = CatD->getMethod(getSelector(),
|
||||
isInstanceMethod()))
|
||||
return MD;
|
||||
@ -635,7 +656,7 @@ ObjCCategoryImplDecl::Create(ASTContext &C, DeclContext *DC,
|
||||
return new (C) ObjCCategoryImplDecl(DC, L, Id, ClassInterface);
|
||||
}
|
||||
|
||||
ObjCCategoryDecl *ObjCCategoryImplDecl::getCategoryClass() const {
|
||||
ObjCCategoryDecl *ObjCCategoryImplDecl::getCategoryDecl() const {
|
||||
return getClassInterface()->FindCategoryDeclaration(getIdentifier());
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,6 @@ namespace {
|
||||
void VisitFieldDecl(FieldDecl *D);
|
||||
void VisitVarDecl(VarDecl *D);
|
||||
void VisitParmVarDecl(ParmVarDecl *D);
|
||||
void VisitOriginalParmVarDecl(OriginalParmVarDecl *D);
|
||||
void VisitFileScopeAsmDecl(FileScopeAsmDecl *D);
|
||||
void VisitOverloadedFunctionDecl(OverloadedFunctionDecl *D);
|
||||
void VisitNamespaceDecl(NamespaceDecl *D);
|
||||
@ -324,7 +323,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
|
||||
case FunctionDecl::PrivateExtern: Out << "__private_extern__ "; break;
|
||||
}
|
||||
|
||||
if (D->isInline()) Out << "inline ";
|
||||
if (D->isInlineSpecified()) Out << "inline ";
|
||||
if (D->isVirtualAsWritten()) Out << "virtual ";
|
||||
}
|
||||
|
||||
@ -489,7 +488,7 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
|
||||
|
||||
std::string Name = D->getNameAsString();
|
||||
QualType T = D->getType();
|
||||
if (OriginalParmVarDecl *Parm = dyn_cast<OriginalParmVarDecl>(D))
|
||||
if (ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D))
|
||||
T = Parm->getOriginalType();
|
||||
T.getAsStringInternal(Name, Policy);
|
||||
Out << Name;
|
||||
@ -508,10 +507,6 @@ void DeclPrinter::VisitParmVarDecl(ParmVarDecl *D) {
|
||||
VisitVarDecl(D);
|
||||
}
|
||||
|
||||
void DeclPrinter::VisitOriginalParmVarDecl(OriginalParmVarDecl *D) {
|
||||
VisitVarDecl(D);
|
||||
}
|
||||
|
||||
void DeclPrinter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) {
|
||||
Out << "__asm (";
|
||||
D->getAsmString()->printPretty(Out, Context, 0, Policy, Indentation);
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===--- DeclCXX.cpp - C++ Declaration AST Node Implementation ------------===//
|
||||
//===--- DeclTemplate.cpp - Template Declaration AST Node Implementation --===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -15,6 +15,7 @@
|
||||
#include "clang/AST/DeclTemplate.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/TypeLoc.h"
|
||||
#include "clang/Basic/IdentifierTable.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
using namespace clang;
|
||||
@ -67,6 +68,21 @@ unsigned TemplateParameterList::getMinRequiredArguments() const {
|
||||
return NumRequiredArgs;
|
||||
}
|
||||
|
||||
unsigned TemplateParameterList::getDepth() const {
|
||||
if (size() == 0)
|
||||
return 0;
|
||||
|
||||
const NamedDecl *FirstParm = getParam(0);
|
||||
if (const TemplateTypeParmDecl *TTP
|
||||
= dyn_cast<TemplateTypeParmDecl>(FirstParm))
|
||||
return TTP->getDepth();
|
||||
else if (const NonTypeTemplateParmDecl *NTTP
|
||||
= dyn_cast<NonTypeTemplateParmDecl>(FirstParm))
|
||||
return NTTP->getDepth();
|
||||
else
|
||||
return cast<TemplateTemplateParmDecl>(FirstParm)->getDepth();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// TemplateDecl Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -194,8 +210,7 @@ QualType ClassTemplateDecl::getInjectedClassNameType(ASTContext &Context) {
|
||||
Param != ParamEnd; ++Param) {
|
||||
if (isa<TemplateTypeParmDecl>(*Param)) {
|
||||
QualType ParamType = Context.getTypeDeclType(cast<TypeDecl>(*Param));
|
||||
TemplateArgs.push_back(TemplateArgument((*Param)->getLocation(),
|
||||
ParamType));
|
||||
TemplateArgs.push_back(TemplateArgument(ParamType));
|
||||
} else if (NonTypeTemplateParmDecl *NTTP =
|
||||
dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
|
||||
Expr *E = new (Context) DeclRefExpr(NTTP, NTTP->getType(),
|
||||
@ -205,7 +220,7 @@ QualType ClassTemplateDecl::getInjectedClassNameType(ASTContext &Context) {
|
||||
TemplateArgs.push_back(TemplateArgument(E));
|
||||
} else {
|
||||
TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*Param);
|
||||
TemplateArgs.push_back(TemplateArgument(TTP->getLocation(), TTP));
|
||||
TemplateArgs.push_back(TemplateArgument(TTP));
|
||||
}
|
||||
}
|
||||
|
||||
@ -229,6 +244,18 @@ TemplateTypeParmDecl::Create(ASTContext &C, DeclContext *DC,
|
||||
return new (C) TemplateTypeParmDecl(DC, L, Id, Typename, Type, ParameterPack);
|
||||
}
|
||||
|
||||
SourceLocation TemplateTypeParmDecl::getDefaultArgumentLoc() const {
|
||||
return DefaultArgument->getTypeLoc().getFullSourceRange().getBegin();
|
||||
}
|
||||
|
||||
unsigned TemplateTypeParmDecl::getDepth() const {
|
||||
return TypeForDecl->getAs<TemplateTypeParmType>()->getDepth();
|
||||
}
|
||||
|
||||
unsigned TemplateTypeParmDecl::getIndex() const {
|
||||
return TypeForDecl->getAs<TemplateTypeParmType>()->getIndex();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// NonTypeTemplateParmDecl Method Implementations
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -263,34 +290,6 @@ SourceLocation TemplateTemplateParmDecl::getDefaultArgumentLoc() const {
|
||||
: SourceLocation();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// TemplateArgument Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
TemplateArgument::TemplateArgument(Expr *E) : Kind(Expression) {
|
||||
TypeOrValue = reinterpret_cast<uintptr_t>(E);
|
||||
StartLoc = E->getSourceRange().getBegin();
|
||||
}
|
||||
|
||||
/// \brief Construct a template argument pack.
|
||||
void TemplateArgument::setArgumentPack(TemplateArgument *args, unsigned NumArgs,
|
||||
bool CopyArgs) {
|
||||
assert(isNull() && "Must call setArgumentPack on a null argument");
|
||||
|
||||
Kind = Pack;
|
||||
Args.NumArgs = NumArgs;
|
||||
Args.CopyArgs = CopyArgs;
|
||||
if (!Args.CopyArgs) {
|
||||
Args.Args = args;
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME: Allocate in ASTContext
|
||||
Args.Args = new TemplateArgument[NumArgs];
|
||||
for (unsigned I = 0; I != Args.NumArgs; ++I)
|
||||
Args.Args[I] = args[I];
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// TemplateArgumentListBuilder Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -459,12 +458,19 @@ Create(ASTContext &Context, DeclContext *DC, SourceLocation L,
|
||||
TemplateParameterList *Params,
|
||||
ClassTemplateDecl *SpecializedTemplate,
|
||||
TemplateArgumentListBuilder &Builder,
|
||||
TemplateArgumentLoc *ArgInfos, unsigned N,
|
||||
ClassTemplatePartialSpecializationDecl *PrevDecl) {
|
||||
TemplateArgumentLoc *ClonedArgs = new (Context) TemplateArgumentLoc[N];
|
||||
for (unsigned I = 0; I != N; ++I)
|
||||
ClonedArgs[I] = ArgInfos[I];
|
||||
|
||||
ClassTemplatePartialSpecializationDecl *Result
|
||||
= new (Context)ClassTemplatePartialSpecializationDecl(Context,
|
||||
DC, L, Params,
|
||||
SpecializedTemplate,
|
||||
Builder, PrevDecl);
|
||||
Builder,
|
||||
ClonedArgs, N,
|
||||
PrevDecl);
|
||||
Result->setSpecializationKind(TSK_ExplicitSpecialization);
|
||||
Context.getTypeDeclType(Result, PrevDecl);
|
||||
return Result;
|
||||
|
201
lib/AST/Expr.cpp
201
lib/AST/Expr.cpp
@ -22,6 +22,7 @@
|
||||
#include "clang/AST/StmtVisitor.h"
|
||||
#include "clang/Basic/Builtins.h"
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <algorithm>
|
||||
using namespace clang;
|
||||
@ -30,6 +31,91 @@ using namespace clang;
|
||||
// Primary Expressions.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
DeclRefExpr::DeclRefExpr(NestedNameSpecifier *Qualifier,
|
||||
SourceRange QualifierRange,
|
||||
NamedDecl *D, SourceLocation NameLoc,
|
||||
bool HasExplicitTemplateArgumentList,
|
||||
SourceLocation LAngleLoc,
|
||||
const TemplateArgumentLoc *ExplicitTemplateArgs,
|
||||
unsigned NumExplicitTemplateArgs,
|
||||
SourceLocation RAngleLoc,
|
||||
QualType T, bool TD, bool VD)
|
||||
: Expr(DeclRefExprClass, T, TD, VD),
|
||||
DecoratedD(D,
|
||||
(Qualifier? HasQualifierFlag : 0) |
|
||||
(HasExplicitTemplateArgumentList?
|
||||
HasExplicitTemplateArgumentListFlag : 0)),
|
||||
Loc(NameLoc) {
|
||||
if (Qualifier) {
|
||||
NameQualifier *NQ = getNameQualifier();
|
||||
NQ->NNS = Qualifier;
|
||||
NQ->Range = QualifierRange;
|
||||
}
|
||||
|
||||
if (HasExplicitTemplateArgumentList) {
|
||||
ExplicitTemplateArgumentList *ETemplateArgs
|
||||
= getExplicitTemplateArgumentList();
|
||||
ETemplateArgs->LAngleLoc = LAngleLoc;
|
||||
ETemplateArgs->RAngleLoc = RAngleLoc;
|
||||
ETemplateArgs->NumTemplateArgs = NumExplicitTemplateArgs;
|
||||
|
||||
TemplateArgumentLoc *TemplateArgs = ETemplateArgs->getTemplateArgs();
|
||||
for (unsigned I = 0; I < NumExplicitTemplateArgs; ++I)
|
||||
new (TemplateArgs + I) TemplateArgumentLoc(ExplicitTemplateArgs[I]);
|
||||
}
|
||||
}
|
||||
|
||||
DeclRefExpr *DeclRefExpr::Create(ASTContext &Context,
|
||||
NestedNameSpecifier *Qualifier,
|
||||
SourceRange QualifierRange,
|
||||
NamedDecl *D,
|
||||
SourceLocation NameLoc,
|
||||
QualType T, bool TD, bool VD) {
|
||||
return Create(Context, Qualifier, QualifierRange, D, NameLoc,
|
||||
false, SourceLocation(), 0, 0, SourceLocation(),
|
||||
T, TD, VD);
|
||||
}
|
||||
|
||||
DeclRefExpr *DeclRefExpr::Create(ASTContext &Context,
|
||||
NestedNameSpecifier *Qualifier,
|
||||
SourceRange QualifierRange,
|
||||
NamedDecl *D,
|
||||
SourceLocation NameLoc,
|
||||
bool HasExplicitTemplateArgumentList,
|
||||
SourceLocation LAngleLoc,
|
||||
const TemplateArgumentLoc *ExplicitTemplateArgs,
|
||||
unsigned NumExplicitTemplateArgs,
|
||||
SourceLocation RAngleLoc,
|
||||
QualType T, bool TD, bool VD) {
|
||||
std::size_t Size = sizeof(DeclRefExpr);
|
||||
if (Qualifier != 0)
|
||||
Size += sizeof(NameQualifier);
|
||||
|
||||
if (HasExplicitTemplateArgumentList)
|
||||
Size += sizeof(ExplicitTemplateArgumentList) +
|
||||
sizeof(TemplateArgumentLoc) * NumExplicitTemplateArgs;
|
||||
|
||||
void *Mem = Context.Allocate(Size, llvm::alignof<DeclRefExpr>());
|
||||
return new (Mem) DeclRefExpr(Qualifier, QualifierRange, D, NameLoc,
|
||||
HasExplicitTemplateArgumentList,
|
||||
LAngleLoc,
|
||||
ExplicitTemplateArgs,
|
||||
NumExplicitTemplateArgs,
|
||||
RAngleLoc,
|
||||
T, TD, VD);
|
||||
}
|
||||
|
||||
SourceRange DeclRefExpr::getSourceRange() const {
|
||||
// FIXME: Does not handle multi-token names well, e.g., operator[].
|
||||
SourceRange R(Loc);
|
||||
|
||||
if (hasQualifier())
|
||||
R.setBegin(getQualifierRange().getBegin());
|
||||
if (hasExplicitTemplateArgumentList())
|
||||
R.setEnd(getRAngleLoc());
|
||||
return R;
|
||||
}
|
||||
|
||||
// FIXME: Maybe this should use DeclPrinter with a special "print predefined
|
||||
// expr" policy instead.
|
||||
std::string PredefinedExpr::ComputeName(ASTContext &Context, IdentType IT,
|
||||
@ -343,7 +429,7 @@ MemberExpr::MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual,
|
||||
SourceRange qualrange, NamedDecl *memberdecl,
|
||||
SourceLocation l, bool has_explicit,
|
||||
SourceLocation langle,
|
||||
const TemplateArgument *targs, unsigned numtargs,
|
||||
const TemplateArgumentLoc *targs, unsigned numtargs,
|
||||
SourceLocation rangle, QualType ty)
|
||||
: Expr(MemberExprClass, ty,
|
||||
base->isTypeDependent() || (qual && qual->isDependent()),
|
||||
@ -365,9 +451,9 @@ MemberExpr::MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual,
|
||||
ETemplateArgs->RAngleLoc = rangle;
|
||||
ETemplateArgs->NumTemplateArgs = numtargs;
|
||||
|
||||
TemplateArgument *TemplateArgs = ETemplateArgs->getTemplateArgs();
|
||||
TemplateArgumentLoc *TemplateArgs = ETemplateArgs->getTemplateArgs();
|
||||
for (unsigned I = 0; I < numtargs; ++I)
|
||||
new (TemplateArgs + I) TemplateArgument(targs[I]);
|
||||
new (TemplateArgs + I) TemplateArgumentLoc(targs[I]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -378,7 +464,7 @@ MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow,
|
||||
SourceLocation l,
|
||||
bool has_explicit,
|
||||
SourceLocation langle,
|
||||
const TemplateArgument *targs,
|
||||
const TemplateArgumentLoc *targs,
|
||||
unsigned numtargs,
|
||||
SourceLocation rangle,
|
||||
QualType ty) {
|
||||
@ -388,7 +474,7 @@ MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow,
|
||||
|
||||
if (has_explicit)
|
||||
Size += sizeof(ExplicitTemplateArgumentList) +
|
||||
sizeof(TemplateArgument) * numtargs;
|
||||
sizeof(TemplateArgumentLoc) * numtargs;
|
||||
|
||||
void *Mem = C.Allocate(Size, llvm::alignof<MemberExpr>());
|
||||
return new (Mem) MemberExpr(base, isarrow, qual, qualrange, memberdecl, l,
|
||||
@ -418,6 +504,8 @@ const char *CastExpr::getCastKindName() const {
|
||||
return "NullToMemberPointer";
|
||||
case CastExpr::CK_BaseToDerivedMemberPointer:
|
||||
return "BaseToDerivedMemberPointer";
|
||||
case CastExpr::CK_DerivedToBaseMemberPointer:
|
||||
return "DerivedToBaseMemberPointer";
|
||||
case CastExpr::CK_UserDefinedConversion:
|
||||
return "UserDefinedConversion";
|
||||
case CastExpr::CK_ConstructorConversion:
|
||||
@ -610,7 +698,7 @@ Stmt *BlockExpr::getBody() {
|
||||
/// with location to warn on and the source range[s] to report with the
|
||||
/// warning.
|
||||
bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
|
||||
SourceRange &R2) const {
|
||||
SourceRange &R2, ASTContext &Ctx) const {
|
||||
// Don't warn if the expr is type dependent. The type could end up
|
||||
// instantiating to void.
|
||||
if (isTypeDependent())
|
||||
@ -623,7 +711,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
|
||||
return true;
|
||||
case ParenExprClass:
|
||||
return cast<ParenExpr>(this)->getSubExpr()->
|
||||
isUnusedResultAWarning(Loc, R1, R2);
|
||||
isUnusedResultAWarning(Loc, R1, R2, Ctx);
|
||||
case UnaryOperatorClass: {
|
||||
const UnaryOperator *UO = cast<UnaryOperator>(this);
|
||||
|
||||
@ -636,17 +724,18 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
|
||||
return false; // Not a warning.
|
||||
case UnaryOperator::Deref:
|
||||
// Dereferencing a volatile pointer is a side-effect.
|
||||
if (getType().isVolatileQualified())
|
||||
if (Ctx.getCanonicalType(getType()).isVolatileQualified())
|
||||
return false;
|
||||
break;
|
||||
case UnaryOperator::Real:
|
||||
case UnaryOperator::Imag:
|
||||
// accessing a piece of a volatile complex is a side-effect.
|
||||
if (UO->getSubExpr()->getType().isVolatileQualified())
|
||||
if (Ctx.getCanonicalType(UO->getSubExpr()->getType())
|
||||
.isVolatileQualified())
|
||||
return false;
|
||||
break;
|
||||
case UnaryOperator::Extension:
|
||||
return UO->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2);
|
||||
return UO->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx);
|
||||
}
|
||||
Loc = UO->getOperatorLoc();
|
||||
R1 = UO->getSubExpr()->getSourceRange();
|
||||
@ -656,8 +745,8 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
|
||||
const BinaryOperator *BO = cast<BinaryOperator>(this);
|
||||
// Consider comma to have side effects if the LHS or RHS does.
|
||||
if (BO->getOpcode() == BinaryOperator::Comma)
|
||||
return BO->getRHS()->isUnusedResultAWarning(Loc, R1, R2) ||
|
||||
BO->getLHS()->isUnusedResultAWarning(Loc, R1, R2);
|
||||
return (BO->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx) ||
|
||||
BO->getLHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx));
|
||||
|
||||
if (BO->isAssignmentOp())
|
||||
return false;
|
||||
@ -674,15 +763,15 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
|
||||
// warning, warn about them.
|
||||
const ConditionalOperator *Exp = cast<ConditionalOperator>(this);
|
||||
if (Exp->getLHS() &&
|
||||
Exp->getLHS()->isUnusedResultAWarning(Loc, R1, R2))
|
||||
Exp->getLHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx))
|
||||
return true;
|
||||
return Exp->getRHS()->isUnusedResultAWarning(Loc, R1, R2);
|
||||
return Exp->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx);
|
||||
}
|
||||
|
||||
case MemberExprClass:
|
||||
// If the base pointer or element is to a volatile pointer/field, accessing
|
||||
// it is a side effect.
|
||||
if (getType().isVolatileQualified())
|
||||
if (Ctx.getCanonicalType(getType()).isVolatileQualified())
|
||||
return false;
|
||||
Loc = cast<MemberExpr>(this)->getMemberLoc();
|
||||
R1 = SourceRange(Loc, Loc);
|
||||
@ -692,7 +781,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
|
||||
case ArraySubscriptExprClass:
|
||||
// If the base pointer or element is to a volatile pointer/field, accessing
|
||||
// it is a side effect.
|
||||
if (getType().isVolatileQualified())
|
||||
if (Ctx.getCanonicalType(getType()).isVolatileQualified())
|
||||
return false;
|
||||
Loc = cast<ArraySubscriptExpr>(this)->getRBracketLoc();
|
||||
R1 = cast<ArraySubscriptExpr>(this)->getLHS()->getSourceRange();
|
||||
@ -750,7 +839,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
|
||||
const CompoundStmt *CS = cast<StmtExpr>(this)->getSubStmt();
|
||||
if (!CS->body_empty())
|
||||
if (const Expr *E = dyn_cast<Expr>(CS->body_back()))
|
||||
return E->isUnusedResultAWarning(Loc, R1, R2);
|
||||
return E->isUnusedResultAWarning(Loc, R1, R2, Ctx);
|
||||
|
||||
Loc = cast<StmtExpr>(this)->getLParenLoc();
|
||||
R1 = getSourceRange();
|
||||
@ -768,20 +857,20 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
|
||||
// If this is a cast to void, check the operand. Otherwise, the result of
|
||||
// the cast is unused.
|
||||
if (getType()->isVoidType())
|
||||
return cast<CastExpr>(this)->getSubExpr()
|
||||
->isUnusedResultAWarning(Loc, R1, R2);
|
||||
return (cast<CastExpr>(this)->getSubExpr()
|
||||
->isUnusedResultAWarning(Loc, R1, R2, Ctx));
|
||||
Loc = cast<CXXFunctionalCastExpr>(this)->getTypeBeginLoc();
|
||||
R1 = cast<CXXFunctionalCastExpr>(this)->getSubExpr()->getSourceRange();
|
||||
return true;
|
||||
|
||||
case ImplicitCastExprClass:
|
||||
// Check the operand, since implicit casts are inserted by Sema
|
||||
return cast<ImplicitCastExpr>(this)
|
||||
->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2);
|
||||
return (cast<ImplicitCastExpr>(this)
|
||||
->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx));
|
||||
|
||||
case CXXDefaultArgExprClass:
|
||||
return cast<CXXDefaultArgExpr>(this)
|
||||
->getExpr()->isUnusedResultAWarning(Loc, R1, R2);
|
||||
return (cast<CXXDefaultArgExpr>(this)
|
||||
->getExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx));
|
||||
|
||||
case CXXNewExprClass:
|
||||
// FIXME: In theory, there might be new expressions that don't have side
|
||||
@ -789,11 +878,11 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
|
||||
case CXXDeleteExprClass:
|
||||
return false;
|
||||
case CXXBindTemporaryExprClass:
|
||||
return cast<CXXBindTemporaryExpr>(this)
|
||||
->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2);
|
||||
return (cast<CXXBindTemporaryExpr>(this)
|
||||
->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx));
|
||||
case CXXExprWithTemporariesClass:
|
||||
return cast<CXXExprWithTemporaries>(this)
|
||||
->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2);
|
||||
return (cast<CXXExprWithTemporaries>(this)
|
||||
->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx));
|
||||
}
|
||||
}
|
||||
|
||||
@ -855,8 +944,7 @@ Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const {
|
||||
if (cast<ArraySubscriptExpr>(this)->getBase()->getType()->isVectorType())
|
||||
return cast<ArraySubscriptExpr>(this)->getBase()->isLvalue(Ctx);
|
||||
return LV_Valid;
|
||||
case DeclRefExprClass:
|
||||
case QualifiedDeclRefExprClass: { // C99 6.5.1p2
|
||||
case DeclRefExprClass: { // C99 6.5.1p2
|
||||
const NamedDecl *RefdDecl = cast<DeclRefExpr>(this)->getDecl();
|
||||
if (DeclCanBeLvalue(RefdDecl, Ctx))
|
||||
return LV_Valid;
|
||||
@ -1042,6 +1130,18 @@ Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const {
|
||||
return LV_Valid;
|
||||
}
|
||||
|
||||
case TemplateIdRefExprClass: {
|
||||
const TemplateIdRefExpr *TID = cast<TemplateIdRefExpr>(this);
|
||||
TemplateName Template = TID->getTemplateName();
|
||||
NamedDecl *ND = Template.getAsTemplateDecl();
|
||||
if (!ND)
|
||||
ND = Template.getAsOverloadedFunctionDecl();
|
||||
if (ND && DeclCanBeLvalue(ND, Ctx))
|
||||
return LV_Valid;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1133,8 +1233,7 @@ bool Expr::isOBJCGCCandidate(ASTContext &Ctx) const {
|
||||
return cast<ImplicitCastExpr>(this)->getSubExpr()->isOBJCGCCandidate(Ctx);
|
||||
case CStyleCastExprClass:
|
||||
return cast<CStyleCastExpr>(this)->getSubExpr()->isOBJCGCCandidate(Ctx);
|
||||
case DeclRefExprClass:
|
||||
case QualifiedDeclRefExprClass: {
|
||||
case DeclRefExprClass: {
|
||||
const Decl *D = cast<DeclRefExpr>(this)->getDecl();
|
||||
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
|
||||
if (VD->hasGlobalStorage())
|
||||
@ -1432,7 +1531,6 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
|
||||
return ICEDiag(2, E->getLocStart());
|
||||
}
|
||||
case Expr::DeclRefExprClass:
|
||||
case Expr::QualifiedDeclRefExprClass:
|
||||
if (isa<EnumConstantDecl>(cast<DeclRefExpr>(E)->getDecl()))
|
||||
return NoDiag();
|
||||
if (Ctx.getLangOptions().CPlusPlus &&
|
||||
@ -1442,16 +1540,35 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
|
||||
// type initialized by an ICE can be used in ICEs.
|
||||
if (const VarDecl *Dcl =
|
||||
dyn_cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl())) {
|
||||
if (Dcl->isInitKnownICE()) {
|
||||
// We have already checked whether this subexpression is an
|
||||
// integral constant expression.
|
||||
if (Dcl->isInitICE())
|
||||
return NoDiag();
|
||||
else
|
||||
return ICEDiag(2, E->getLocStart());
|
||||
}
|
||||
Qualifiers Quals = Ctx.getCanonicalType(Dcl->getType()).getQualifiers();
|
||||
if (Quals.hasVolatile() || !Quals.hasConst())
|
||||
return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation());
|
||||
|
||||
// Look for the definition of this variable, which will actually have
|
||||
// an initializer.
|
||||
const VarDecl *Def = 0;
|
||||
const Expr *Init = Dcl->getDefinition(Def);
|
||||
if (Init) {
|
||||
if (Def->isInitKnownICE()) {
|
||||
// We have already checked whether this subexpression is an
|
||||
// integral constant expression.
|
||||
if (Def->isInitICE())
|
||||
return NoDiag();
|
||||
else
|
||||
return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation());
|
||||
}
|
||||
|
||||
if (const Expr *Init = Dcl->getInit()) {
|
||||
// C++ [class.static.data]p4:
|
||||
// If a static data member is of const integral or const
|
||||
// enumeration type, its declaration in the class definition can
|
||||
// specify a constant-initializer which shall be an integral
|
||||
// constant expression (5.19). In that case, the member can appear
|
||||
// in integral constant expressions.
|
||||
if (Def->isOutOfLine()) {
|
||||
Dcl->setInitKnownICE(Ctx, false);
|
||||
return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation());
|
||||
}
|
||||
|
||||
ICEDiag Result = CheckICE(Init, Ctx);
|
||||
// Cache the result of the ICE test.
|
||||
Dcl->setInitKnownICE(Ctx, Result.Val == 0);
|
||||
@ -1654,7 +1771,7 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx,
|
||||
}
|
||||
EvalResult EvalResult;
|
||||
if (!Evaluate(EvalResult, Ctx))
|
||||
assert(0 && "ICE cannot be evaluated!");
|
||||
llvm::llvm_unreachable("ICE cannot be evaluated!");
|
||||
assert(!EvalResult.HasSideEffects && "ICE with side effects!");
|
||||
assert(EvalResult.Val.isInt() && "ICE that isn't integer!");
|
||||
Result = EvalResult.Val.getInt();
|
||||
|
@ -151,7 +151,7 @@ TemplateIdRefExpr::TemplateIdRefExpr(QualType T,
|
||||
TemplateName Template,
|
||||
SourceLocation TemplateNameLoc,
|
||||
SourceLocation LAngleLoc,
|
||||
const TemplateArgument *TemplateArgs,
|
||||
const TemplateArgumentLoc *TemplateArgs,
|
||||
unsigned NumTemplateArgs,
|
||||
SourceLocation RAngleLoc)
|
||||
: Expr(TemplateIdRefExprClass, T,
|
||||
@ -164,10 +164,10 @@ TemplateIdRefExpr::TemplateIdRefExpr(QualType T,
|
||||
Qualifier(Qualifier), QualifierRange(QualifierRange), Template(Template),
|
||||
TemplateNameLoc(TemplateNameLoc), LAngleLoc(LAngleLoc),
|
||||
RAngleLoc(RAngleLoc), NumTemplateArgs(NumTemplateArgs) {
|
||||
TemplateArgument *StoredTemplateArgs
|
||||
= reinterpret_cast<TemplateArgument *> (this+1);
|
||||
TemplateArgumentLoc *StoredTemplateArgs
|
||||
= reinterpret_cast<TemplateArgumentLoc *> (this+1);
|
||||
for (unsigned I = 0; I != NumTemplateArgs; ++I)
|
||||
new (StoredTemplateArgs + I) TemplateArgument(TemplateArgs[I]);
|
||||
new (StoredTemplateArgs + I) TemplateArgumentLoc(TemplateArgs[I]);
|
||||
}
|
||||
|
||||
TemplateIdRefExpr *
|
||||
@ -176,19 +176,19 @@ TemplateIdRefExpr::Create(ASTContext &Context, QualType T,
|
||||
SourceRange QualifierRange,
|
||||
TemplateName Template, SourceLocation TemplateNameLoc,
|
||||
SourceLocation LAngleLoc,
|
||||
const TemplateArgument *TemplateArgs,
|
||||
const TemplateArgumentLoc *TemplateArgs,
|
||||
unsigned NumTemplateArgs, SourceLocation RAngleLoc) {
|
||||
void *Mem = Context.Allocate(sizeof(TemplateIdRefExpr) +
|
||||
sizeof(TemplateArgument) * NumTemplateArgs);
|
||||
sizeof(TemplateArgumentLoc) * NumTemplateArgs);
|
||||
return new (Mem) TemplateIdRefExpr(T, Qualifier, QualifierRange, Template,
|
||||
TemplateNameLoc, LAngleLoc, TemplateArgs,
|
||||
NumTemplateArgs, RAngleLoc);
|
||||
}
|
||||
|
||||
void TemplateIdRefExpr::DoDestroy(ASTContext &Context) {
|
||||
const TemplateArgument *TemplateArgs = getTemplateArgs();
|
||||
const TemplateArgumentLoc *TemplateArgs = getTemplateArgs();
|
||||
for (unsigned I = 0; I != NumTemplateArgs; ++I)
|
||||
if (Expr *E = TemplateArgs[I].getAsExpr())
|
||||
if (Expr *E = TemplateArgs[I].getArgument().getAsExpr())
|
||||
E->Destroy(Context);
|
||||
this->~TemplateIdRefExpr();
|
||||
Context.Deallocate(this);
|
||||
@ -528,7 +528,7 @@ CXXUnresolvedMemberExpr::CXXUnresolvedMemberExpr(ASTContext &C,
|
||||
SourceLocation MemberLoc,
|
||||
bool HasExplicitTemplateArgs,
|
||||
SourceLocation LAngleLoc,
|
||||
const TemplateArgument *TemplateArgs,
|
||||
const TemplateArgumentLoc *TemplateArgs,
|
||||
unsigned NumTemplateArgs,
|
||||
SourceLocation RAngleLoc)
|
||||
: Expr(CXXUnresolvedMemberExprClass, C.DependentTy, true, true),
|
||||
@ -545,9 +545,9 @@ CXXUnresolvedMemberExpr::CXXUnresolvedMemberExpr(ASTContext &C,
|
||||
ETemplateArgs->RAngleLoc = RAngleLoc;
|
||||
ETemplateArgs->NumTemplateArgs = NumTemplateArgs;
|
||||
|
||||
TemplateArgument *SavedTemplateArgs = ETemplateArgs->getTemplateArgs();
|
||||
TemplateArgumentLoc *SavedTemplateArgs = ETemplateArgs->getTemplateArgs();
|
||||
for (unsigned I = 0; I < NumTemplateArgs; ++I)
|
||||
new (SavedTemplateArgs + I) TemplateArgument(TemplateArgs[I]);
|
||||
new (SavedTemplateArgs + I) TemplateArgumentLoc(TemplateArgs[I]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -562,7 +562,7 @@ CXXUnresolvedMemberExpr::Create(ASTContext &C,
|
||||
SourceLocation MemberLoc,
|
||||
bool HasExplicitTemplateArgs,
|
||||
SourceLocation LAngleLoc,
|
||||
const TemplateArgument *TemplateArgs,
|
||||
const TemplateArgumentLoc *TemplateArgs,
|
||||
unsigned NumTemplateArgs,
|
||||
SourceLocation RAngleLoc) {
|
||||
if (!HasExplicitTemplateArgs)
|
||||
@ -573,7 +573,7 @@ CXXUnresolvedMemberExpr::Create(ASTContext &C,
|
||||
|
||||
void *Mem = C.Allocate(sizeof(CXXUnresolvedMemberExpr) +
|
||||
sizeof(ExplicitTemplateArgumentList) +
|
||||
sizeof(TemplateArgument) * NumTemplateArgs,
|
||||
sizeof(TemplateArgumentLoc) * NumTemplateArgs,
|
||||
llvm::alignof<CXXUnresolvedMemberExpr>());
|
||||
return new (Mem) CXXUnresolvedMemberExpr(C, Base, IsArrow, OperatorLoc,
|
||||
Qualifier, QualifierRange,
|
||||
|
@ -58,7 +58,8 @@ struct EvalInfo {
|
||||
static bool EvaluateLValue(const Expr *E, APValue &Result, EvalInfo &Info);
|
||||
static bool EvaluatePointer(const Expr *E, APValue &Result, EvalInfo &Info);
|
||||
static bool EvaluateInteger(const Expr *E, APSInt &Result, EvalInfo &Info);
|
||||
static bool EvaluateIntegerOrLValue(const Expr *E, APValue &Result, EvalInfo &Info);
|
||||
static bool EvaluateIntegerOrLValue(const Expr *E, APValue &Result,
|
||||
EvalInfo &Info);
|
||||
static bool EvaluateFloat(const Expr *E, APFloat &Result, EvalInfo &Info);
|
||||
static bool EvaluateComplex(const Expr *E, APValue &Result, EvalInfo &Info);
|
||||
|
||||
@ -151,6 +152,67 @@ static APFloat HandleIntToFloatCast(QualType DestType, QualType SrcType,
|
||||
return Result;
|
||||
}
|
||||
|
||||
namespace {
|
||||
class VISIBILITY_HIDDEN HasSideEffect
|
||||
: public StmtVisitor<HasSideEffect, bool> {
|
||||
EvalInfo &Info;
|
||||
public:
|
||||
|
||||
HasSideEffect(EvalInfo &info) : Info(info) {}
|
||||
|
||||
// Unhandled nodes conservatively default to having side effects.
|
||||
bool VisitStmt(Stmt *S) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
|
||||
bool VisitDeclRefExpr(DeclRefExpr *E) {
|
||||
if (Info.Ctx.getCanonicalType(E->getType()).isVolatileQualified())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
// We don't want to evaluate BlockExprs multiple times, as they generate
|
||||
// a ton of code.
|
||||
bool VisitBlockExpr(BlockExpr *E) { return true; }
|
||||
bool VisitPredefinedExpr(PredefinedExpr *E) { return false; }
|
||||
bool VisitCompoundLiteralExpr(CompoundLiteralExpr *E)
|
||||
{ return Visit(E->getInitializer()); }
|
||||
bool VisitMemberExpr(MemberExpr *E) { return Visit(E->getBase()); }
|
||||
bool VisitIntegerLiteral(IntegerLiteral *E) { return false; }
|
||||
bool VisitFloatingLiteral(FloatingLiteral *E) { return false; }
|
||||
bool VisitStringLiteral(StringLiteral *E) { return false; }
|
||||
bool VisitCharacterLiteral(CharacterLiteral *E) { return false; }
|
||||
bool VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { return false; }
|
||||
bool VisitArraySubscriptExpr(ArraySubscriptExpr *E)
|
||||
{ return Visit(E->getLHS()) || Visit(E->getRHS()); }
|
||||
bool VisitChooseExpr(ChooseExpr *E)
|
||||
{ return Visit(E->getChosenSubExpr(Info.Ctx)); }
|
||||
bool VisitCastExpr(CastExpr *E) { return Visit(E->getSubExpr()); }
|
||||
bool VisitBinAssign(BinaryOperator *E) { return true; }
|
||||
bool VisitCompoundAssignOperator(BinaryOperator *E) { return true; }
|
||||
bool VisitBinaryOperator(BinaryOperator *E)
|
||||
{ return Visit(E->getLHS()) || Visit(E->getRHS()); }
|
||||
bool VisitUnaryPreInc(UnaryOperator *E) { return true; }
|
||||
bool VisitUnaryPostInc(UnaryOperator *E) { return true; }
|
||||
bool VisitUnaryPreDec(UnaryOperator *E) { return true; }
|
||||
bool VisitUnaryPostDec(UnaryOperator *E) { return true; }
|
||||
bool VisitUnaryDeref(UnaryOperator *E) {
|
||||
if (Info.Ctx.getCanonicalType(E->getType()).isVolatileQualified())
|
||||
return true;
|
||||
return Visit(E->getSubExpr());
|
||||
}
|
||||
bool VisitUnaryOperator(UnaryOperator *E) { return Visit(E->getSubExpr()); }
|
||||
};
|
||||
|
||||
bool HasSideEffects(const Expr* E, ASTContext &Ctx) {
|
||||
Expr::EvalResult Result;
|
||||
EvalInfo Info(Ctx, Result);
|
||||
|
||||
return HasSideEffect(Info).Visit(const_cast<Expr*>(E));
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// LValue Evaluation
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -208,8 +270,9 @@ APValue LValueExprEvaluator::VisitDeclRefExpr(DeclRefExpr *E) {
|
||||
if (!VD->getType()->isReferenceType())
|
||||
return APValue(E, 0);
|
||||
// FIXME: Check whether VD might be overridden!
|
||||
if (VD->getInit())
|
||||
return Visit(VD->getInit());
|
||||
const VarDecl *Def = 0;
|
||||
if (const Expr *Init = VD->getDefinition(Def))
|
||||
return Visit(const_cast<Expr *>(Init));
|
||||
}
|
||||
|
||||
return APValue();
|
||||
@ -793,11 +856,14 @@ bool IntExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) {
|
||||
|
||||
// In C++, const, non-volatile integers initialized with ICEs are ICEs.
|
||||
// In C, they can also be folded, although they are not ICEs.
|
||||
if (E->getType().getCVRQualifiers() == Qualifiers::Const) {
|
||||
if (Info.Ctx.getCanonicalType(E->getType()).getCVRQualifiers()
|
||||
== Qualifiers::Const) {
|
||||
if (const VarDecl *D = dyn_cast<VarDecl>(E->getDecl())) {
|
||||
if (APValue *V = D->getEvaluatedValue())
|
||||
return Success(V->getInt(), E);
|
||||
if (const Expr *Init = D->getInit()) {
|
||||
const VarDecl *Def = 0;
|
||||
if (const Expr *Init = D->getDefinition(Def)) {
|
||||
if (APValue *V = D->getEvaluatedValue())
|
||||
return Success(V->getInt(), E);
|
||||
|
||||
if (Visit(const_cast<Expr*>(Init))) {
|
||||
// Cache the evaluated value in the variable declaration.
|
||||
D->setEvaluatedValue(Info.Ctx, Result);
|
||||
@ -873,6 +939,40 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
|
||||
switch (E->isBuiltinCall(Info.Ctx)) {
|
||||
default:
|
||||
return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E);
|
||||
|
||||
case Builtin::BI__builtin_object_size: {
|
||||
const Expr *Arg = E->getArg(0)->IgnoreParens();
|
||||
Expr::EvalResult Base;
|
||||
if (Arg->EvaluateAsAny(Base, Info.Ctx)
|
||||
&& Base.Val.getKind() == APValue::LValue
|
||||
&& !Base.HasSideEffects)
|
||||
if (const Expr *LVBase = Base.Val.getLValueBase())
|
||||
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(LVBase)) {
|
||||
if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
|
||||
if (!VD->getType()->isIncompleteType()
|
||||
&& VD->getType()->isObjectType()
|
||||
&& !VD->getType()->isVariablyModifiedType()
|
||||
&& !VD->getType()->isDependentType()) {
|
||||
uint64_t Size = Info.Ctx.getTypeSize(VD->getType()) / 8;
|
||||
uint64_t Offset = Base.Val.getLValueOffset();
|
||||
if (Offset <= Size)
|
||||
Size -= Base.Val.getLValueOffset();
|
||||
else
|
||||
Size = 0;
|
||||
return Success(Size, E);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (HasSideEffects(E->getArg(0), Info.Ctx)) {
|
||||
if (E->getArg(1)->EvaluateAsInt(Info.Ctx).getZExtValue() < 2)
|
||||
return Success(-1ULL, E);
|
||||
return Success(0, E);
|
||||
}
|
||||
|
||||
return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E);
|
||||
}
|
||||
|
||||
case Builtin::BI__builtin_classify_type:
|
||||
return Success(EvaluateBuiltinClassifyType(E), E);
|
||||
|
||||
@ -1801,6 +1901,33 @@ bool Expr::Evaluate(EvalResult &Result, ASTContext &Ctx) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Expr::EvaluateAsAny(EvalResult &Result, ASTContext &Ctx) const {
|
||||
EvalInfo Info(Ctx, Result, true);
|
||||
|
||||
if (getType()->isVectorType()) {
|
||||
if (!EvaluateVector(this, Result.Val, Info))
|
||||
return false;
|
||||
} else if (getType()->isIntegerType()) {
|
||||
if (!IntExprEvaluator(Info, Result.Val).Visit(const_cast<Expr*>(this)))
|
||||
return false;
|
||||
} else if (getType()->hasPointerRepresentation()) {
|
||||
if (!EvaluatePointer(this, Result.Val, Info))
|
||||
return false;
|
||||
} else if (getType()->isRealFloatingType()) {
|
||||
llvm::APFloat f(0.0);
|
||||
if (!EvaluateFloat(this, f, Info))
|
||||
return false;
|
||||
|
||||
Result.Val = APValue(f);
|
||||
} else if (getType()->isAnyComplexType()) {
|
||||
if (!EvaluateComplex(this, Result.Val, Info))
|
||||
return false;
|
||||
} else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Expr::EvaluateAsLValue(EvalResult &Result, ASTContext &Ctx) const {
|
||||
EvalInfo Info(Ctx, Result);
|
||||
|
||||
|
@ -47,6 +47,8 @@ ASTRecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) {
|
||||
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
|
||||
e = RD->bases_end(); i != e; ++i) {
|
||||
if (!i->isVirtual()) {
|
||||
assert(!i->getType()->isDependentType() &&
|
||||
"Cannot layout class with dependent bases.");
|
||||
const CXXRecordDecl *Base =
|
||||
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
|
||||
// Skip the PrimaryBase here, as it is laid down first.
|
||||
@ -82,6 +84,8 @@ void ASTRecordLayoutBuilder::IdentifyPrimaryBases(const CXXRecordDecl *RD) {
|
||||
// Now traverse all bases and find primary bases for them.
|
||||
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
|
||||
e = RD->bases_end(); i != e; ++i) {
|
||||
assert(!i->getType()->isDependentType() &&
|
||||
"Cannot layout class with dependent bases.");
|
||||
const CXXRecordDecl *Base =
|
||||
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
|
||||
|
||||
@ -97,6 +101,8 @@ ASTRecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD,
|
||||
const CXXRecordDecl *&FirstPrimary) {
|
||||
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
|
||||
e = RD->bases_end(); i != e; ++i) {
|
||||
assert(!i->getType()->isDependentType() &&
|
||||
"Cannot layout class with dependent bases.");
|
||||
const CXXRecordDecl *Base =
|
||||
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
|
||||
if (!i->isVirtual()) {
|
||||
@ -123,6 +129,8 @@ void ASTRecordLayoutBuilder::SelectPrimaryBase(const CXXRecordDecl *RD) {
|
||||
// indirect bases, and record all their primary virtual base classes.
|
||||
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
|
||||
e = RD->bases_end(); i != e; ++i) {
|
||||
assert(!i->getType()->isDependentType() &&
|
||||
"Cannot layout class with dependent bases.");
|
||||
const CXXRecordDecl *Base =
|
||||
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
|
||||
IdentifyPrimaryBases(Base);
|
||||
@ -173,6 +181,8 @@ void ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD,
|
||||
llvm::SmallSet<const CXXRecordDecl*, 32> &IndirectPrimary) {
|
||||
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
|
||||
e = RD->bases_end(); i != e; ++i) {
|
||||
assert(!i->getType()->isDependentType() &&
|
||||
"Cannot layout class with dependent bases.");
|
||||
const CXXRecordDecl *Base =
|
||||
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
|
||||
#if 0
|
||||
@ -235,6 +245,8 @@ bool ASTRecordLayoutBuilder::canPlaceRecordAtOffset(const CXXRecordDecl *RD,
|
||||
// Check bases.
|
||||
for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
|
||||
E = RD->bases_end(); I != E; ++I) {
|
||||
assert(!I->getType()->isDependentType() &&
|
||||
"Cannot layout class with dependent bases.");
|
||||
if (I->isVirtual())
|
||||
continue;
|
||||
|
||||
@ -305,6 +317,8 @@ void ASTRecordLayoutBuilder::UpdateEmptyClassOffsets(const CXXRecordDecl *RD,
|
||||
// Update bases.
|
||||
for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
|
||||
E = RD->bases_end(); I != E; ++I) {
|
||||
assert(!I->getType()->isDependentType() &&
|
||||
"Cannot layout class with dependent bases.");
|
||||
if (I->isVirtual())
|
||||
continue;
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/SmallSet.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/System/DataTypes.h"
|
||||
#include <map>
|
||||
|
||||
namespace clang {
|
||||
|
@ -473,14 +473,14 @@ void StmtPrinter::VisitExpr(Expr *Node) {
|
||||
}
|
||||
|
||||
void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) {
|
||||
if (NestedNameSpecifier *Qualifier = Node->getQualifier())
|
||||
Qualifier->print(OS, Policy);
|
||||
OS << Node->getDecl()->getNameAsString();
|
||||
}
|
||||
|
||||
void StmtPrinter::VisitQualifiedDeclRefExpr(QualifiedDeclRefExpr *Node) {
|
||||
NamedDecl *D = Node->getDecl();
|
||||
|
||||
Node->getQualifier()->print(OS, Policy);
|
||||
OS << D->getNameAsString();
|
||||
if (Node->hasExplicitTemplateArgumentList())
|
||||
OS << TemplateSpecializationType::PrintTemplateArgumentList(
|
||||
Node->getTemplateArgs(),
|
||||
Node->getNumTemplateArgs(),
|
||||
Policy);
|
||||
}
|
||||
|
||||
void StmtPrinter::VisitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *Node) {
|
||||
|
@ -60,7 +60,10 @@ namespace {
|
||||
|
||||
/// \brief Visit template arguments that occur within an expression or
|
||||
/// statement.
|
||||
void VisitTemplateArguments(const TemplateArgument *Args, unsigned NumArgs);
|
||||
void VisitTemplateArguments(const TemplateArgumentLoc *Args, unsigned NumArgs);
|
||||
|
||||
/// \brief Visit a single template argument.
|
||||
void VisitTemplateArgument(const TemplateArgument &Arg);
|
||||
};
|
||||
}
|
||||
|
||||
@ -206,7 +209,9 @@ void StmtProfiler::VisitExpr(Expr *S) {
|
||||
|
||||
void StmtProfiler::VisitDeclRefExpr(DeclRefExpr *S) {
|
||||
VisitExpr(S);
|
||||
VisitNestedNameSpecifier(S->getQualifier());
|
||||
VisitDecl(S->getDecl());
|
||||
VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs());
|
||||
}
|
||||
|
||||
void StmtProfiler::VisitPredefinedExpr(PredefinedExpr *S) {
|
||||
@ -521,11 +526,6 @@ void StmtProfiler::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *S) {
|
||||
VisitType(S->getQueriedType());
|
||||
}
|
||||
|
||||
void StmtProfiler::VisitQualifiedDeclRefExpr(QualifiedDeclRefExpr *S) {
|
||||
VisitDeclRefExpr(S);
|
||||
VisitNestedNameSpecifier(S->getQualifier());
|
||||
}
|
||||
|
||||
void StmtProfiler::VisitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *S) {
|
||||
VisitExpr(S);
|
||||
VisitName(S->getDeclName());
|
||||
@ -677,39 +677,42 @@ void StmtProfiler::VisitTemplateName(TemplateName Name) {
|
||||
Name.Profile(ID);
|
||||
}
|
||||
|
||||
void StmtProfiler::VisitTemplateArguments(const TemplateArgument *Args,
|
||||
void StmtProfiler::VisitTemplateArguments(const TemplateArgumentLoc *Args,
|
||||
unsigned NumArgs) {
|
||||
ID.AddInteger(NumArgs);
|
||||
for (unsigned I = 0; I != NumArgs; ++I) {
|
||||
const TemplateArgument &Arg = Args[I];
|
||||
for (unsigned I = 0; I != NumArgs; ++I)
|
||||
VisitTemplateArgument(Args[I].getArgument());
|
||||
}
|
||||
|
||||
// Mostly repetitive with TemplateArgument::Profile!
|
||||
ID.AddInteger(Arg.getKind());
|
||||
switch (Arg.getKind()) {
|
||||
case TemplateArgument::Null:
|
||||
break;
|
||||
void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) {
|
||||
// Mostly repetitive with TemplateArgument::Profile!
|
||||
ID.AddInteger(Arg.getKind());
|
||||
switch (Arg.getKind()) {
|
||||
case TemplateArgument::Null:
|
||||
break;
|
||||
|
||||
case TemplateArgument::Type:
|
||||
VisitType(Arg.getAsType());
|
||||
break;
|
||||
case TemplateArgument::Type:
|
||||
VisitType(Arg.getAsType());
|
||||
break;
|
||||
|
||||
case TemplateArgument::Declaration:
|
||||
VisitDecl(Arg.getAsDecl());
|
||||
break;
|
||||
case TemplateArgument::Declaration:
|
||||
VisitDecl(Arg.getAsDecl());
|
||||
break;
|
||||
|
||||
case TemplateArgument::Integral:
|
||||
Arg.getAsIntegral()->Profile(ID);
|
||||
VisitType(Arg.getIntegralType());
|
||||
break;
|
||||
case TemplateArgument::Integral:
|
||||
Arg.getAsIntegral()->Profile(ID);
|
||||
VisitType(Arg.getIntegralType());
|
||||
break;
|
||||
|
||||
case TemplateArgument::Expression:
|
||||
Visit(Arg.getAsExpr());
|
||||
break;
|
||||
case TemplateArgument::Expression:
|
||||
Visit(Arg.getAsExpr());
|
||||
break;
|
||||
|
||||
case TemplateArgument::Pack:
|
||||
VisitTemplateArguments(Arg.pack_begin(), Arg.pack_size());
|
||||
break;
|
||||
}
|
||||
case TemplateArgument::Pack:
|
||||
const TemplateArgument *Pack = Arg.pack_begin();
|
||||
for (unsigned i = 0, e = Arg.pack_size(); i != e; ++i)
|
||||
VisitTemplateArgument(Pack[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
97
lib/AST/TemplateBase.cpp
Normal file
97
lib/AST/TemplateBase.cpp
Normal file
@ -0,0 +1,97 @@
|
||||
//===--- TemplateBase.cpp - Common template AST class implementation ------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements common classes used throughout C++ template
|
||||
// representations.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "clang/AST/TemplateBase.h"
|
||||
#include "clang/AST/DeclBase.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/TypeLoc.h"
|
||||
|
||||
using namespace clang;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// TemplateArgument Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// \brief Construct a template argument pack.
|
||||
void TemplateArgument::setArgumentPack(TemplateArgument *args, unsigned NumArgs,
|
||||
bool CopyArgs) {
|
||||
assert(isNull() && "Must call setArgumentPack on a null argument");
|
||||
|
||||
Kind = Pack;
|
||||
Args.NumArgs = NumArgs;
|
||||
Args.CopyArgs = CopyArgs;
|
||||
if (!Args.CopyArgs) {
|
||||
Args.Args = args;
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME: Allocate in ASTContext
|
||||
Args.Args = new TemplateArgument[NumArgs];
|
||||
for (unsigned I = 0; I != Args.NumArgs; ++I)
|
||||
Args.Args[I] = args[I];
|
||||
}
|
||||
|
||||
void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
|
||||
ASTContext &Context) const {
|
||||
ID.AddInteger(Kind);
|
||||
switch (Kind) {
|
||||
case Null:
|
||||
break;
|
||||
|
||||
case Type:
|
||||
getAsType().Profile(ID);
|
||||
break;
|
||||
|
||||
case Declaration:
|
||||
ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0);
|
||||
break;
|
||||
|
||||
case Integral:
|
||||
getAsIntegral()->Profile(ID);
|
||||
getIntegralType().Profile(ID);
|
||||
break;
|
||||
|
||||
case Expression:
|
||||
getAsExpr()->Profile(ID, Context, true);
|
||||
break;
|
||||
|
||||
case Pack:
|
||||
ID.AddInteger(Args.NumArgs);
|
||||
for (unsigned I = 0; I != Args.NumArgs; ++I)
|
||||
Args.Args[I].Profile(ID, Context);
|
||||
}
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// TemplateArgumentLoc Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
SourceRange TemplateArgumentLoc::getSourceRange() const {
|
||||
switch (Argument.getKind()) {
|
||||
case TemplateArgument::Expression:
|
||||
return getSourceExpression()->getSourceRange();
|
||||
case TemplateArgument::Declaration:
|
||||
return getSourceDeclExpression()->getSourceRange();
|
||||
case TemplateArgument::Type:
|
||||
return getSourceDeclaratorInfo()->getTypeLoc().getFullSourceRange();
|
||||
case TemplateArgument::Integral:
|
||||
case TemplateArgument::Pack:
|
||||
case TemplateArgument::Null:
|
||||
return SourceRange();
|
||||
}
|
||||
|
||||
// Silence bonus gcc warning.
|
||||
return SourceRange();
|
||||
}
|
@ -56,7 +56,7 @@ void
|
||||
TemplateName::print(llvm::raw_ostream &OS, const PrintingPolicy &Policy,
|
||||
bool SuppressNNS) const {
|
||||
if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
|
||||
OS << Template->getIdentifier()->getName();
|
||||
OS << Template->getNameAsString();
|
||||
else if (OverloadedFunctionDecl *Ovl
|
||||
= Storage.dyn_cast<OverloadedFunctionDecl *>())
|
||||
OS << Ovl->getNameAsString();
|
||||
@ -70,8 +70,11 @@ TemplateName::print(llvm::raw_ostream &OS, const PrintingPolicy &Policy,
|
||||
if (!SuppressNNS && DTN->getQualifier())
|
||||
DTN->getQualifier()->print(OS, Policy);
|
||||
OS << "template ";
|
||||
// FIXME: Shouldn't we have a more general kind of name?
|
||||
OS << DTN->getName()->getName();
|
||||
|
||||
if (DTN->isIdentifier())
|
||||
OS << DTN->getIdentifier()->getName();
|
||||
else
|
||||
OS << "operator " << getOperatorSpelling(DTN->getOperator());
|
||||
}
|
||||
}
|
||||
|
||||
|
145
lib/AST/Type.cpp
145
lib/AST/Type.cpp
@ -224,6 +224,8 @@ QualType Type::getPointeeType() const {
|
||||
return OPT->getPointeeType();
|
||||
if (const BlockPointerType *BPT = getAs<BlockPointerType>())
|
||||
return BPT->getPointeeType();
|
||||
if (const ReferenceType *RT = getAs<ReferenceType>())
|
||||
return RT->getPointeeType();
|
||||
return QualType();
|
||||
}
|
||||
|
||||
@ -791,40 +793,48 @@ bool EnumType::classof(const TagType *TT) {
|
||||
return isa<EnumDecl>(TT->getDecl());
|
||||
}
|
||||
|
||||
bool
|
||||
TemplateSpecializationType::
|
||||
anyDependentTemplateArguments(const TemplateArgument *Args, unsigned NumArgs) {
|
||||
for (unsigned Idx = 0; Idx < NumArgs; ++Idx) {
|
||||
switch (Args[Idx].getKind()) {
|
||||
case TemplateArgument::Null:
|
||||
assert(false && "Should not have a NULL template argument");
|
||||
break;
|
||||
static bool isDependent(const TemplateArgument &Arg) {
|
||||
switch (Arg.getKind()) {
|
||||
case TemplateArgument::Null:
|
||||
assert(false && "Should not have a NULL template argument");
|
||||
return false;
|
||||
|
||||
case TemplateArgument::Type:
|
||||
if (Args[Idx].getAsType()->isDependentType())
|
||||
return true;
|
||||
break;
|
||||
case TemplateArgument::Type:
|
||||
return Arg.getAsType()->isDependentType();
|
||||
|
||||
case TemplateArgument::Declaration:
|
||||
case TemplateArgument::Integral:
|
||||
// Never dependent
|
||||
break;
|
||||
case TemplateArgument::Declaration:
|
||||
case TemplateArgument::Integral:
|
||||
// Never dependent
|
||||
return false;
|
||||
|
||||
case TemplateArgument::Expression:
|
||||
if (Args[Idx].getAsExpr()->isTypeDependent() ||
|
||||
Args[Idx].getAsExpr()->isValueDependent())
|
||||
return true;
|
||||
break;
|
||||
case TemplateArgument::Expression:
|
||||
return (Arg.getAsExpr()->isTypeDependent() ||
|
||||
Arg.getAsExpr()->isValueDependent());
|
||||
|
||||
case TemplateArgument::Pack:
|
||||
assert(0 && "FIXME: Implement!");
|
||||
break;
|
||||
}
|
||||
case TemplateArgument::Pack:
|
||||
assert(0 && "FIXME: Implement!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TemplateSpecializationType::
|
||||
anyDependentTemplateArguments(const TemplateArgumentLoc *Args, unsigned N) {
|
||||
for (unsigned i = 0; i != N; ++i)
|
||||
if (isDependent(Args[i].getArgument()))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TemplateSpecializationType::
|
||||
anyDependentTemplateArguments(const TemplateArgument *Args, unsigned N) {
|
||||
for (unsigned i = 0; i != N; ++i)
|
||||
if (isDependent(Args[i]))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
TemplateSpecializationType::
|
||||
TemplateSpecializationType(ASTContext &Context, TemplateName T,
|
||||
const TemplateArgument *Args,
|
||||
@ -1260,6 +1270,38 @@ void SubstTemplateTypeParmType::getAsStringInternal(std::string &InnerString, co
|
||||
getReplacementType().getAsStringInternal(InnerString, Policy);
|
||||
}
|
||||
|
||||
static void PrintTemplateArgument(std::string &Buffer,
|
||||
const TemplateArgument &Arg,
|
||||
const PrintingPolicy &Policy) {
|
||||
switch (Arg.getKind()) {
|
||||
case TemplateArgument::Null:
|
||||
assert(false && "Null template argument");
|
||||
break;
|
||||
|
||||
case TemplateArgument::Type:
|
||||
Arg.getAsType().getAsStringInternal(Buffer, Policy);
|
||||
break;
|
||||
|
||||
case TemplateArgument::Declaration:
|
||||
Buffer = cast<NamedDecl>(Arg.getAsDecl())->getNameAsString();
|
||||
break;
|
||||
|
||||
case TemplateArgument::Integral:
|
||||
Buffer = Arg.getAsIntegral()->toString(10, true);
|
||||
break;
|
||||
|
||||
case TemplateArgument::Expression: {
|
||||
llvm::raw_string_ostream s(Buffer);
|
||||
Arg.getAsExpr()->printPretty(s, 0, Policy);
|
||||
break;
|
||||
}
|
||||
|
||||
case TemplateArgument::Pack:
|
||||
assert(0 && "FIXME: Implement!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
TemplateSpecializationType::PrintTemplateArgumentList(
|
||||
const TemplateArgument *Args,
|
||||
@ -1273,32 +1315,41 @@ TemplateSpecializationType::PrintTemplateArgumentList(
|
||||
|
||||
// Print the argument into a string.
|
||||
std::string ArgString;
|
||||
switch (Args[Arg].getKind()) {
|
||||
case TemplateArgument::Null:
|
||||
assert(false && "Null template argument");
|
||||
break;
|
||||
PrintTemplateArgument(ArgString, Args[Arg], Policy);
|
||||
|
||||
case TemplateArgument::Type:
|
||||
Args[Arg].getAsType().getAsStringInternal(ArgString, Policy);
|
||||
break;
|
||||
// If this is the first argument and its string representation
|
||||
// begins with the global scope specifier ('::foo'), add a space
|
||||
// to avoid printing the diagraph '<:'.
|
||||
if (!Arg && !ArgString.empty() && ArgString[0] == ':')
|
||||
SpecString += ' ';
|
||||
|
||||
case TemplateArgument::Declaration:
|
||||
ArgString = cast<NamedDecl>(Args[Arg].getAsDecl())->getNameAsString();
|
||||
break;
|
||||
SpecString += ArgString;
|
||||
}
|
||||
|
||||
case TemplateArgument::Integral:
|
||||
ArgString = Args[Arg].getAsIntegral()->toString(10, true);
|
||||
break;
|
||||
// If the last character of our string is '>', add another space to
|
||||
// keep the two '>''s separate tokens. We don't *have* to do this in
|
||||
// C++0x, but it's still good hygiene.
|
||||
if (SpecString[SpecString.size() - 1] == '>')
|
||||
SpecString += ' ';
|
||||
|
||||
case TemplateArgument::Expression: {
|
||||
llvm::raw_string_ostream s(ArgString);
|
||||
Args[Arg].getAsExpr()->printPretty(s, 0, Policy);
|
||||
break;
|
||||
}
|
||||
case TemplateArgument::Pack:
|
||||
assert(0 && "FIXME: Implement!");
|
||||
break;
|
||||
}
|
||||
SpecString += '>';
|
||||
|
||||
return SpecString;
|
||||
}
|
||||
|
||||
// Sadly, repeat all that with TemplateArgLoc.
|
||||
std::string TemplateSpecializationType::
|
||||
PrintTemplateArgumentList(const TemplateArgumentLoc *Args, unsigned NumArgs,
|
||||
const PrintingPolicy &Policy) {
|
||||
std::string SpecString;
|
||||
SpecString += '<';
|
||||
for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
|
||||
if (Arg)
|
||||
SpecString += ", ";
|
||||
|
||||
// Print the argument into a string.
|
||||
std::string ArgString;
|
||||
PrintTemplateArgument(ArgString, Args[Arg].getArgument(), Policy);
|
||||
|
||||
// If this is the first argument and its string representation
|
||||
// begins with the global scope specifier ('::foo'), add a space
|
||||
|
100
lib/Analysis/AttrNonNullChecker.cpp
Normal file
100
lib/Analysis/AttrNonNullChecker.cpp
Normal file
@ -0,0 +1,100 @@
|
||||
//===--- AttrNonNullChecker.h - Undefined arguments checker ----*- C++ -*--===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This defines AttrNonNullChecker, a builtin check in GRExprEngine that
|
||||
// performs checks for arguments declared to have nonnull attribute.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Analysis/PathSensitive/Checkers/AttrNonNullChecker.h"
|
||||
#include "clang/Analysis/PathSensitive/BugReporter.h"
|
||||
|
||||
using namespace clang;
|
||||
|
||||
void *AttrNonNullChecker::getTag() {
|
||||
static int x = 0;
|
||||
return &x;
|
||||
}
|
||||
|
||||
void AttrNonNullChecker::PreVisitCallExpr(CheckerContext &C,
|
||||
const CallExpr *CE) {
|
||||
const GRState *state = C.getState();
|
||||
const GRState *originalState = state;
|
||||
|
||||
// Check if the callee has a 'nonnull' attribute.
|
||||
SVal X = state->getSVal(CE->getCallee());
|
||||
|
||||
const FunctionDecl* FD = X.getAsFunctionDecl();
|
||||
if (!FD)
|
||||
return;
|
||||
|
||||
const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
|
||||
if (!Att)
|
||||
return;
|
||||
|
||||
// Iterate through the arguments of CE and check them for null.
|
||||
unsigned idx = 0;
|
||||
|
||||
for (CallExpr::const_arg_iterator I=CE->arg_begin(), E=CE->arg_end(); I!=E;
|
||||
++I, ++idx) {
|
||||
|
||||
if (!Att->isNonNull(idx))
|
||||
continue;
|
||||
|
||||
const SVal &V = state->getSVal(*I);
|
||||
const DefinedSVal *DV = dyn_cast<DefinedSVal>(&V);
|
||||
|
||||
if (!DV)
|
||||
continue;
|
||||
|
||||
ConstraintManager &CM = C.getConstraintManager();
|
||||
const GRState *stateNotNull, *stateNull;
|
||||
llvm::tie(stateNotNull, stateNull) = CM.AssumeDual(state, *DV);
|
||||
|
||||
if (stateNull && !stateNotNull) {
|
||||
// Generate an error node. Check for a null node in case
|
||||
// we cache out.
|
||||
if (ExplodedNode *errorNode = C.GenerateNode(CE, stateNull, true)) {
|
||||
|
||||
// Lazily allocate the BugType object if it hasn't already been
|
||||
// created. Ownership is transferred to the BugReporter object once
|
||||
// the BugReport is passed to 'EmitWarning'.
|
||||
if (!BT)
|
||||
BT = new BugType("Argument with 'nonnull' attribute passed null",
|
||||
"API");
|
||||
|
||||
EnhancedBugReport *R =
|
||||
new EnhancedBugReport(*BT,
|
||||
"Null pointer passed as an argument to a "
|
||||
"'nonnull' parameter", errorNode);
|
||||
|
||||
// Highlight the range of the argument that was null.
|
||||
const Expr *arg = *I;
|
||||
R->addRange(arg->getSourceRange());
|
||||
R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, arg);
|
||||
|
||||
// Emit the bug report.
|
||||
C.EmitReport(R);
|
||||
}
|
||||
|
||||
// Always return. Either we cached out or we just emitted an error.
|
||||
return;
|
||||
}
|
||||
|
||||
// If a pointer value passed the check we should assume that it is
|
||||
// indeed not null from this point forward.
|
||||
assert(stateNotNull);
|
||||
state = stateNotNull;
|
||||
}
|
||||
|
||||
// If we reach here all of the arguments passed the nonnull check.
|
||||
// If 'state' has been updated generated a new node.
|
||||
if (state != originalState)
|
||||
C.addTransition(C.GenerateNode(CE, state));
|
||||
}
|
44
lib/Analysis/BadCallChecker.cpp
Normal file
44
lib/Analysis/BadCallChecker.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
//===--- BadCallChecker.h - Bad call checker --------------------*- C++ -*--==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This defines BadCallChecker, a builtin check in GRExprEngine that performs
|
||||
// checks for bad callee at call sites.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Analysis/PathSensitive/Checkers/BadCallChecker.h"
|
||||
#include "clang/Analysis/PathSensitive/BugReporter.h"
|
||||
|
||||
using namespace clang;
|
||||
|
||||
void *BadCallChecker::getTag() {
|
||||
static int x = 0;
|
||||
return &x;
|
||||
}
|
||||
|
||||
void BadCallChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
|
||||
const Expr *Callee = CE->getCallee()->IgnoreParens();
|
||||
SVal L = C.getState()->getSVal(Callee);
|
||||
|
||||
if (L.isUndef() || isa<loc::ConcreteInt>(L)) {
|
||||
if (ExplodedNode *N = C.GenerateNode(CE, true)) {
|
||||
if (!BT)
|
||||
BT = new BuiltinBug(0, "Invalid function call",
|
||||
"Called function pointer is a null or undefined pointer value");
|
||||
|
||||
EnhancedBugReport *R =
|
||||
new EnhancedBugReport(*BT, BT->getDescription().c_str(), N);
|
||||
|
||||
R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
|
||||
bugreporter::GetCalleeExpr(N));
|
||||
|
||||
C.EmitReport(R);
|
||||
}
|
||||
}
|
||||
}
|
@ -535,4 +535,5 @@ void clang::RegisterAppleChecks(GRExprEngine& Eng, const Decl &D) {
|
||||
Eng.AddCheck(CreateAuditCFRetainRelease(Ctx, BR), Stmt::CallExprClass);
|
||||
|
||||
RegisterNSErrorChecks(BR, Eng, D);
|
||||
RegisterNSAutoreleasePoolChecks(Eng);
|
||||
}
|
||||
|
@ -42,6 +42,7 @@ GRSimpleAPICheck *CreateAuditCFRetainRelease(ASTContext& Ctx,
|
||||
BugReporter& BR);
|
||||
|
||||
void RegisterNSErrorChecks(BugReporter& BR, GRExprEngine &Eng, const Decl &D);
|
||||
void RegisterNSAutoreleasePoolChecks(GRExprEngine &Eng);
|
||||
|
||||
} // end clang namespace
|
||||
|
||||
|
@ -92,19 +92,17 @@ class VISIBILITY_HIDDEN BasicStoreManager : public StoreManager {
|
||||
|
||||
void iterBindings(Store store, BindingsHandler& f);
|
||||
|
||||
const GRState *BindDecl(const GRState *state, const VarDecl *VD,
|
||||
const LocationContext *LC, SVal InitVal) {
|
||||
return state->makeWithStore(BindDeclInternal(state->getStore(),VD, LC,
|
||||
const GRState *BindDecl(const GRState *state, const VarRegion *VR,
|
||||
SVal InitVal) {
|
||||
return state->makeWithStore(BindDeclInternal(state->getStore(), VR,
|
||||
&InitVal));
|
||||
}
|
||||
|
||||
const GRState *BindDeclWithNoInit(const GRState *state, const VarDecl *VD,
|
||||
const LocationContext *LC) {
|
||||
return state->makeWithStore(BindDeclInternal(state->getStore(), VD, LC, 0));
|
||||
const GRState *BindDeclWithNoInit(const GRState *state, const VarRegion *VR) {
|
||||
return state->makeWithStore(BindDeclInternal(state->getStore(), VR, 0));
|
||||
}
|
||||
|
||||
Store BindDeclInternal(Store store, const VarDecl *VD,
|
||||
const LocationContext *LC, SVal *InitVal);
|
||||
Store BindDeclInternal(Store store, const VarRegion *VR, SVal *InitVal);
|
||||
|
||||
static inline BindingsTy GetBindings(Store store) {
|
||||
return BindingsTy(static_cast<const BindingsTy::TreeTy*>(store));
|
||||
@ -532,11 +530,11 @@ Store BasicStoreManager::getInitialStore(const LocationContext *InitLoc) {
|
||||
return St;
|
||||
}
|
||||
|
||||
Store BasicStoreManager::BindDeclInternal(Store store, const VarDecl* VD,
|
||||
const LocationContext *LC,
|
||||
Store BasicStoreManager::BindDeclInternal(Store store, const VarRegion* VR,
|
||||
SVal* InitVal) {
|
||||
|
||||
BasicValueFactory& BasicVals = StateMgr.getBasicVals();
|
||||
const VarDecl *VD = VR->getDecl();
|
||||
|
||||
// BasicStore does not model arrays and structs.
|
||||
if (VD->getType()->isArrayType() || VD->getType()->isStructureType())
|
||||
@ -564,16 +562,16 @@ Store BasicStoreManager::BindDeclInternal(Store store, const VarDecl* VD,
|
||||
if (!InitVal) {
|
||||
QualType T = VD->getType();
|
||||
if (Loc::IsLocType(T))
|
||||
store = BindInternal(store, getLoc(VD, LC),
|
||||
store = BindInternal(store, loc::MemRegionVal(VR),
|
||||
loc::ConcreteInt(BasicVals.getValue(0, T)));
|
||||
else if (T->isIntegerType())
|
||||
store = BindInternal(store, getLoc(VD, LC),
|
||||
store = BindInternal(store, loc::MemRegionVal(VR),
|
||||
nonloc::ConcreteInt(BasicVals.getValue(0, T)));
|
||||
else {
|
||||
// assert(0 && "ignore other types of variables");
|
||||
}
|
||||
} else {
|
||||
store = BindInternal(store, getLoc(VD, LC), *InitVal);
|
||||
store = BindInternal(store, loc::MemRegionVal(VR), *InitVal);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -581,7 +579,7 @@ Store BasicStoreManager::BindDeclInternal(Store store, const VarDecl* VD,
|
||||
QualType T = VD->getType();
|
||||
if (ValMgr.getSymbolManager().canSymbolicate(T)) {
|
||||
SVal V = InitVal ? *InitVal : UndefinedVal();
|
||||
store = BindInternal(store, getLoc(VD, LC), V);
|
||||
store = BindInternal(store, loc::MemRegionVal(VR), V);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -192,20 +192,6 @@ class VISIBILITY_HIDDEN GenericNodeBuilder {
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Selector creation functions.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static inline Selector GetNullarySelector(const char* name, ASTContext& Ctx) {
|
||||
IdentifierInfo* II = &Ctx.Idents.get(name);
|
||||
return Ctx.Selectors.getSelector(0, &II);
|
||||
}
|
||||
|
||||
static inline Selector GetUnarySelector(const char* name, ASTContext& Ctx) {
|
||||
IdentifierInfo* II = &Ctx.Idents.get(name);
|
||||
return Ctx.Selectors.getSelector(1, &II);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Type querying functions.
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -1031,11 +1017,25 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
|
||||
// Eventually this can be improved by recognizing that the pixel
|
||||
// buffer passed to CVPixelBufferCreateWithBytes is released via
|
||||
// a callback and doing full IPA to make sure this is done correctly.
|
||||
// FIXME: This function has an out parameter that returns an
|
||||
// allocated object.
|
||||
ScratchArgs = AF.Add(ScratchArgs, 7, StopTracking);
|
||||
S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing,
|
||||
DoNothing);
|
||||
}
|
||||
break;
|
||||
|
||||
case 29:
|
||||
if (!memcmp(FName, "CGBitmapContextCreateWithData", 29)) {
|
||||
// FIXES: <rdar://problem/7358899>
|
||||
// Eventually this can be improved by recognizing that 'releaseInfo'
|
||||
// passed to CGBitmapContextCreateWithData is released via
|
||||
// a callback and doing full IPA to make sure this is done correctly.
|
||||
ScratchArgs = AF.Add(ScratchArgs, 8, StopTracking);
|
||||
S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true),
|
||||
DoNothing,DoNothing);
|
||||
}
|
||||
break;
|
||||
|
||||
case 32:
|
||||
if (!memcmp(FName, "IOServiceAddMatchingNotification", 32)) {
|
||||
@ -1899,7 +1899,7 @@ class VISIBILITY_HIDDEN CFRefCount : public GRTransferFuncs {
|
||||
|
||||
virtual ~CFRefCount() {}
|
||||
|
||||
void RegisterChecks(BugReporter &BR);
|
||||
void RegisterChecks(GRExprEngine &Eng);
|
||||
|
||||
virtual void RegisterPrinters(std::vector<GRState::Printer*>& Printers) {
|
||||
Printers.push_back(new BindingsPrinter());
|
||||
@ -2193,7 +2193,9 @@ namespace {
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
void CFRefCount::RegisterChecks(BugReporter& BR) {
|
||||
void CFRefCount::RegisterChecks(GRExprEngine& Eng) {
|
||||
BugReporter &BR = Eng.getBugReporter();
|
||||
|
||||
useAfterRelease = new UseAfterRelease(this);
|
||||
BR.Register(useAfterRelease);
|
||||
|
||||
|
@ -3,6 +3,8 @@ set(LLVM_NO_RTTI 1)
|
||||
add_clang_library(clangAnalysis
|
||||
AnalysisContext.cpp
|
||||
AnalysisManager.cpp
|
||||
AttrNonNullChecker.cpp
|
||||
BadCallChecker.cpp
|
||||
BasicConstraintManager.cpp
|
||||
BasicObjCFoundationChecks.cpp
|
||||
BasicStore.cpp
|
||||
@ -14,11 +16,12 @@ add_clang_library(clangAnalysis
|
||||
CallGraph.cpp
|
||||
CallInliner.cpp
|
||||
CheckDeadStores.cpp
|
||||
CheckNSError.cpp
|
||||
CheckObjCDealloc.cpp
|
||||
CheckObjCInstMethSignature.cpp
|
||||
CheckObjCUnusedIVars.cpp
|
||||
CheckSecuritySyntaxOnly.cpp
|
||||
DereferenceChecker.cpp
|
||||
DivZeroChecker.cpp
|
||||
Environment.cpp
|
||||
ExplodedGraph.cpp
|
||||
GRBlockCounter.cpp
|
||||
@ -28,6 +31,8 @@ add_clang_library(clangAnalysis
|
||||
GRState.cpp
|
||||
LiveVariables.cpp
|
||||
MemRegion.cpp
|
||||
NSAutoreleasePoolChecker.cpp
|
||||
NSErrorChecker.cpp
|
||||
PathDiagnostic.cpp
|
||||
RangeConstraintManager.cpp
|
||||
RegionStore.cpp
|
||||
@ -37,8 +42,11 @@ add_clang_library(clangAnalysis
|
||||
SimpleSValuator.cpp
|
||||
Store.cpp
|
||||
SymbolManager.cpp
|
||||
UndefinedArgChecker.cpp
|
||||
UndefinedAssignmentChecker.cpp
|
||||
UninitializedValues.cpp
|
||||
ValueManager.cpp
|
||||
VLASizeChecker.cpp
|
||||
)
|
||||
|
||||
add_dependencies(clangAnalysis ClangDiagnosticAnalysis)
|
||||
|
@ -68,10 +68,8 @@ CallGraph::~CallGraph() {
|
||||
}
|
||||
}
|
||||
|
||||
void CallGraph::addTU(ASTUnit &AST) {
|
||||
ASTContext &Ctx = AST.getASTContext();
|
||||
void CallGraph::addTU(ASTContext& Ctx) {
|
||||
DeclContext *DC = Ctx.getTranslationUnitDecl();
|
||||
|
||||
for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
|
||||
I != E; ++I) {
|
||||
|
||||
|
@ -62,6 +62,29 @@ static void Scan(IvarUsageMap& M, const ObjCPropertyImplDecl* D) {
|
||||
I->second = Used;
|
||||
}
|
||||
|
||||
static void Scan(IvarUsageMap& M, const ObjCContainerDecl* D) {
|
||||
// Scan the methods for accesses.
|
||||
for (ObjCContainerDecl::instmeth_iterator I = D->instmeth_begin(),
|
||||
E = D->instmeth_end(); I!=E; ++I)
|
||||
Scan(M, (*I)->getBody());
|
||||
|
||||
if (const ObjCImplementationDecl *ID = dyn_cast<ObjCImplementationDecl>(D)) {
|
||||
// Scan for @synthesized property methods that act as setters/getters
|
||||
// to an ivar.
|
||||
for (ObjCImplementationDecl::propimpl_iterator I = ID->propimpl_begin(),
|
||||
E = ID->propimpl_end(); I!=E; ++I)
|
||||
Scan(M, *I);
|
||||
|
||||
// Scan the associated categories as well.
|
||||
for (const ObjCCategoryDecl *CD =
|
||||
ID->getClassInterface()->getCategoryList(); CD ;
|
||||
CD = CD->getNextClassCategory()) {
|
||||
if (const ObjCCategoryImplDecl *CID = CD->getImplementation())
|
||||
Scan(M, CID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void clang::CheckObjCUnusedIvar(const ObjCImplementationDecl *D,
|
||||
BugReporter &BR) {
|
||||
|
||||
@ -88,16 +111,8 @@ void clang::CheckObjCUnusedIvar(const ObjCImplementationDecl *D,
|
||||
if (M.empty())
|
||||
return;
|
||||
|
||||
// Now scan the methods for accesses.
|
||||
for (ObjCImplementationDecl::instmeth_iterator I = D->instmeth_begin(),
|
||||
E = D->instmeth_end(); I!=E; ++I)
|
||||
Scan(M, (*I)->getBody());
|
||||
|
||||
// Scan for @synthesized property methods that act as setters/getters
|
||||
// to an ivar.
|
||||
for (ObjCImplementationDecl::propimpl_iterator I = D->propimpl_begin(),
|
||||
E = D->propimpl_end(); I!=E; ++I)
|
||||
Scan(M, *I);
|
||||
// Now scan the implementation declaration.
|
||||
Scan(M, D);
|
||||
|
||||
// Find ivars that are unused.
|
||||
for (IvarUsageMap::iterator I = M.begin(), E = M.end(); I!=E; ++I)
|
||||
|
112
lib/Analysis/DereferenceChecker.cpp
Normal file
112
lib/Analysis/DereferenceChecker.cpp
Normal file
@ -0,0 +1,112 @@
|
||||
//== NullDerefChecker.cpp - Null dereference checker ------------*- C++ -*--==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This defines NullDerefChecker, a builtin check in GRExprEngine that performs
|
||||
// checks for null pointers at loads and stores.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h"
|
||||
#include "clang/Analysis/PathSensitive/GRExprEngine.h"
|
||||
#include "clang/Analysis/PathSensitive/BugReporter.h"
|
||||
|
||||
using namespace clang;
|
||||
|
||||
void *NullDerefChecker::getTag() {
|
||||
static int x = 0;
|
||||
return &x;
|
||||
}
|
||||
|
||||
ExplodedNode *NullDerefChecker::CheckLocation(const Stmt *S, ExplodedNode *Pred,
|
||||
const GRState *state, SVal V,
|
||||
GRExprEngine &Eng) {
|
||||
Loc *LV = dyn_cast<Loc>(&V);
|
||||
|
||||
// If the value is not a location, don't touch the node.
|
||||
if (!LV)
|
||||
return Pred;
|
||||
|
||||
const GRState *NotNullState = state->Assume(*LV, true);
|
||||
const GRState *NullState = state->Assume(*LV, false);
|
||||
|
||||
GRStmtNodeBuilder &Builder = Eng.getBuilder();
|
||||
BugReporter &BR = Eng.getBugReporter();
|
||||
|
||||
// The explicit NULL case.
|
||||
if (NullState) {
|
||||
// Use the GDM to mark in the state what lval was null.
|
||||
const SVal *PersistentLV = Eng.getBasicVals().getPersistentSVal(*LV);
|
||||
NullState = NullState->set<GRState::NullDerefTag>(PersistentLV);
|
||||
|
||||
ExplodedNode *N = Builder.generateNode(S, NullState, Pred,
|
||||
ProgramPoint::PostNullCheckFailedKind);
|
||||
if (N) {
|
||||
N->markAsSink();
|
||||
|
||||
if (!NotNullState) { // Explicit null case.
|
||||
if (!BT)
|
||||
BT = new BuiltinBug(NULL, "Null dereference",
|
||||
"Dereference of null pointer");
|
||||
|
||||
EnhancedBugReport *R =
|
||||
new EnhancedBugReport(*BT, BT->getDescription().c_str(), N);
|
||||
|
||||
R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
|
||||
bugreporter::GetDerefExpr(N));
|
||||
|
||||
BR.EmitReport(R);
|
||||
|
||||
return 0;
|
||||
} else // Implicit null case.
|
||||
ImplicitNullDerefNodes.push_back(N);
|
||||
}
|
||||
}
|
||||
|
||||
if (!NotNullState)
|
||||
return 0;
|
||||
|
||||
return Builder.generateNode(S, NotNullState, Pred,
|
||||
ProgramPoint::PostLocationChecksSucceedKind);
|
||||
}
|
||||
|
||||
|
||||
void *UndefDerefChecker::getTag() {
|
||||
static int x = 0;
|
||||
return &x;
|
||||
}
|
||||
|
||||
ExplodedNode *UndefDerefChecker::CheckLocation(const Stmt *S,
|
||||
ExplodedNode *Pred,
|
||||
const GRState *state, SVal V,
|
||||
GRExprEngine &Eng) {
|
||||
GRStmtNodeBuilder &Builder = Eng.getBuilder();
|
||||
BugReporter &BR = Eng.getBugReporter();
|
||||
|
||||
if (V.isUndef()) {
|
||||
ExplodedNode *N = Builder.generateNode(S, state, Pred,
|
||||
ProgramPoint::PostUndefLocationCheckFailedKind);
|
||||
if (N) {
|
||||
N->markAsSink();
|
||||
|
||||
if (!BT)
|
||||
BT = new BuiltinBug(0, "Undefined dereference",
|
||||
"Dereference of undefined pointer value");
|
||||
|
||||
EnhancedBugReport *R =
|
||||
new EnhancedBugReport(*BT, BT->getDescription().c_str(), N);
|
||||
R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
|
||||
bugreporter::GetDerefExpr(N));
|
||||
BR.EmitReport(R);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Pred;
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user