Update clang to r86025.

This commit is contained in:
Roman Divacky 2009-11-04 15:04:32 +00:00
parent 73490b8909
commit 51fb8b013e
338 changed files with 13989 additions and 5642 deletions

View File

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

View File

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

View File

@ -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(&lt;stdint.h&gt;)
# 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(&lt;stdint.h&gt;)
# 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>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -26,6 +26,7 @@ add_clang_library(clangAST
StmtPrinter.cpp
StmtProfile.cpp
StmtViz.cpp
TemplateBase.cpp
TemplateName.cpp
Type.cpp
TypeLoc.cpp

View File

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

View File

@ -199,7 +199,6 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case Var:
case ImplicitParam:
case ParmVar:
case OriginalParmVar:
case NonTypeTemplateParm:
case Using:
case UnresolvedUsing:

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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