aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEd Schouten <ed@FreeBSD.org>2009-06-22 08:08:35 +0000
committerEd Schouten <ed@FreeBSD.org>2009-06-22 08:08:35 +0000
commitb897c8660c4ff7037dde81b9645737bc1c992abe (patch)
treeb6403365e77095a79062d3379c9e6aea0df5f088
parent7ef7bab7e3d06f660b059b903c231f100bb13cc5 (diff)
downloadsrc-vendor/clang/clang-r73879.tar.gz
src-vendor/clang/clang-r73879.zip
Update Clang sources to r73879.vendor/clang/clang-r73879
-rw-r--r--CMakeLists.txt9
-rw-r--r--include/clang/AST/ASTContext.h34
-rw-r--r--include/clang/AST/Decl.h26
-rw-r--r--include/clang/AST/DeclBase.h45
-rw-r--r--include/clang/AST/DeclCXX.h81
-rw-r--r--include/clang/AST/DeclNodes.def1
-rw-r--r--include/clang/AST/DeclTemplate.h73
-rw-r--r--include/clang/AST/Expr.h14
-rw-r--r--include/clang/AST/ExprCXX.h11
-rw-r--r--include/clang/AST/ExprObjC.h8
-rw-r--r--include/clang/AST/Type.h150
-rw-r--r--include/clang/AST/TypeNodes.def3
-rw-r--r--include/clang/AST/TypeVisitor.h50
-rw-r--r--include/clang/Analysis/PathSensitive/ConstraintManager.h21
-rw-r--r--include/clang/Analysis/PathSensitive/Environment.h25
-rw-r--r--include/clang/Analysis/PathSensitive/GRExprEngine.h57
-rw-r--r--include/clang/Analysis/PathSensitive/GRExprEngineBuilders.h6
-rw-r--r--include/clang/Analysis/PathSensitive/GRState.h573
-rw-r--r--include/clang/Analysis/PathSensitive/GRTransferFuncs.h8
-rw-r--r--include/clang/Analysis/PathSensitive/MemRegion.h2
-rw-r--r--include/clang/Analysis/PathSensitive/SVals.h4
-rw-r--r--include/clang/Analysis/PathSensitive/Store.h107
-rw-r--r--include/clang/Analysis/PathSensitive/SymbolManager.h17
-rw-r--r--include/clang/Analysis/PathSensitive/ValueManager.h2
-rw-r--r--include/clang/Basic/Builtins.h5
-rw-r--r--include/clang/Basic/DiagnosticGroups.td12
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td10
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td18
-rw-r--r--include/clang/Basic/SourceLocation.h4
-rw-r--r--include/clang/Basic/SourceManager.h14
-rw-r--r--include/clang/Driver/Options.def6
-rw-r--r--include/clang/Driver/ToolChain.h2
-rw-r--r--include/clang/Frontend/ASTUnit.h75
-rw-r--r--include/clang/Frontend/DeclContextXML.def113
-rw-r--r--include/clang/Frontend/DeclXML.def250
-rw-r--r--include/clang/Frontend/DocumentXML.def75
-rw-r--r--include/clang/Frontend/DocumentXML.h84
-rw-r--r--include/clang/Frontend/PCHBitCodes.h4
-rw-r--r--include/clang/Frontend/PCHReader.h108
-rw-r--r--include/clang/Frontend/StmtXML.def517
-rw-r--r--include/clang/Frontend/TypeXML.def277
-rw-r--r--include/clang/Parse/Action.h34
-rw-r--r--include/clang/Parse/Parser.h18
-rw-r--r--lib/AST/ASTContext.cpp101
-rw-r--r--lib/AST/Decl.cpp35
-rw-r--r--lib/AST/DeclBase.cpp48
-rw-r--r--lib/AST/DeclCXX.cpp73
-rw-r--r--lib/AST/DeclTemplate.cpp41
-rw-r--r--lib/AST/Expr.cpp37
-rw-r--r--lib/AST/ExprCXX.cpp9
-rw-r--r--lib/AST/StmtPrinter.cpp8
-rw-r--r--lib/AST/Type.cpp107
-rw-r--r--lib/Analysis/BasicConstraintManager.cpp191
-rw-r--r--lib/Analysis/BasicObjCFoundationChecks.cpp41
-rw-r--r--lib/Analysis/BasicObjCFoundationChecks.h2
-rw-r--r--lib/Analysis/BasicStore.cpp61
-rw-r--r--lib/Analysis/BugReporter.cpp2
-rw-r--r--lib/Analysis/CFRefCount.cpp277
-rw-r--r--lib/Analysis/CheckDeadStores.cpp4
-rw-r--r--lib/Analysis/CheckNSError.cpp15
-rw-r--r--lib/Analysis/CheckObjCDealloc.cpp2
-rw-r--r--lib/Analysis/CheckObjCUnusedIVars.cpp2
-rw-r--r--lib/Analysis/Environment.cpp20
-rw-r--r--lib/Analysis/GRExprEngine.cpp434
-rw-r--r--lib/Analysis/GRExprEngineInternalChecks.cpp30
-rw-r--r--lib/Analysis/GRSimpleVals.cpp22
-rw-r--r--lib/Analysis/GRState.cpp53
-rw-r--r--lib/Analysis/GRTransferFuncs.cpp3
-rw-r--r--lib/Analysis/MemRegion.cpp8
-rw-r--r--lib/Analysis/RangeConstraintManager.cpp49
-rw-r--r--lib/Analysis/RegionStore.cpp822
-rw-r--r--lib/Analysis/SVals.cpp13
-rw-r--r--lib/Analysis/SimpleConstraintManager.cpp185
-rw-r--r--lib/Analysis/SimpleConstraintManager.h86
-rw-r--r--lib/Analysis/Store.cpp3
-rw-r--r--lib/Analysis/SymbolManager.cpp9
-rw-r--r--lib/Basic/Builtins.cpp11
-rw-r--r--lib/Basic/Diagnostic.cpp2
-rw-r--r--lib/Basic/SourceManager.cpp42
-rw-r--r--lib/CodeGen/CGBuiltin.cpp4
-rw-r--r--lib/CodeGen/CGCXXTemp.cpp5
-rw-r--r--lib/CodeGen/CGCall.cpp11
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp62
-rw-r--r--lib/CodeGen/CGDebugInfo.h4
-rw-r--r--lib/CodeGen/CGDecl.cpp12
-rw-r--r--lib/CodeGen/CGExpr.cpp5
-rw-r--r--lib/CodeGen/CGExprComplex.cpp117
-rw-r--r--lib/CodeGen/CGExprConstant.cpp7
-rw-r--r--lib/CodeGen/CGExprScalar.cpp24
-rw-r--r--lib/CodeGen/CGObjC.cpp2
-rw-r--r--lib/CodeGen/CGObjCGNU.cpp33
-rw-r--r--lib/CodeGen/CGObjCMac.cpp11
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp2
-rw-r--r--lib/CodeGen/CodeGenModule.cpp70
-rw-r--r--lib/CodeGen/CodeGenTypes.cpp2
-rw-r--r--lib/CodeGen/Mangle.cpp4
-rw-r--r--lib/Driver/CMakeLists.txt2
-rw-r--r--lib/Driver/Driver.cpp48
-rw-r--r--lib/Driver/HostInfo.cpp34
-rw-r--r--lib/Frontend/ASTConsumers.cpp8
-rw-r--r--lib/Frontend/ASTUnit.cpp159
-rw-r--r--lib/Frontend/CMakeLists.txt4
-rw-r--r--lib/Frontend/DeclXML.cpp161
-rw-r--r--lib/Frontend/DocumentXML.cpp348
-rw-r--r--lib/Frontend/InitHeaderSearch.cpp6
-rw-r--r--lib/Frontend/InitPreprocessor.cpp6
-rw-r--r--lib/Frontend/PCHReader.cpp814
-rw-r--r--lib/Frontend/PCHReaderDecl.cpp4
-rw-r--r--lib/Frontend/PCHReaderStmt.cpp1
-rw-r--r--lib/Frontend/PCHWriter.cpp10
-rw-r--r--lib/Frontend/PCHWriterDecl.cpp6
-rw-r--r--lib/Frontend/PCHWriterStmt.cpp1
-rw-r--r--lib/Frontend/PrintPreprocessedOutput.cpp35
-rw-r--r--lib/Frontend/RewriteBlocks.cpp2
-rw-r--r--lib/Frontend/RewriteObjC.cpp2
-rw-r--r--lib/Frontend/StmtXML.cpp100
-rw-r--r--lib/Frontend/TextDiagnosticPrinter.cpp13
-rw-r--r--lib/Frontend/TypeXML.cpp127
-rw-r--r--lib/Headers/CMakeLists.txt7
-rw-r--r--lib/Lex/HeaderSearch.cpp4
-rw-r--r--lib/Lex/Pragma.cpp20
-rw-r--r--lib/Lex/Preprocessor.cpp2
-rw-r--r--lib/Lex/TokenConcatenation.cpp8
-rw-r--r--lib/Parse/MinimalAction.cpp16
-rw-r--r--lib/Parse/ParseDecl.cpp15
-rw-r--r--lib/Parse/ParseDeclCXX.cpp91
-rw-r--r--lib/Parse/ParseExpr.cpp22
-rw-r--r--lib/Parse/ParseExprCXX.cpp11
-rw-r--r--lib/Sema/JumpDiagnostics.cpp6
-rw-r--r--lib/Sema/Sema.cpp5
-rw-r--r--lib/Sema/Sema.h92
-rw-r--r--lib/Sema/SemaAttr.cpp2
-rw-r--r--lib/Sema/SemaCXXScopeSpec.cpp15
-rw-r--r--lib/Sema/SemaChecking.cpp7
-rw-r--r--lib/Sema/SemaDecl.cpp139
-rw-r--r--lib/Sema/SemaDeclAttr.cpp175
-rw-r--r--lib/Sema/SemaDeclCXX.cpp176
-rw-r--r--lib/Sema/SemaDeclObjC.cpp12
-rw-r--r--lib/Sema/SemaExpr.cpp119
-rw-r--r--lib/Sema/SemaExprCXX.cpp11
-rw-r--r--lib/Sema/SemaExprObjC.cpp35
-rw-r--r--lib/Sema/SemaLookup.cpp12
-rw-r--r--lib/Sema/SemaOverload.cpp48
-rw-r--r--lib/Sema/SemaStmt.cpp21
-rw-r--r--lib/Sema/SemaTemplate.cpp24
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp108
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp45
-rw-r--r--lib/Sema/SemaTemplateInstantiateExpr.cpp5
-rw-r--r--lib/Sema/SemaType.cpp42
-rw-r--r--test/Analysis/casts.c24
-rw-r--r--test/Analysis/elementtype.c13
-rw-r--r--test/Analysis/fields.c9
-rw-r--r--test/Analysis/func.c1
-rw-r--r--test/Analysis/retain-release.m160
-rw-r--r--test/CMakeLists.txt22
-rw-r--r--test/CXX/basic/basic.lookup/basic.lookup.unqual/p11.cpp12
-rw-r--r--test/CXX/basic/basic.lookup/basic.lookup.unqual/p12.cpp13
-rw-r--r--test/CXX/basic/basic.lookup/basic.lookup.unqual/p13.cpp8
-rw-r--r--test/CXX/basic/basic.lookup/basic.lookup.unqual/p14.cpp11
-rw-r--r--test/CXX/basic/basic.lookup/basic.lookup.unqual/p15.cpp17
-rw-r--r--test/CXX/basic/basic.lookup/basic.lookup.unqual/p3.cpp26
-rw-r--r--test/CodeGen/2009-05-22-callingconv.c2
-rw-r--r--test/CodeGen/2009-06-14-anonymous-union-init.c7
-rw-r--r--test/CodeGen/2009-06-16-inc_test.c3
-rw-r--r--test/CodeGen/2009-06-16-test.c15
-rw-r--r--test/CodeGen/call-knr-indirect.c11
-rw-r--r--test/CodeGen/libcalls.c4
-rw-r--r--test/CodeGenCXX/default-arg-temps.cpp15
-rw-r--r--test/CodeGenObjC/encode-test-5.m6
-rw-r--r--test/Driver/analyze.c4
-rw-r--r--test/Driver/darwin-cc.c1
-rw-r--r--test/Driver/darwin-ld.c1
-rw-r--r--test/Driver/default-toolchain.c8
-rw-r--r--test/Lexer/token-concat-2.c4
-rw-r--r--test/Parser/cxx-template-decl.cpp11
-rw-r--r--test/Parser/cxx-using-declaration.cpp45
-rw-r--r--test/Parser/cxx-using-directive.cpp3
-rw-r--r--test/Parser/namespace-alias-attr.cpp8
-rw-r--r--test/Preprocessor/_Pragma-dependency2.c5
-rw-r--r--test/Preprocessor/_Pragma-syshdr2.c5
-rw-r--r--test/Preprocessor/pragma_sysheader.c3
-rw-r--r--test/Preprocessor/pragma_sysheader.h4
-rw-r--r--test/Preprocessor/print_line_count.c4
-rw-r--r--test/Sema/block-return.c24
-rw-r--r--test/Sema/warn-unused-parameters.c13
-rw-r--r--test/SemaCXX/default-constructor-initializers.cpp56
-rw-r--r--test/SemaCXX/using-directive.cpp2
-rw-r--r--test/SemaObjC/undeclared-selector.m45
-rw-r--r--test/SemaObjC/warn-unused-parameters.m11
-rw-r--r--test/SemaTemplate/ext-vector-type.cpp47
-rw-r--r--test/SemaTemplate/nested-template.cpp2
-rw-r--r--tools/clang-cc/clang-cc.cpp7
-rw-r--r--tools/driver/CMakeLists.txt3
-rwxr-xr-xutils/test/MultiTestRunner.py23
-rwxr-xr-xutils/test/TestRunner.py129
-rw-r--r--www/OpenProjects.html5
-rw-r--r--www/analyzer/index.html9
-rw-r--r--www/analyzer/latest_checker.html.incl2
-rw-r--r--www/cxx_status.html9
199 files changed, 7112 insertions, 3122 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2f63051a0da4..bb128d68f2bd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,11 +1,14 @@
macro(add_clang_library name)
set(srcs ${ARGN})
if(MSVC_IDE OR XCODE)
- file( GLOB_RECURSE headers *.h)
+ file( GLOB_RECURSE headers *.h *.td *.def)
set(srcs ${srcs} ${headers})
string( REGEX MATCHALL "/[^/]+" split_path ${CMAKE_CURRENT_SOURCE_DIR})
list( GET split_path -1 dir)
- file( GLOB_RECURSE headers ../../include/clang${dir}/*.h)
+ file( GLOB_RECURSE headers
+ ../../include/clang${dir}/*.h
+ ../../include/clang${dir}/*.td
+ ../../include/clang${dir}/*.def)
set(srcs ${srcs} ${headers})
endif(MSVC_IDE OR XCODE)
add_library( ${name} ${srcs} )
@@ -29,7 +32,7 @@ endmacro(add_clang_library)
macro(add_clang_executable name)
set(srcs ${ARGN})
if(MSVC_IDE)
- file( GLOB_RECURSE headers *.h)
+ file( GLOB_RECURSE headers *.h *.td *.def)
set(srcs ${srcs} ${headers})
endif(MSVC_IDE)
add_llvm_executable( ${name} ${srcs} )
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index f4313f4dbfff..b686b0edd30a 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -71,6 +71,7 @@ class ASTContext {
llvm::FoldingSet<IncompleteArrayType> IncompleteArrayTypes;
std::vector<VariableArrayType*> VariableArrayTypes;
std::vector<DependentSizedArrayType*> DependentSizedArrayTypes;
+ std::vector<DependentSizedExtVectorType*> DependentSizedExtVectorTypes;
llvm::FoldingSet<VectorType> VectorTypes;
llvm::FoldingSet<FunctionNoProtoType> FunctionNoProtoTypes;
llvm::FoldingSet<FunctionProtoType> FunctionProtoTypes;
@@ -79,7 +80,7 @@ class ASTContext {
llvm::FoldingSet<QualifiedNameType> QualifiedNameTypes;
llvm::FoldingSet<TypenameType> TypenameTypes;
llvm::FoldingSet<ObjCQualifiedInterfaceType> ObjCQualifiedInterfaceTypes;
- llvm::FoldingSet<ObjCQualifiedIdType> ObjCQualifiedIdTypes;
+ llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes;
llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;
llvm::FoldingSet<DependentTemplateName> DependentTemplateNames;
@@ -103,7 +104,7 @@ class ASTContext {
/// This is initially null and set by Sema::LazilyCreateBuiltin when
/// a builtin that takes a valist is encountered.
QualType BuiltinVaListType;
-
+
/// ObjCIdType - a pseudo built-in typedef type (set by Sema).
QualType ObjCIdType;
const RecordType *IdStructType;
@@ -125,6 +126,12 @@ class ASTContext {
RecordDecl *ObjCFastEnumerationStateTypeDecl;
+ /// \brief Keeps track of all declaration attributes.
+ ///
+ /// Since so few decls have attrs, we keep them in a hash map instead of
+ /// wasting space in the Decl class.
+ llvm::DenseMap<const Decl*, Attr*> DeclAttrs;
+
TranslationUnitDecl *TUDecl;
/// SourceMgr - The associated SourceManager object.
@@ -163,6 +170,12 @@ public:
return FullSourceLoc(Loc,SourceMgr);
}
+ /// \brief Retrieve the attributes for the given declaration.
+ Attr*& getDeclAttrs(const Decl *D) { return DeclAttrs[D]; }
+
+ /// \brief Erase the attributes corresponding to the given declaration.
+ void eraseDeclAttrs(const Decl *D) { DeclAttrs.erase(D); }
+
TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; }
@@ -277,6 +290,14 @@ public:
/// type.
QualType getExtVectorType(QualType VectorType, unsigned NumElts);
+ /// getDependentSizedExtVectorType - Returns a non-unique reference to
+ /// the type for a dependently-sized vector of the specified element
+ /// type. FIXME: We will need these to be uniqued, or at least
+ /// comparable, at some point.
+ QualType getDependentSizedExtVectorType(QualType VectorType,
+ Expr *SizeExpr,
+ SourceLocation AttrLoc);
+
/// getFunctionNoProtoType - Return a K&R style C function type like 'int()'.
///
QualType getFunctionNoProtoType(QualType ResultTy);
@@ -299,6 +320,7 @@ public:
QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl);
QualType getTemplateTypeParmType(unsigned Depth, unsigned Index,
+ bool ParameterPack,
IdentifierInfo *Name = 0);
QualType getTemplateSpecializationType(TemplateName T,
@@ -315,6 +337,12 @@ public:
const TemplateSpecializationType *TemplateId,
QualType Canon = QualType());
+ /// getObjCObjectPointerType - Return a ObjCObjectPointerType type for the
+ /// given interface decl and the conforming protocol list.
+ QualType getObjCObjectPointerType(ObjCInterfaceDecl *Decl,
+ ObjCProtocolDecl **ProtocolList = 0,
+ unsigned NumProtocols = 0);
+
/// getObjCQualifiedInterfaceType - Return a
/// ObjCQualifiedInterfaceType type for the given interface decl and
/// the conforming protocol list.
@@ -416,7 +444,7 @@ public:
/// getObjCEncodingTypeSize returns size of type for objective-c encoding
/// purpose.
int getObjCEncodingTypeSize(QualType t);
-
+
/// This setter/getter represents the ObjC 'id' type. It is setup lazily, by
/// Sema. id is always a (typedef for a) pointer type, a pointer to a struct.
QualType getObjCIdType() const { return ObjCIdType; }
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 7440e7b5f150..77b7bf6a9520 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -146,8 +146,8 @@ public:
}
void setOriginalNamespace(NamespaceDecl *ND) { OrigNamespace = ND; }
- SourceRange getSourceRange() const {
- return SourceRange(LBracLoc, RBracLoc);
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(getLocation(), RBracLoc);
}
SourceLocation getLBracLoc() const { return LBracLoc; }
@@ -259,6 +259,8 @@ public:
StorageClass getStorageClass() const { return (StorageClass)SClass; }
void setStorageClass(StorageClass SC) { SClass = SC; }
+
+ virtual SourceRange getSourceRange() const;
SourceLocation getTypeSpecStartLoc() const { return TypeSpecStartLoc; }
void setTypeSpecStartLoc(SourceLocation SL) {
@@ -644,6 +646,8 @@ private:
// Move to DeclGroup when it is implemented.
SourceLocation TypeSpecStartLoc;
+
+ SourceLocation EndRangeLoc;
/// \brief The template or declaration that this declaration
/// describes or was instantiated from, respectively.
@@ -667,7 +671,7 @@ protected:
SClass(S), IsInline(isInline), C99InlineDefinition(false),
IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false),
HasWrittenPrototype(true), IsDeleted(false), TypeSpecStartLoc(TSSL),
- TemplateOrInstantiation() {}
+ EndRangeLoc(L), TemplateOrInstantiation() {}
virtual ~FunctionDecl() {}
virtual void Destroy(ASTContext& C);
@@ -677,7 +681,15 @@ public:
DeclarationName N, QualType T,
StorageClass S = None, bool isInline = false,
bool hasWrittenPrototype = true,
- SourceLocation TSStartLoc = SourceLocation());
+ SourceLocation TSStartLoc = SourceLocation());
+
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(getLocation(), EndRangeLoc);
+ }
+ void setLocEnd(SourceLocation E) {
+ assert(getLocation() <= E && "Invalid end location");
+ EndRangeLoc = E;
+ }
SourceLocation getTypeSpecStartLoc() const { return TypeSpecStartLoc; }
void setTypeSpecStartLoc(SourceLocation TS) { TypeSpecStartLoc = TS; }
@@ -706,7 +718,7 @@ public:
/// CodeGenModule.cpp uses it, and I don't know if this would break it.
bool isThisDeclarationADefinition() const { return Body; }
- void setBody(Stmt *B) { Body = B; }
+ void setBody(Stmt *B);
void setLazyBody(uint64_t Offset) { Body = Offset; }
/// Whether this function is marked as virtual explicitly.
@@ -832,12 +844,12 @@ public:
/// The gnu_inline attribute only introduces GNU inline semantics
/// when all of the inline declarations of the function are marked
/// gnu_inline.
- bool hasActiveGNUInlineAttribute() const;
+ bool hasActiveGNUInlineAttribute(ASTContext &Context) const;
/// \brief Determines whether this function is a GNU "extern
/// inline", which is roughly the opposite of a C99 "extern inline"
/// function.
- bool isExternGNUInline() const;
+ bool isExternGNUInline(ASTContext &Context) const;
/// isOverloadedOperator - Whether this function declaration
/// represents an C++ overloaded operator, e.g., "operator+".
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index 5c9fd342fa96..a75eecd02220 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -156,9 +156,15 @@ private:
/// the implementation rather than explicitly written by the user.
bool Implicit : 1;
+ /// \brief Whether this declaration was "used", meaning that a definition is
+ /// required.
+ bool Used : 1;
+
+protected:
/// IdentifierNamespace - This specifies what IDNS_* namespace this lives in.
unsigned IdentifierNamespace : 8;
+private:
#ifndef NDEBUG
void CheckAccessDeclContext() const;
#else
@@ -174,7 +180,7 @@ protected:
Decl(Kind DK, DeclContext *DC, SourceLocation L)
: NextDeclInContext(0), DeclCtx(DC),
Loc(L), DeclKind(DK), InvalidDecl(0),
- HasAttrs(false), Implicit(false),
+ HasAttrs(false), Implicit(false), Used(false),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)), Access(AS_none) {
if (Decl::CollectingStats()) addDeclKind(DK);
}
@@ -182,6 +188,14 @@ protected:
virtual ~Decl();
public:
+
+ /// \brief Source range that this declaration covers.
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(getLocation(), getLocation());
+ }
+ SourceLocation getLocStart() const { return getSourceRange().getBegin(); }
+ SourceLocation getLocEnd() const { return getSourceRange().getEnd(); }
+
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
@@ -211,23 +225,23 @@ public:
}
bool hasAttrs() const { return HasAttrs; }
- void addAttr(Attr *attr);
- const Attr *getAttrs() const {
+ void addAttr(ASTContext &Context, Attr *attr);
+ const Attr *getAttrs(ASTContext &Context) const {
if (!HasAttrs) return 0; // common case, no attributes.
- return getAttrsImpl(); // Uncommon case, out of line hash lookup.
+ return getAttrsImpl(Context); // Uncommon case, out of line hash lookup.
}
- void swapAttrs(Decl *D);
- void invalidateAttrs();
+ void swapAttrs(ASTContext &Context, Decl *D);
+ void invalidateAttrs(ASTContext &Context);
- template<typename T> const T *getAttr() const {
- for (const Attr *attr = getAttrs(); attr; attr = attr->getNext())
+ template<typename T> const T *getAttr(ASTContext &Context) const {
+ for (const Attr *attr = getAttrs(Context); attr; attr = attr->getNext())
if (const T *V = dyn_cast<T>(attr))
return V;
return 0;
}
- template<typename T> bool hasAttr() const {
- return getAttr<T>() != 0;
+ template<typename T> bool hasAttr(ASTContext &Context) const {
+ return getAttr<T>(Context) != 0;
}
/// setInvalidDecl - Indicates the Decl had a semantic error. This
@@ -241,6 +255,11 @@ public:
bool isImplicit() const { return Implicit; }
void setImplicit(bool I = true) { Implicit = I; }
+ /// \brief Whether this declaration was used, meaning that a definition
+ /// is required.
+ bool isUsed() const { return Used; }
+ void setUsed(bool U = true) { Used = U; }
+
unsigned getIdentifierNamespace() const {
return IdentifierNamespace;
}
@@ -268,6 +287,10 @@ public:
const DeclContext *getLexicalDeclContext() const {
return const_cast<Decl*>(this)->getLexicalDeclContext();
}
+
+ bool isOutOfLine() const {
+ return getLexicalDeclContext() != getDeclContext();
+ }
/// setDeclContext - Set both the semantic and lexical DeclContext
/// to DC.
@@ -325,7 +348,7 @@ public:
void dump(ASTContext &Context);
private:
- const Attr *getAttrsImpl() const;
+ const Attr *getAttrsImpl(ASTContext &Context) const;
};
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index 4a74a2c2cbc4..9ca1823f3822 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -439,6 +439,9 @@ public:
TemplateOrInstantiation = Template;
}
+ /// getDefaultConstructor - Returns the default constructor for this class
+ CXXConstructorDecl *getDefaultConstructor(ASTContext &Context);
+
/// getDestructor - Returns the destructor decl for this class.
const CXXDestructorDecl *getDestructor(ASTContext &Context);
@@ -477,10 +480,6 @@ public:
bool isStatic() const { return getStorageClass() == Static; }
bool isInstance() const { return !isStatic(); }
- bool isOutOfLineDefinition() const {
- return getLexicalDeclContext() != getDeclContext();
- }
-
bool isVirtual() const {
return isVirtualAsWritten() ||
(begin_overridden_methods() != end_overridden_methods());
@@ -535,6 +534,7 @@ public:
/// public:
/// B(A& a) : A(a), f(3.14159) { }
/// };
+/// @endcode
class CXXBaseOrMemberInitializer {
/// BaseOrMember - This points to the entity being initialized,
/// which is either a base class (a Type) or a non-static data
@@ -641,6 +641,10 @@ class CXXConstructorDecl : public CXXMethodDecl {
/// explicitly defaulted (i.e., defined with " = default") will have
/// @c !Implicit && ImplicitlyDefined.
bool ImplicitlyDefined : 1;
+
+ /// ImplicitMustBeDefined - Implicit constructor was used to create an
+ /// object of its class type. It must be defined.
+ bool ImplicitMustBeDefined : 1;
/// FIXME: Add support for base and member initializers.
@@ -648,7 +652,8 @@ class CXXConstructorDecl : public CXXMethodDecl {
DeclarationName N, QualType T,
bool isExplicit, bool isInline, bool isImplicitlyDeclared)
: CXXMethodDecl(CXXConstructor, RD, L, N, T, false, isInline),
- Explicit(isExplicit), ImplicitlyDefined(false) {
+ Explicit(isExplicit), ImplicitlyDefined(false),
+ ImplicitMustBeDefined(false) {
setImplicit(isImplicitlyDeclared);
}
@@ -679,6 +684,17 @@ public:
ImplicitlyDefined = ID;
}
+ /// isImplicitMustBeDefined - Whether a definition must be synthesized for
+ /// the implicit constructor.
+ bool isImplicitMustBeDefined() const {
+ return isImplicit() && ImplicitMustBeDefined;
+ }
+
+ /// setImplicitMustBeDefined - constructor must be implicitly defined.
+ void setImplicitMustBeDefined() {
+ ImplicitMustBeDefined = true;
+ }
+
/// isDefaultConstructor - Whether this constructor is a default
/// constructor (C++ [class.ctor]p5), which can be used to
/// default-initialize a class of this type.
@@ -1033,6 +1049,61 @@ public:
}
static bool classof(const NamespaceAliasDecl *D) { return true; }
};
+
+/// UsingDecl - Represents a C++ using-declaration. For example:
+/// using someNameSpace::someIdentifier;
+class UsingDecl : public NamedDecl {
+
+ /// \brief The source range that covers the nested-name-specifier
+ /// preceding the declaration name.
+ SourceRange NestedNameRange;
+ /// \brief The source location of the target declaration name.
+ SourceLocation TargetNameLocation;
+ /// \brief The source location of the "using" location itself.
+ SourceLocation UsingLocation;
+ /// \brief Target declaration.
+ NamedDecl* TargetDecl;
+ /// \brief Target declaration.
+ NestedNameSpecifier* TargetNestedNameDecl;
+
+ // Had 'typename' keyword.
+ bool IsTypeName;
+
+ UsingDecl(DeclContext *DC, SourceLocation L, SourceRange NNR,
+ SourceLocation TargetNL, SourceLocation UL, NamedDecl* Target,
+ NestedNameSpecifier* TargetNNS, bool IsTypeNameArg)
+ : NamedDecl(Decl::Using, DC, L, Target->getDeclName()),
+ NestedNameRange(NNR), TargetNameLocation(TargetNL),
+ UsingLocation(UL), TargetDecl(Target),
+ TargetNestedNameDecl(TargetNNS), IsTypeName(IsTypeNameArg) {
+ this->IdentifierNamespace = TargetDecl->getIdentifierNamespace();
+ }
+
+public:
+ /// \brief Returns the source range that covers the nested-name-specifier
+ /// preceding the namespace name.
+ SourceRange getNestedNameRange() { return(NestedNameRange); }
+ /// \brief Returns the source location of the target declaration name.
+ SourceLocation getTargetNameLocation() { return(TargetNameLocation); }
+ /// \brief Returns the source location of the "using" location itself.
+ SourceLocation getUsingLocation() { return(UsingLocation); }
+ /// \brief getTargetDecl - Returns target specified by using-decl.
+ NamedDecl *getTargetDecl() { return(TargetDecl); }
+ /// \brief Get target nested name declaration.
+ NestedNameSpecifier* getTargetNestedNameDecl() { return(TargetNestedNameDecl); }
+ /// isTypeName - Return true if using decl had 'typename'.
+ bool isTypeName() const { return(IsTypeName); }
+
+ static UsingDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, SourceRange NNR, SourceLocation TargetNL,
+ SourceLocation UL, NamedDecl* Target,
+ NestedNameSpecifier* TargetNNS, bool IsTypeNameArg);
+
+ static bool classof(const Decl *D) {
+ return D->getKind() == Decl::Using;
+ }
+ static bool classof(const UsingDecl *D) { return true; }
+};
/// StaticAssertDecl - Represents a C++0x static_assert declaration.
class StaticAssertDecl : public Decl {
diff --git a/include/clang/AST/DeclNodes.def b/include/clang/AST/DeclNodes.def
index d1b921a4cb65..1e4440357b65 100644
--- a/include/clang/AST/DeclNodes.def
+++ b/include/clang/AST/DeclNodes.def
@@ -108,6 +108,7 @@ ABSTRACT_DECL(Named, Decl)
DECL(FunctionTemplate, TemplateDecl)
DECL(ClassTemplate, TemplateDecl)
DECL(TemplateTemplateParm, TemplateDecl)
+ DECL(Using, NamedDecl)
DECL(ObjCMethod, NamedDecl)
DECL(ObjCContainer, NamedDecl)
DECL(ObjCCategory, ObjCContainerDecl)
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index a480f54394c6..af06965f84e9 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/PointerUnion.h"
+#include <limits>
namespace clang {
@@ -404,6 +405,11 @@ class TemplateArgument {
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.
@@ -413,7 +419,7 @@ public:
/// \brief The type of template argument we're storing.
enum ArgKind {
Null = 0,
- /// The template argument is a type. It's value is stored in the
+ /// The template argument is a type. Its value is stored in the
/// TypeOrValue field.
Type = 1,
/// The template argument is a declaration
@@ -422,7 +428,11 @@ public:
Integral = 3,
/// The template argument is a value- or type-dependent expression
/// stored in an Expr*.
- Expression = 4
+ 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.
@@ -459,11 +469,20 @@ public:
/// occur in a non-dependent, canonical template argument list.
TemplateArgument(Expr *E);
+ /// \brief Construct a template argument pack.
+ TemplateArgument(SourceLocation Loc, TemplateArgument *Args,
+ unsigned NumArgs, bool CopyArgs);
+
/// \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;
@@ -475,6 +494,10 @@ public:
// 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();
@@ -502,6 +525,8 @@ public:
if (Kind == Integral)
getAsIntegral()->~APSInt();
+ else if (Kind == Pack && Args.CopyArgs)
+ delete[] Args.Args;
}
/// \brief Return the kind of stored template argument.
@@ -586,34 +611,44 @@ public:
// FIXME: We need a canonical representation of expressions.
ID.AddPointer(getAsExpr());
break;
+
+ case Pack:
+ ID.AddInteger(Args.NumArgs);
+ for (unsigned I = 0; I != Args.NumArgs; ++I)
+ Args.Args[I].Profile(ID);
}
}
};
/// \brief A helper class for making template argument lists.
class TemplateArgumentListBuilder {
- /// Args - contains the template arguments.
- llvm::SmallVector<TemplateArgument, 16> Args;
+ /// FlatArgs - contains the template arguments in flat form.
+ llvm::SmallVector<TemplateArgument, 16> FlatArgs;
- llvm::SmallVector<unsigned, 32> Indices;
+ llvm::SmallVector<TemplateArgument, 16> StructuredArgs;
ASTContext &Context;
+ unsigned PackBeginIndex;
+
/// isAddingFromParameterPack - Returns whether we're adding arguments from
/// a parameter pack.
- bool isAddingFromParameterPack() const { return Indices.size() % 2; }
+ bool isAddingFromParameterPack() const {
+ return PackBeginIndex != std::numeric_limits<unsigned>::max();
+ }
public:
- TemplateArgumentListBuilder(ASTContext &Context) : Context(Context) { }
+ TemplateArgumentListBuilder(ASTContext &Context) : Context(Context),
+ PackBeginIndex(std::numeric_limits<unsigned>::max()) { }
- size_t size() const {
+ size_t structuredSize() const {
assert(!isAddingFromParameterPack() &&
"Size is not valid when adding from a parameter pack");
- return Indices.size() / 2;
+ return StructuredArgs.size();
}
- size_t flatSize() const { return Args.size(); }
+ size_t flatSize() const { return FlatArgs.size(); }
void push_back(const TemplateArgument& Arg);
@@ -623,8 +658,12 @@ public:
/// EndParameterPack - Finish adding arguments from a parameter pack.
void EndParameterPack();
- const TemplateArgument *getFlatArgumentList() const { return Args.data(); }
- TemplateArgument *getFlatArgumentList() { return Args.data(); }
+ const TemplateArgument *getFlatArgumentList() const {
+ return FlatArgs.data();
+ }
+ TemplateArgument *getFlatArgumentList() {
+ return FlatArgs.data();
+ }
};
/// \brief A template argument list.
@@ -657,13 +696,6 @@ public:
}
/// \brief Retrieve the template argument at a given index.
- TemplateArgument &get(unsigned Idx) {
- assert(Idx < NumArguments && "Invalid template argument index");
- return getFlatArgumentList()[Idx];
- }
-
- /// \brief Retrieve the template argument at a given index.
- TemplateArgument &operator[](unsigned Idx) { return get(Idx); }
const TemplateArgument &operator[](unsigned Idx) const { return get(Idx); }
/// \brief Retrieve the number of template arguments in this
@@ -675,9 +707,6 @@ public:
unsigned flat_size() const { return NumArguments; }
/// \brief Retrieve the flattened template argument list.
- TemplateArgument *getFlatArgumentList() {
- return Arguments.getPointer();
- }
const TemplateArgument *getFlatArgumentList() const {
return Arguments.getPointer();
}
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index 98de5f9d382e..2ed91124758d 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -124,7 +124,7 @@ public:
/// 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 &Context) 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:
@@ -2463,10 +2463,13 @@ public:
class BlockDeclRefExpr : public Expr {
ValueDecl *D;
SourceLocation Loc;
- bool IsByRef;
+ bool IsByRef : 1;
+ bool ConstQualAdded : 1;
public:
- BlockDeclRefExpr(ValueDecl *d, QualType t, SourceLocation l, bool ByRef) :
- Expr(BlockDeclRefExprClass, t), D(d), Loc(l), IsByRef(ByRef) {}
+ BlockDeclRefExpr(ValueDecl *d, QualType t, SourceLocation l, bool ByRef,
+ bool constAdded = false) :
+ Expr(BlockDeclRefExprClass, t), D(d), Loc(l), IsByRef(ByRef),
+ ConstQualAdded(constAdded) {}
// \brief Build an empty reference to a declared variable in a
// block.
@@ -2484,6 +2487,9 @@ public:
bool isByRef() const { return IsByRef; }
void setByRef(bool BR) { IsByRef = BR; }
+
+ bool isConstQualAdded() const { return ConstQualAdded; }
+ void setConstQualAdded(bool C) { ConstQualAdded = C; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == BlockDeclRefExprClass;
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index e44ccca0bd74..f9f5da129142 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -1023,17 +1023,16 @@ class CXXExprWithTemporaries : public Expr {
CXXTemporary **Temps;
unsigned NumTemps;
- bool DestroyTemps;
+ bool ShouldDestroyTemps;
CXXExprWithTemporaries(Expr *SubExpr, CXXTemporary **Temps,
- unsigned NumTemps, bool DestroyTemps);
+ unsigned NumTemps, bool ShouldDestroyTemps);
~CXXExprWithTemporaries();
public:
static CXXExprWithTemporaries *Create(ASTContext &C, Expr *SubExpr,
- CXXTemporary **Temps,
- unsigned NumTemps,
- bool DestroyTems);
+ CXXTemporary **Temps, unsigned NumTemps,
+ bool ShouldDestroyTemporaries);
void Destroy(ASTContext &C);
unsigned getNumTemporaries() const { return NumTemps; }
@@ -1046,6 +1045,8 @@ public:
return Temps[i];
}
+ bool shouldDestroyTemporaries() const { return ShouldDestroyTemps; }
+
void removeLastTemporary() { NumTemps--; }
Expr *getSubExpr() { return cast<Expr>(SubExpr); }
diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h
index ef78c4081e34..e00833b5820e 100644
--- a/include/clang/AST/ExprObjC.h
+++ b/include/clang/AST/ExprObjC.h
@@ -138,20 +138,20 @@ public:
/// obj conformsToProtocol:@protocol(foo)]
/// The return type is "Protocol*".
class ObjCProtocolExpr : public Expr {
- ObjCProtocolDecl *Protocol;
+ ObjCProtocolDecl *TheProtocol;
SourceLocation AtLoc, RParenLoc;
public:
ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol,
SourceLocation at, SourceLocation rp)
- : Expr(ObjCProtocolExprClass, T), Protocol(protocol),
+ : Expr(ObjCProtocolExprClass, T), TheProtocol(protocol),
AtLoc(at), RParenLoc(rp) {}
explicit ObjCProtocolExpr(EmptyShell Empty)
: Expr(ObjCProtocolExprClass, Empty) {}
ObjCProtocolExpr *Clone(ASTContext &C) const;
- ObjCProtocolDecl *getProtocol() const { return Protocol; }
- void setProtocol(ObjCProtocolDecl *P) { Protocol = P; }
+ ObjCProtocolDecl *getProtocol() const { return TheProtocol; }
+ void setProtocol(ObjCProtocolDecl *P) { TheProtocol = P; }
SourceLocation getAtLoc() const { return AtLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 1b012385c9f2..ca55ea670b24 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -393,6 +393,7 @@ public:
bool isComplexIntegerType() const; // GCC _Complex integer type.
bool isVectorType() const; // GCC vector type.
bool isExtVectorType() const; // Extended vector type.
+ bool isObjCObjectPointerType() const; // Pointer to *any* ObjC object.
bool isObjCInterfaceType() const; // NSString or NSString<foo>
bool isObjCQualifiedInterfaceType() const; // NSString<foo>
bool isObjCQualifiedIdType() const; // id<foo>
@@ -439,9 +440,10 @@ public:
const ComplexType *getAsComplexType() const;
const ComplexType *getAsComplexIntegerType() const; // GCC complex int type.
const ExtVectorType *getAsExtVectorType() const; // Extended vector type.
+ const ObjCObjectPointerType *getAsObjCObjectPointerType() const;
const ObjCInterfaceType *getAsObjCInterfaceType() const;
const ObjCQualifiedInterfaceType *getAsObjCQualifiedInterfaceType() const;
- const ObjCQualifiedIdType *getAsObjCQualifiedIdType() const;
+ const ObjCObjectPointerType *getAsObjCQualifiedIdType() const;
const TemplateTypeParmType *getAsTemplateTypeParmType() const;
const TemplateSpecializationType *
@@ -992,6 +994,41 @@ public:
}
};
+/// DependentSizedExtVectorType - This type represent an extended vector type
+/// where either the type or size is dependent. For example:
+/// @code
+/// template<typename T, int Size>
+/// class vector {
+/// typedef T __attribute__((ext_vector_type(Size))) type;
+/// }
+/// @endcode
+class DependentSizedExtVectorType : public Type {
+ Expr *SizeExpr;
+ /// ElementType - The element type of the array.
+ QualType ElementType;
+ SourceLocation loc;
+
+ DependentSizedExtVectorType(QualType ElementType, QualType can,
+ Expr *SizeExpr, SourceLocation loc)
+ : Type (DependentSizedExtVector, can, true),
+ SizeExpr(SizeExpr), ElementType(ElementType), loc(loc) {}
+ friend class ASTContext;
+ virtual void Destroy(ASTContext& C);
+
+public:
+ const Expr *getSizeExpr() const { return SizeExpr; }
+ QualType getElementType() const { return ElementType; }
+ SourceLocation getAttributeLoc() const { return loc; }
+
+ virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const;
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == DependentSizedExtVector;
+ }
+ static bool classof(const DependentSizedExtVectorType *) { return true; }
+};
+
+
/// VectorType - GCC generic vector type. This type is created using
/// __attribute__((vector_size(n)), where "n" specifies the vector size in
/// bytes. Since the constructor takes the number of vector elements, the
@@ -1403,36 +1440,40 @@ public:
};
class TemplateTypeParmType : public Type, public llvm::FoldingSetNode {
- unsigned Depth : 16;
+ unsigned Depth : 15;
unsigned Index : 16;
+ unsigned ParameterPack : 1;
IdentifierInfo *Name;
- TemplateTypeParmType(unsigned D, unsigned I, IdentifierInfo *N,
+ TemplateTypeParmType(unsigned D, unsigned I, bool PP, IdentifierInfo *N,
QualType Canon)
: Type(TemplateTypeParm, Canon, /*Dependent=*/true),
- Depth(D), Index(I), Name(N) { }
+ Depth(D), Index(I), ParameterPack(PP), Name(N) { }
- TemplateTypeParmType(unsigned D, unsigned I)
+ TemplateTypeParmType(unsigned D, unsigned I, bool PP)
: Type(TemplateTypeParm, QualType(this, 0), /*Dependent=*/true),
- Depth(D), Index(I), Name(0) { }
+ Depth(D), Index(I), ParameterPack(PP), Name(0) { }
friend class ASTContext; // ASTContext creates these
public:
unsigned getDepth() const { return Depth; }
unsigned getIndex() const { return Index; }
+ bool isParameterPack() const { return ParameterPack; }
IdentifierInfo *getName() const { return Name; }
virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const;
void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, Depth, Index, Name);
+ Profile(ID, Depth, Index, ParameterPack, Name);
}
static void Profile(llvm::FoldingSetNodeID &ID, unsigned Depth,
- unsigned Index, IdentifierInfo *Name) {
+ unsigned Index, bool ParameterPack,
+ IdentifierInfo *Name) {
ID.AddInteger(Depth);
ID.AddInteger(Index);
+ ID.AddBoolean(ParameterPack);
ID.AddPointer(Name);
}
@@ -1644,6 +1685,53 @@ public:
static bool classof(const TypenameType *T) { return true; }
};
+/// ObjCObjectPointerType - Used to represent 'id', 'Interface *', 'id <p>',
+/// and 'Interface <p> *'.
+///
+/// Duplicate protocols are removed and protocol list is canonicalized to be in
+/// alphabetical order.
+class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {
+ ObjCInterfaceDecl *Decl;
+ // List of protocols for this protocol conforming object type
+ // List is sorted on protocol name. No protocol is entered more than once.
+ llvm::SmallVector<ObjCProtocolDecl*, 8> Protocols;
+
+ ObjCObjectPointerType(ObjCInterfaceDecl *D,
+ ObjCProtocolDecl **Protos, unsigned NumP) :
+ Type(ObjCObjectPointer, QualType(), /*Dependent=*/false),
+ Decl(D), Protocols(Protos, Protos+NumP) { }
+ friend class ASTContext; // ASTContext creates these.
+
+public:
+ ObjCInterfaceDecl *getDecl() const { return Decl; }
+
+ /// isObjCQualifiedIdType - true for "id <p>".
+ bool isObjCQualifiedIdType() const { return Decl == 0 && Protocols.size(); }
+
+ /// qual_iterator and friends: this provides access to the (potentially empty)
+ /// list of protocols qualifying this interface.
+ typedef llvm::SmallVector<ObjCProtocolDecl*, 8>::const_iterator qual_iterator;
+
+ qual_iterator qual_begin() const { return Protocols.begin(); }
+ qual_iterator qual_end() const { return Protocols.end(); }
+ bool qual_empty() const { return Protocols.size() == 0; }
+
+ /// getNumProtocols - Return the number of qualifying protocols in this
+ /// interface type, or 0 if there are none.
+ unsigned getNumProtocols() const { return Protocols.size(); }
+
+ void Profile(llvm::FoldingSetNodeID &ID);
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ const ObjCInterfaceDecl *Decl,
+ ObjCProtocolDecl **protocols, unsigned NumProtocols);
+ virtual void getAsStringInternal(std::string &InnerString,
+ const PrintingPolicy &Policy) const;
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == ObjCObjectPointer;
+ }
+ static bool classof(const ObjCObjectPointerType *) { return true; }
+};
+
/// ObjCInterfaceType - Interfaces are the core concept in Objective-C for
/// object oriented design. They basically correspond to C++ classes. There
/// are two kinds of interface types, normal interfaces like "NSString" and
@@ -1742,44 +1830,6 @@ inline unsigned ObjCInterfaceType::getNumProtocols() const {
return 0;
}
-/// ObjCQualifiedIdType - to represent id<protocol-list>.
-///
-/// Duplicate protocols are removed and protocol list is canonicalized to be in
-/// alphabetical order.
-class ObjCQualifiedIdType : public Type,
- public llvm::FoldingSetNode {
- // List of protocols for this protocol conforming 'id' type
- // List is sorted on protocol name. No protocol is enterred more than once.
- llvm::SmallVector<ObjCProtocolDecl*, 8> Protocols;
-
- ObjCQualifiedIdType(ObjCProtocolDecl **Protos, unsigned NumP)
- : Type(ObjCQualifiedId, QualType()/*these are always canonical*/,
- /*Dependent=*/false),
- Protocols(Protos, Protos+NumP) { }
- friend class ASTContext; // ASTContext creates these.
-public:
-
- unsigned getNumProtocols() const {
- return Protocols.size();
- }
-
- typedef llvm::SmallVector<ObjCProtocolDecl*, 8>::const_iterator qual_iterator;
- qual_iterator qual_begin() const { return Protocols.begin(); }
- qual_iterator qual_end() const { return Protocols.end(); }
-
- virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const;
-
- void Profile(llvm::FoldingSetNodeID &ID);
- static void Profile(llvm::FoldingSetNodeID &ID,
- ObjCProtocolDecl **protocols, unsigned NumProtocols);
-
- static bool classof(const Type *T) {
- return T->getTypeClass() == ObjCQualifiedId;
- }
- static bool classof(const ObjCQualifiedIdType *) { return true; }
-
-};
-
// Inline function definitions.
/// getUnqualifiedType - Return the type without any qualifiers.
@@ -1926,6 +1976,9 @@ inline bool Type::isVectorType() const {
inline bool Type::isExtVectorType() const {
return isa<ExtVectorType>(CanonicalType.getUnqualifiedType());
}
+inline bool Type::isObjCObjectPointerType() const {
+ return isa<ObjCObjectPointerType>(CanonicalType.getUnqualifiedType());
+}
inline bool Type::isObjCInterfaceType() const {
return isa<ObjCInterfaceType>(CanonicalType.getUnqualifiedType());
}
@@ -1933,7 +1986,10 @@ inline bool Type::isObjCQualifiedInterfaceType() const {
return isa<ObjCQualifiedInterfaceType>(CanonicalType.getUnqualifiedType());
}
inline bool Type::isObjCQualifiedIdType() const {
- return isa<ObjCQualifiedIdType>(CanonicalType.getUnqualifiedType());
+ if (const ObjCObjectPointerType *OPT = getAsObjCObjectPointerType()) {
+ return OPT->isObjCQualifiedIdType();
+ }
+ return false;
}
inline bool Type::isTemplateTypeParmType() const {
return isa<TemplateTypeParmType>(CanonicalType.getUnqualifiedType());
diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def
index 76cbed311d79..5555a9b0ae7e 100644
--- a/include/clang/AST/TypeNodes.def
+++ b/include/clang/AST/TypeNodes.def
@@ -60,6 +60,7 @@ TYPE(ConstantArray, ArrayType)
TYPE(IncompleteArray, ArrayType)
TYPE(VariableArray, ArrayType)
DEPENDENT_TYPE(DependentSizedArray, ArrayType)
+DEPENDENT_TYPE(DependentSizedExtVector, Type)
TYPE(Vector, Type)
TYPE(ExtVector, VectorType)
ABSTRACT_TYPE(Function, Type)
@@ -76,8 +77,8 @@ TYPE(TemplateSpecialization, Type)
NON_CANONICAL_TYPE(QualifiedName, Type)
DEPENDENT_TYPE(Typename, Type)
TYPE(ObjCInterface, Type)
+TYPE(ObjCObjectPointer, Type)
TYPE(ObjCQualifiedInterface, ObjCInterfaceType)
-TYPE(ObjCQualifiedId, Type)
#undef DEPENDENT_TYPE
#undef NON_CANONICAL_TYPE
diff --git a/include/clang/AST/TypeVisitor.h b/include/clang/AST/TypeVisitor.h
new file mode 100644
index 000000000000..a02e39b3f34e
--- /dev/null
+++ b/include/clang/AST/TypeVisitor.h
@@ -0,0 +1,50 @@
+//===--- TypeVisitor.h - Visitor for Stmt subclasses ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the TypeVisitor interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_TYPEVISITOR_H
+#define LLVM_CLANG_AST_TYPEVISITOR_H
+
+#include "clang/AST/Type.h"
+
+namespace clang {
+
+#define DISPATCH(CLASS) \
+ return static_cast<ImplClass*>(this)->Visit ## CLASS(static_cast<CLASS*>(T))
+
+template<typename ImplClass, typename RetTy=void>
+class TypeVisitor {
+public:
+ RetTy Visit(Type *T) {
+ // Top switch stmt: dispatch to VisitFooStmt for each FooStmt.
+ switch (T->getTypeClass()) {
+ default: assert(0 && "Unknown type class!");
+#define ABSTRACT_TYPE(CLASS, PARENT)
+#define TYPE(CLASS, PARENT) case Type::CLASS: DISPATCH(CLASS##Type);
+#include "clang/AST/TypeNodes.def"
+ }
+ }
+
+ // If the implementation chooses not to implement a certain visit method, fall
+ // back on superclass.
+#define TYPE(CLASS, PARENT) RetTy Visit##CLASS##Type(CLASS##Type *T) { DISPATCH(PARENT); }
+#include "clang/AST/TypeNodes.def"
+
+ // Base case, ignore it. :)
+ RetTy VisitType(Type*) { return RetTy(); }
+};
+
+#undef DISPATCH
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Analysis/PathSensitive/ConstraintManager.h b/include/clang/Analysis/PathSensitive/ConstraintManager.h
index c8e5e85c8a1a..eb519e0e7431 100644
--- a/include/clang/Analysis/PathSensitive/ConstraintManager.h
+++ b/include/clang/Analysis/PathSensitive/ConstraintManager.h
@@ -30,26 +30,25 @@ class SVal;
class ConstraintManager {
public:
virtual ~ConstraintManager();
- virtual const GRState* Assume(const GRState* St, SVal Cond,
- bool Assumption, bool& isFeasible) = 0;
+ virtual const GRState *Assume(const GRState *state, SVal Cond,
+ bool Assumption) = 0;
- virtual const GRState* AssumeInBound(const GRState* St, SVal Idx,
- SVal UpperBound, bool Assumption,
- bool& isFeasible) = 0;
+ virtual const GRState *AssumeInBound(const GRState *state, SVal Idx,
+ SVal UpperBound, bool Assumption) = 0;
- virtual const llvm::APSInt* getSymVal(const GRState* St, SymbolRef sym)
- const = 0;
+ virtual const llvm::APSInt* getSymVal(const GRState *state,
+ SymbolRef sym) const = 0;
- virtual bool isEqual(const GRState* St, SymbolRef sym,
+ virtual bool isEqual(const GRState *state, SymbolRef sym,
const llvm::APSInt& V) const = 0;
- virtual const GRState* RemoveDeadBindings(const GRState* St,
+ virtual const GRState *RemoveDeadBindings(const GRState *state,
SymbolReaper& SymReaper) = 0;
- virtual void print(const GRState* St, std::ostream& Out,
+ virtual void print(const GRState *state, std::ostream& Out,
const char* nl, const char *sep) = 0;
- virtual void EndPath(const GRState* St) {}
+ virtual void EndPath(const GRState *state) {}
/// canReasonAbout - Not all ConstraintManagers can accurately reason about
/// all SVal values. This method returns true if the ConstraintManager can
diff --git a/include/clang/Analysis/PathSensitive/Environment.h b/include/clang/Analysis/PathSensitive/Environment.h
index fde8b167f3c7..0fc49f5a586e 100644
--- a/include/clang/Analysis/PathSensitive/Environment.h
+++ b/include/clang/Analysis/PathSensitive/Environment.h
@@ -30,13 +30,12 @@ class EnvironmentManager;
class BasicValueFactory;
class LiveVariables;
-class Environment : public llvm::FoldingSetNode {
+class Environment {
private:
-
friend class EnvironmentManager;
// Type definitions.
- typedef llvm::ImmutableMap<Stmt*,SVal> BindingsTy;
+ typedef llvm::ImmutableMap<const Stmt*,SVal> BindingsTy;
// Data.
BindingsTy SubExprBindings;
@@ -55,25 +54,25 @@ public:
beb_iterator beb_begin() const { return BlkExprBindings.begin(); }
beb_iterator beb_end() const { return BlkExprBindings.end(); }
- SVal LookupSubExpr(Stmt* E) const {
+ SVal LookupSubExpr(const Stmt* E) const {
const SVal* X = SubExprBindings.lookup(cast<Expr>(E));
return X ? *X : UnknownVal();
}
- SVal LookupBlkExpr(Stmt* E) const {
+ SVal LookupBlkExpr(const Stmt* E) const {
const SVal* X = BlkExprBindings.lookup(E);
return X ? *X : UnknownVal();
}
- SVal LookupExpr(Stmt* E) const {
+ SVal LookupExpr(const Stmt* E) const {
const SVal* X = SubExprBindings.lookup(E);
if (X) return *X;
X = BlkExprBindings.lookup(E);
return X ? *X : UnknownVal();
}
- SVal GetSVal(Stmt* Ex, BasicValueFactory& BasicVals) const;
- SVal GetBlkExprSVal(Stmt* Ex, BasicValueFactory& BasicVals) const;
+ SVal GetSVal(const Stmt* Ex, BasicValueFactory& BasicVals) const;
+ SVal GetBlkExprSVal(const Stmt* Ex, BasicValueFactory& BasicVals) const;
/// Profile - Profile the contents of an Environment object for use
/// in a FoldingSet.
@@ -109,19 +108,19 @@ public:
/// removed. This method only removes bindings for block-level expressions.
/// Using this method on a non-block level expression will return the
/// same environment object.
- Environment RemoveBlkExpr(const Environment& Env, Stmt* E) {
+ Environment RemoveBlkExpr(const Environment& Env, const Stmt* E) {
return Environment(Env.SubExprBindings, F.Remove(Env.BlkExprBindings, E));
}
- Environment RemoveSubExpr(const Environment& Env, Stmt* E) {
+ Environment RemoveSubExpr(const Environment& Env, const Stmt* E) {
return Environment(F.Remove(Env.SubExprBindings, E), Env.BlkExprBindings);
}
- Environment AddBlkExpr(const Environment& Env, Stmt* E, SVal V) {
+ Environment AddBlkExpr(const Environment& Env, const Stmt *E, SVal V) {
return Environment(Env.SubExprBindings, F.Add(Env.BlkExprBindings, E, V));
}
- Environment AddSubExpr(const Environment& Env, Stmt* E, SVal V) {
+ Environment AddSubExpr(const Environment& Env, const Stmt *E, SVal V) {
return Environment(F.Add(Env.SubExprBindings, E, V), Env.BlkExprBindings);
}
@@ -136,7 +135,7 @@ public:
return Environment(F.GetEmptyMap(), F.GetEmptyMap());
}
- Environment BindExpr(const Environment& Env, Stmt* E, SVal V,
+ Environment BindExpr(const Environment& Env, const Stmt* E, SVal V,
bool isBlkExpr, bool Invalidate);
Environment
diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h
index 2068b1beaa13..4af8a7c845a7 100644
--- a/include/clang/Analysis/PathSensitive/GRExprEngine.h
+++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h
@@ -477,67 +477,14 @@ public:
const SymbolManager& getSymbolManager() const { return SymMgr; }
protected:
-
const GRState* GetState(NodeTy* N) {
return N == EntryNode ? CleanedState : N->getState();
}
-public:
-
- const GRState* BindExpr(const GRState* St, Expr* Ex, SVal V) {
- return StateMgr.BindExpr(St, Ex, V);
- }
-
- const GRState* BindExpr(const GRState* St, const Expr* Ex, SVal V) {
- return BindExpr(St, const_cast<Expr*>(Ex), V);
- }
-
-protected:
-
- const GRState* BindBlkExpr(const GRState* St, Expr* Ex, SVal V) {
- return StateMgr.BindExpr(St, Ex, V, true, false);
- }
-
- const GRState* BindLoc(const GRState* St, Loc LV, SVal V) {
- return StateMgr.BindLoc(St, LV, V);
- }
-
- SVal GetSVal(const GRState* St, Stmt* Ex) {
- return StateMgr.GetSVal(St, Ex);
- }
-
- SVal GetSVal(const GRState* St, const Stmt* Ex) {
- return GetSVal(St, const_cast<Stmt*>(Ex));
- }
-
- SVal GetBlkExprSVal(const GRState* St, Stmt* Ex) {
- return StateMgr.GetBlkExprSVal(St, Ex);
- }
-
- SVal GetSVal(const GRState* St, Loc LV, QualType T = QualType()) {
- return StateMgr.GetSVal(St, LV, T);
- }
-
+public:
inline NonLoc MakeConstantVal(uint64_t X, Expr* Ex) {
return NonLoc::MakeVal(getBasicVals(), X, Ex->getType());
- }
-
- /// Assume - Create new state by assuming that a given expression
- /// is true or false.
- const GRState* Assume(const GRState* St, SVal Cond, bool Assumption,
- bool& isFeasible) {
- return StateMgr.Assume(St, Cond, Assumption, isFeasible);
- }
-
- const GRState* Assume(const GRState* St, Loc Cond, bool Assumption,
- bool& isFeasible) {
- return StateMgr.Assume(St, Cond, Assumption, isFeasible);
- }
-
- const GRState* AssumeInBound(const GRState* St, SVal Idx, SVal UpperBound,
- bool Assumption, bool& isFeasible) {
- return StateMgr.AssumeInBound(St, Idx, UpperBound, Assumption, isFeasible);
- }
+ }
public:
NodeTy* MakeNode(NodeSet& Dst, Stmt* S, NodeTy* Pred, const GRState* St,
diff --git a/include/clang/Analysis/PathSensitive/GRExprEngineBuilders.h b/include/clang/Analysis/PathSensitive/GRExprEngineBuilders.h
index 6c23745de23a..0f3a1372a0f0 100644
--- a/include/clang/Analysis/PathSensitive/GRExprEngineBuilders.h
+++ b/include/clang/Analysis/PathSensitive/GRExprEngineBuilders.h
@@ -83,11 +83,9 @@ public:
Dst.Add(Pred);
}
}
-
- GRStateRef getState() {
- return GRStateRef(state, Eng.getStateManager());
- }
+ const GRState *getState() { return state; }
+
GRStateManager& getStateManager() {
return Eng.getStateManager();
}
diff --git a/include/clang/Analysis/PathSensitive/GRState.h b/include/clang/Analysis/PathSensitive/GRState.h
index d61feea4819e..6f95c6ff4ab0 100644
--- a/include/clang/Analysis/PathSensitive/GRState.h
+++ b/include/clang/Analysis/PathSensitive/GRState.h
@@ -64,6 +64,8 @@ template <typename T> struct GRStateTrait {
//===----------------------------------------------------------------------===//
// GRState- An ImmutableMap type Stmt*/Decl*/Symbols to SVals.
//===----------------------------------------------------------------------===//
+
+class GRStateManager;
/// GRState - This class encapsulates the actual data values for
/// for a "state" in our symbolic value tracking. It is intended to be
@@ -81,7 +83,8 @@ private:
void operator=(const GRState& R) const;
friend class GRStateManager;
-
+
+ GRStateManager *Mgr;
Environment Env;
Store St;
@@ -92,8 +95,10 @@ public:
public:
/// This ctor is used when creating the first GRState object.
- GRState(const Environment& env, Store st, GenericDataMap gdm)
- : Env(env),
+ GRState(GRStateManager *mgr, const Environment& env, Store st,
+ GenericDataMap gdm)
+ : Mgr(mgr),
+ Env(env),
St(st),
GDM(gdm) {}
@@ -101,10 +106,14 @@ public:
/// in FoldingSetNode will also get copied.
GRState(const GRState& RHS)
: llvm::FoldingSetNode(),
+ Mgr(RHS.Mgr),
Env(RHS.Env),
St(RHS.St),
GDM(RHS.GDM) {}
+ /// getStateManager - Return the GRStateManager associated with this state.
+ GRStateManager &getStateManager() const { return *Mgr; }
+
/// getEnvironment - Return the environment associated with this state.
/// The environment is the mapping from expressions to values.
const Environment& getEnvironment() const { return Env; }
@@ -134,6 +143,10 @@ public:
return Env.LookupExpr(E);
}
+ /// makeWithStore - Return a GRState with the same values as the current
+ /// state with the exception of using the specified Store.
+ const GRState *makeWithStore(Store store) const;
+
// Iterators.
typedef Environment::seb_iterator seb_iterator;
seb_iterator seb_begin() const { return Env.seb_begin(); }
@@ -142,10 +155,119 @@ public:
typedef Environment::beb_iterator beb_iterator;
beb_iterator beb_begin() const { return Env.beb_begin(); }
beb_iterator beb_end() const { return Env.beb_end(); }
+
+ BasicValueFactory &getBasicVals() const;
+ SymbolManager &getSymbolManager() const;
+ GRTransferFuncs &getTransferFuncs() const;
+
+ //==---------------------------------------------------------------------==//
+ // Constraints on values.
+ //==---------------------------------------------------------------------==//
+ //
+ // Each GRState records constraints on symbolic values. These constraints
+ // are managed using the ConstraintManager associated with a GRStateManager.
+ // As constraints gradually accrue on symbolic values, added constraints
+ // may conflict and indicate that a state is infeasible (as no real values
+ // could satisfy all the constraints). This is the principal mechanism
+ // for modeling path-sensitivity in GRExprEngine/GRState.
+ //
+ // Various "Assume" methods form the interface for adding constraints to
+ // symbolic values. A call to "Assume" indicates an assumption being placed
+ // on one or symbolic values. Assume methods take the following inputs:
+ //
+ // (1) A GRState object representing the current state.
+ //
+ // (2) The assumed constraint (which is specific to a given "Assume" method).
+ //
+ // (3) A binary value "Assumption" that indicates whether the constraint is
+ // assumed to be true or false.
+ //
+ // The output of "Assume" are two values:
+ //
+ // (a) "isFeasible" is set to true or false to indicate whether or not
+ // the assumption is feasible.
+ //
+ // (b) A new GRState object with the added constraints.
+ //
+ // FIXME: (a) should probably disappear since it is redundant with (b).
+ // (i.e., (b) could just be set to NULL).
+ //
+
+ const GRState *assume(SVal condition, bool assumption) const;
+
+ const GRState *assumeInBound(SVal idx, SVal upperBound,
+ bool assumption) const;
+
+ //==---------------------------------------------------------------------==//
+ // Binding and retrieving values to/from the environment and symbolic store.
+ //==---------------------------------------------------------------------==//
+
+ /// BindCompoundLiteral - Return the state that has the bindings currently
+ /// in 'state' plus the bindings for the CompoundLiteral. 'R' is the region
+ /// for the compound literal and 'BegInit' and 'EndInit' represent an
+ /// array of initializer values.
+ const GRState* bindCompoundLiteral(const CompoundLiteralExpr* CL,
+ SVal V) const;
+
+ const GRState *bindExpr(const Stmt* Ex, SVal V, bool isBlkExpr,
+ bool Invalidate) const;
+
+ const GRState *bindExpr(const Stmt* Ex, SVal V, bool Invalidate = true) const;
+
+ const GRState *bindBlkExpr(const Stmt *Ex, SVal V) const {
+ return bindExpr(Ex, V, true, false);
+ }
+
+ const GRState *bindLoc(Loc location, SVal V) const;
+
+ const GRState *bindLoc(SVal location, SVal V) const;
+
+ const GRState *unbindLoc(Loc LV) const;
+
+ /// Get the lvalue for a variable reference.
+ SVal getLValue(const VarDecl *decl) const;
+
+ /// Get the lvalue for a StringLiteral.
+ SVal getLValue(const StringLiteral *literal) const;
+
+ SVal getLValue(const CompoundLiteralExpr *literal) const;
+
+ /// Get the lvalue for an ivar reference.
+ SVal getLValue(const ObjCIvarDecl *decl, SVal base) const;
+
+ /// Get the lvalue for a field reference.
+ SVal getLValue(SVal Base, const FieldDecl *decl) const;
+
+ /// Get the lvalue for an array index.
+ SVal getLValue(QualType ElementType, SVal Base, SVal Idx) const;
+
+ const llvm::APSInt *getSymVal(SymbolRef sym) const;
+
+ SVal getSVal(const Stmt* Ex) const;
+
+ SVal getBlkExprSVal(const Stmt* Ex) const;
+
+ SVal getSValAsScalarOrLoc(const Stmt *Ex) const;
+
+ SVal getSVal(Loc LV, QualType T = QualType()) const;
+
+ SVal getSVal(const MemRegion* R) const;
+
+ SVal getSValAsScalarOrLoc(const MemRegion *R) const;
+
+ bool scanReachableSymbols(SVal val, SymbolVisitor& visitor) const;
+
+ template <typename CB> CB scanReachableSymbols(SVal val) const;
+
+ //==---------------------------------------------------------------------==//
+ // Accessing the Generic Data Map (GDM).
+ //==---------------------------------------------------------------------==//
- // Trait based GDM dispatch.
void* const* FindGDM(void* K) const;
+ template<typename T>
+ const GRState *add(typename GRStateTrait<T>::key_type K) const;
+
template <typename T>
typename GRStateTrait<T>::data_type
get() const {
@@ -159,6 +281,29 @@ public:
return GRStateTrait<T>::Lookup(GRStateTrait<T>::MakeData(d), key);
}
+ template <typename T>
+ typename GRStateTrait<T>::context_type get_context() const;
+
+
+ template<typename T>
+ const GRState *remove(typename GRStateTrait<T>::key_type K) const;
+
+ template<typename T>
+ const GRState *remove(typename GRStateTrait<T>::key_type K,
+ typename GRStateTrait<T>::context_type C) const;
+
+ template<typename T>
+ const GRState *set(typename GRStateTrait<T>::data_type D) const;
+
+ template<typename T>
+ const GRState *set(typename GRStateTrait<T>::key_type K,
+ typename GRStateTrait<T>::value_type E) const;
+
+ template<typename T>
+ const GRState *set(typename GRStateTrait<T>::key_type K,
+ typename GRStateTrait<T>::value_type E,
+ typename GRStateTrait<T>::context_type C) const;
+
template<typename T>
bool contains(typename GRStateTrait<T>::key_type key) const {
void* const* d = FindGDM(GRStateTrait<T>::GDMIndex());
@@ -172,11 +317,14 @@ public:
virtual void Print(std::ostream& Out, const GRState* state,
const char* nl, const char* sep) = 0;
};
+
+ // Pretty-printing.
+ void print(std::ostream& Out, const char *nl = "\n",
+ const char *sep = "") const;
- void print(std::ostream& Out, StoreManager& StoreMgr,
- ConstraintManager& ConstraintMgr,
- Printer **Beg = 0, Printer **End = 0,
- const char* nl = "\n", const char *sep = "") const;
+ void printStdErr() const;
+
+ void printDOT(std::ostream& Out) const;
// Tags used for the Generic Data Map.
struct NullDerefTag {
@@ -233,11 +381,9 @@ public:
// GRStateManager - Factory object for GRStates.
//===----------------------------------------------------------------------===//
-class GRStateRef;
-
class GRStateManager {
friend class GRExprEngine;
- friend class GRStateRef;
+ friend class GRState;
private:
EnvironmentManager EnvMgr;
@@ -361,15 +507,6 @@ public:
// Store manager should return a persistent state.
return StoreMgr->BindDeclWithNoInit(St, VD);
}
-
- /// BindCompoundLiteral - Return the state that has the bindings currently
- /// in 'state' plus the bindings for the CompoundLiteral. 'R' is the region
- /// for the compound literal and 'BegInit' and 'EndInit' represent an
- /// array of initializer values.
- const GRState* BindCompoundLiteral(const GRState* St,
- const CompoundLiteralExpr* CL, SVal V) {
- return StoreMgr->BindCompoundLiteral(St, CL, V);
- }
const GRState* RemoveDeadBindings(const GRState* St, Stmt* Loc,
SymbolReaper& SymReaper);
@@ -391,38 +528,10 @@ public:
return StoreMgr->getSelfRegion(state->getStore());
}
- // Get the lvalue for a variable reference.
- SVal GetLValue(const GRState* St, const VarDecl* D) {
- return StoreMgr->getLValueVar(St, D);
- }
-
- // Get the lvalue for a StringLiteral.
- SVal GetLValue(const GRState* St, const StringLiteral* E) {
- return StoreMgr->getLValueString(St, E);
- }
-
- SVal GetLValue(const GRState* St, const CompoundLiteralExpr* CL) {
- return StoreMgr->getLValueCompoundLiteral(St, CL);
- }
-
- // Get the lvalue for an ivar reference.
- SVal GetLValue(const GRState* St, const ObjCIvarDecl* D, SVal Base) {
- return StoreMgr->getLValueIvar(St, D, Base);
- }
-
- // Get the lvalue for a field reference.
- SVal GetLValue(const GRState* St, SVal Base, const FieldDecl* D) {
- return StoreMgr->getLValueField(St, Base, D);
- }
-
- // Get the lvalue for an array index.
- SVal GetLValue(const GRState* St, QualType ElementType, SVal Base, SVal Idx) {
- return StoreMgr->getLValueElement(St, ElementType, Base, Idx);
- }
+private:
- // Methods that query & manipulate the Environment.
-
- SVal GetSVal(const GRState* St, Stmt* Ex) {
+ // Methods that query & manipulate the Environment.
+ SVal GetSVal(const GRState* St, const Stmt* Ex) {
return St->getEnvironment().GetSVal(Ex, getBasicVals());
}
@@ -435,19 +544,12 @@ public:
return UnknownVal();
}
-
- SVal GetSVal(const GRState* St, const Stmt* Ex) {
- return St->getEnvironment().GetSVal(const_cast<Stmt*>(Ex), getBasicVals());
- }
-
- SVal GetBlkExprSVal(const GRState* St, Stmt* Ex) {
+ SVal GetBlkExprSVal(const GRState* St, const Stmt* Ex) {
return St->getEnvironment().GetBlkExprSVal(Ex, getBasicVals());
}
-
-
- const GRState* BindExpr(const GRState* St, Stmt* Ex, SVal V,
+ const GRState* BindExpr(const GRState* St, const Stmt* Ex, SVal V,
bool isBlkExpr, bool Invalidate) {
const Environment& OldEnv = St->getEnvironment();
@@ -461,7 +563,7 @@ public:
return getPersistentState(NewSt);
}
- const GRState* BindExpr(const GRState* St, Stmt* Ex, SVal V,
+ const GRState* BindExpr(const GRState* St, const Stmt* Ex, SVal V,
bool Invalidate = true) {
bool isBlkExpr = false;
@@ -478,6 +580,8 @@ public:
return BindExpr(St, Ex, V, isBlkExpr, Invalidate);
}
+public:
+
SVal ArrayToPointer(Loc Array) {
return StoreMgr->ArrayToPointer(Array);
}
@@ -533,13 +637,9 @@ public:
const GRState* getPersistentState(GRState& Impl);
- // MakeStateWithStore - get a persistent state with the new store.
- const GRState* MakeStateWithStore(const GRState* St, Store store);
-
bool isEqual(const GRState* state, Expr* Ex, const llvm::APSInt& V);
bool isEqual(const GRState* state, Expr* Ex, uint64_t);
-
//==---------------------------------------------------------------------==//
// Generic Data Map methods.
//==---------------------------------------------------------------------==//
@@ -605,56 +705,6 @@ public:
return GRStateTrait<T>::MakeContext(p);
}
-
- //==---------------------------------------------------------------------==//
- // Constraints on values.
- //==---------------------------------------------------------------------==//
- //
- // Each GRState records constraints on symbolic values. These constraints
- // are managed using the ConstraintManager associated with a GRStateManager.
- // As constraints gradually accrue on symbolic values, added constraints
- // may conflict and indicate that a state is infeasible (as no real values
- // could satisfy all the constraints). This is the principal mechanism
- // for modeling path-sensitivity in GRExprEngine/GRState.
- //
- // Various "Assume" methods form the interface for adding constraints to
- // symbolic values. A call to "Assume" indicates an assumption being placed
- // on one or symbolic values. Assume methods take the following inputs:
- //
- // (1) A GRState object representing the current state.
- //
- // (2) The assumed constraint (which is specific to a given "Assume" method).
- //
- // (3) A binary value "Assumption" that indicates whether the constraint is
- // assumed to be true or false.
- //
- // The output of "Assume" are two values:
- //
- // (a) "isFeasible" is set to true or false to indicate whether or not
- // the assumption is feasible.
- //
- // (b) A new GRState object with the added constraints.
- //
- // FIXME: (a) should probably disappear since it is redundant with (b).
- // (i.e., (b) could just be set to NULL).
- //
-
- const GRState* Assume(const GRState* St, SVal Cond, bool Assumption,
- bool& isFeasible) {
- const GRState *state =
- ConstraintMgr->Assume(St, Cond, Assumption, isFeasible);
- assert(!isFeasible || state);
- return isFeasible ? state : NULL;
- }
-
- const GRState* AssumeInBound(const GRState* St, SVal Idx, SVal UpperBound,
- bool Assumption, bool& isFeasible) {
- const GRState *state =
- ConstraintMgr->AssumeInBound(St, Idx, UpperBound, Assumption,
- isFeasible);
- assert(!isFeasible || state);
- return isFeasible ? state : NULL;
- }
const llvm::APSInt* getSymVal(const GRState* St, SymbolRef sym) {
return ConstraintMgr->getSymVal(St, sym);
@@ -663,157 +713,158 @@ public:
void EndPath(const GRState* St) {
ConstraintMgr->EndPath(St);
}
-
- bool scanReachableSymbols(SVal val, const GRState* state,
- SymbolVisitor& visitor);
};
+
//===----------------------------------------------------------------------===//
-// GRStateRef - A "fat" reference to GRState that also bundles GRStateManager.
+// Out-of-line method definitions for GRState.
//===----------------------------------------------------------------------===//
-
-class GRStateRef {
- const GRState* St;
- GRStateManager* Mgr;
-public:
- GRStateRef(const GRState* st, GRStateManager& mgr) : St(st), Mgr(&mgr) {}
-
- const GRState* getState() const { return St; }
- operator const GRState*() const { return St; }
- GRStateManager& getManager() const { return *Mgr; }
-
- SVal GetSVal(Expr* Ex) {
- return Mgr->GetSVal(St, Ex);
- }
-
- SVal GetBlkExprSVal(Expr* Ex) {
- return Mgr->GetBlkExprSVal(St, Ex);
- }
-
- SVal GetSValAsScalarOrLoc(const Expr *Ex) {
- return Mgr->GetSValAsScalarOrLoc(St, Ex);
- }
-
- SVal GetSVal(Loc LV, QualType T = QualType()) {
- return Mgr->GetSVal(St, LV, T);
- }
-
- SVal GetSVal(const MemRegion* R) {
- return Mgr->GetSVal(St, R);
- }
-
- SVal GetSValAsScalarOrLoc(const MemRegion *R) {
- return Mgr->GetSValAsScalarOrLoc(St, R);
- }
-
- GRStateRef BindExpr(Stmt* Ex, SVal V, bool isBlkExpr, bool Invalidate) {
- return GRStateRef(Mgr->BindExpr(St, Ex, V, isBlkExpr, Invalidate), *Mgr);
- }
-
- GRStateRef BindExpr(Stmt* Ex, SVal V, bool Invalidate = true) {
- return GRStateRef(Mgr->BindExpr(St, Ex, V, Invalidate), *Mgr);
- }
-
- GRStateRef BindDecl(const VarDecl* VD, SVal InitVal) {
- return GRStateRef(Mgr->BindDecl(St, VD, InitVal), *Mgr);
- }
-
- GRStateRef BindLoc(Loc LV, SVal V) {
- return GRStateRef(Mgr->BindLoc(St, LV, V), *Mgr);
- }
-
- GRStateRef BindLoc(SVal LV, SVal V) {
- if (!isa<Loc>(LV)) return *this;
- return BindLoc(cast<Loc>(LV), V);
- }
-
- GRStateRef Unbind(Loc LV) {
- return GRStateRef(Mgr->Unbind(St, LV), *Mgr);
- }
-
- // Trait based GDM dispatch.
- template<typename T>
- typename GRStateTrait<T>::data_type get() const {
- return St->get<T>();
- }
-
- template<typename T>
- typename GRStateTrait<T>::lookup_type
- get(typename GRStateTrait<T>::key_type key) const {
- return St->get<T>(key);
- }
-
- template<typename T>
- GRStateRef set(typename GRStateTrait<T>::data_type D) {
- return GRStateRef(Mgr->set<T>(St, D), *Mgr);
- }
- template <typename T>
- typename GRStateTrait<T>::context_type get_context() {
- return Mgr->get_context<T>();
- }
-
- template<typename T>
- GRStateRef set(typename GRStateTrait<T>::key_type K,
- typename GRStateTrait<T>::value_type E,
- typename GRStateTrait<T>::context_type C) {
- return GRStateRef(Mgr->set<T>(St, K, E, C), *Mgr);
- }
-
- template<typename T>
- GRStateRef set(typename GRStateTrait<T>::key_type K,
- typename GRStateTrait<T>::value_type E) {
- return GRStateRef(Mgr->set<T>(St, K, E, get_context<T>()), *Mgr);
- }
-
- template<typename T>
- GRStateRef add(typename GRStateTrait<T>::key_type K) {
- return GRStateRef(Mgr->add<T>(St, K, get_context<T>()), *Mgr);
- }
-
- template<typename T>
- GRStateRef remove(typename GRStateTrait<T>::key_type K,
- typename GRStateTrait<T>::context_type C) {
- return GRStateRef(Mgr->remove<T>(St, K, C), *Mgr);
- }
-
- template<typename T>
- GRStateRef remove(typename GRStateTrait<T>::key_type K) {
- return GRStateRef(Mgr->remove<T>(St, K, get_context<T>()), *Mgr);
- }
-
- template<typename T>
- bool contains(typename GRStateTrait<T>::key_type key) const {
- return St->contains<T>(key);
- }
-
- // Lvalue methods.
- SVal GetLValue(const VarDecl* VD) {
- return Mgr->GetLValue(St, VD);
- }
-
- GRStateRef Assume(SVal Cond, bool Assumption, bool& isFeasible) {
- return GRStateRef(Mgr->Assume(St, Cond, Assumption, isFeasible), *Mgr);
- }
-
- template <typename CB>
- CB scanReachableSymbols(SVal val) {
- CB cb(*this);
- Mgr->scanReachableSymbols(val, St, cb);
- return cb;
- }
-
- SymbolManager& getSymbolManager() { return Mgr->getSymbolManager(); }
- BasicValueFactory& getBasicVals() { return Mgr->getBasicVals(); }
-
- // Pretty-printing.
- void print(std::ostream& Out, const char* nl = "\n",
- const char *sep = "") const;
-
- void printStdErr() const;
-
- void printDOT(std::ostream& Out) const;
-};
+inline const GRState *GRState::assume(SVal Cond, bool Assumption) const {
+ return Mgr->ConstraintMgr->Assume(this, Cond, Assumption);
+}
+
+inline const GRState *GRState::assumeInBound(SVal Idx, SVal UpperBound,
+ bool Assumption) const {
+ return Mgr->ConstraintMgr->AssumeInBound(this, Idx, UpperBound, Assumption);
+}
+
+inline const GRState *GRState::bindCompoundLiteral(const CompoundLiteralExpr* CL,
+ SVal V) const {
+ return Mgr->StoreMgr->BindCompoundLiteral(this, CL, V);
+}
+
+inline const GRState *GRState::bindExpr(const Stmt* Ex, SVal V, bool isBlkExpr,
+ bool Invalidate) const {
+ return Mgr->BindExpr(this, Ex, V, isBlkExpr, Invalidate);
+}
+
+inline const GRState *GRState::bindExpr(const Stmt* Ex, SVal V,
+ bool Invalidate) const {
+ return Mgr->BindExpr(this, Ex, V, Invalidate);
+}
+
+inline const GRState *GRState::bindLoc(Loc LV, SVal V) const {
+ return Mgr->BindLoc(this, LV, V);
+}
+
+inline const GRState *GRState::bindLoc(SVal LV, SVal V) const {
+ return !isa<Loc>(LV) ? this : bindLoc(cast<Loc>(LV), V);
+}
+
+inline SVal GRState::getLValue(const VarDecl* VD) const {
+ return Mgr->StoreMgr->getLValueVar(this, VD);
+}
+
+inline SVal GRState::getLValue(const StringLiteral *literal) const {
+ return Mgr->StoreMgr->getLValueString(this, literal);
+}
+
+inline SVal GRState::getLValue(const CompoundLiteralExpr *literal) const {
+ return Mgr->StoreMgr->getLValueCompoundLiteral(this, literal);
+}
+
+inline SVal GRState::getLValue(const ObjCIvarDecl *D, SVal Base) const {
+ return Mgr->StoreMgr->getLValueIvar(this, D, Base);
+}
+
+inline SVal GRState::getLValue(SVal Base, const FieldDecl* D) const {
+ return Mgr->StoreMgr->getLValueField(this, Base, D);
+}
+
+inline SVal GRState::getLValue(QualType ElementType, SVal Base, SVal Idx) const{
+ return Mgr->StoreMgr->getLValueElement(this, ElementType, Base, Idx);
+}
+
+inline const llvm::APSInt *GRState::getSymVal(SymbolRef sym) const {
+ return Mgr->getSymVal(this, sym);
+}
+
+inline SVal GRState::getSVal(const Stmt* Ex) const {
+ return Mgr->GetSVal(this, Ex);
+}
+
+inline SVal GRState::getBlkExprSVal(const Stmt* Ex) const {
+ return Mgr->GetBlkExprSVal(this, Ex);
+}
+
+inline SVal GRState::getSValAsScalarOrLoc(const Stmt *Ex) const {
+ return Mgr->GetSValAsScalarOrLoc(this, Ex);
+}
+
+inline SVal GRState::getSVal(Loc LV, QualType T) const {
+ return Mgr->GetSVal(this, LV, T);
+}
+
+inline SVal GRState::getSVal(const MemRegion* R) const {
+ return Mgr->GetSVal(this, R);
+}
+
+inline SVal GRState::getSValAsScalarOrLoc(const MemRegion *R) const {
+ return Mgr->GetSValAsScalarOrLoc(this, R);
+}
+
+inline BasicValueFactory &GRState::getBasicVals() const {
+ return Mgr->getBasicVals();
+}
+
+inline SymbolManager &GRState::getSymbolManager() const {
+ return Mgr->getSymbolManager();
+}
+
+inline GRTransferFuncs &GRState::getTransferFuncs() const {
+ return Mgr->getTransferFuncs();
+}
+
+template<typename T>
+const GRState *GRState::add(typename GRStateTrait<T>::key_type K) const {
+ return Mgr->add<T>(this, K, get_context<T>());
+}
+
+template <typename T>
+typename GRStateTrait<T>::context_type GRState::get_context() const {
+ return Mgr->get_context<T>();
+}
+
+template<typename T>
+const GRState *GRState::remove(typename GRStateTrait<T>::key_type K) const {
+ return Mgr->remove<T>(this, K, get_context<T>());
+}
+
+template<typename T>
+const GRState *GRState::remove(typename GRStateTrait<T>::key_type K,
+ typename GRStateTrait<T>::context_type C) const {
+ return Mgr->remove<T>(this, K, C);
+}
+
+template<typename T>
+const GRState *GRState::set(typename GRStateTrait<T>::data_type D) const {
+ return Mgr->set<T>(this, D);
+}
+
+template<typename T>
+const GRState *GRState::set(typename GRStateTrait<T>::key_type K,
+ typename GRStateTrait<T>::value_type E) const {
+ return Mgr->set<T>(this, K, E, get_context<T>());
+}
+
+template<typename T>
+const GRState *GRState::set(typename GRStateTrait<T>::key_type K,
+ typename GRStateTrait<T>::value_type E,
+ typename GRStateTrait<T>::context_type C) const {
+ return Mgr->set<T>(this, K, E, C);
+}
+
+template <typename CB>
+CB GRState::scanReachableSymbols(SVal val) const {
+ CB cb(this);
+ scanReachableSymbols(val, cb);
+ return cb;
+}
+
+inline const GRState *GRState::unbindLoc(Loc LV) const {
+ return Mgr->Unbind(this, LV);
+}
} // end clang namespace
diff --git a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h
index 0f353d07004f..c2f8f5aae0e9 100644
--- a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h
+++ b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h
@@ -110,11 +110,9 @@ public:
// Assumptions.
- virtual const GRState* EvalAssume(GRStateManager& VMgr,
- const GRState* St,
- SVal Cond, bool Assumption,
- bool& isFeasible) {
- return St;
+ virtual const GRState* EvalAssume(const GRState *state,
+ SVal Cond, bool Assumption) {
+ return state;
}
};
diff --git a/include/clang/Analysis/PathSensitive/MemRegion.h b/include/clang/Analysis/PathSensitive/MemRegion.h
index 0e8da2aee318..8afcc4c2414f 100644
--- a/include/clang/Analysis/PathSensitive/MemRegion.h
+++ b/include/clang/Analysis/PathSensitive/MemRegion.h
@@ -620,7 +620,7 @@ public:
/// getElementRegion - Retrieve the memory region associated with the
/// associated element type, index, and super region.
ElementRegion* getElementRegion(QualType elementType, SVal Idx,
- const MemRegion* superRegion);
+ const MemRegion* superRegion,ASTContext &Ctx);
/// getFieldRegion - Retrieve or create the memory region associated with
/// a specified FieldDecl. 'superRegion' corresponds to the containing
diff --git a/include/clang/Analysis/PathSensitive/SVals.h b/include/clang/Analysis/PathSensitive/SVals.h
index ee6d4dcf1f37..c9d1e25da789 100644
--- a/include/clang/Analysis/PathSensitive/SVals.h
+++ b/include/clang/Analysis/PathSensitive/SVals.h
@@ -181,7 +181,7 @@ public:
static NonLoc MakeVal(BasicValueFactory& BasicVals, uint64_t X, QualType T);
- static NonLoc MakeVal(BasicValueFactory& BasicVals, IntegerLiteral* I);
+ static NonLoc MakeVal(BasicValueFactory& BasicVals, const IntegerLiteral *I);
static NonLoc MakeVal(BasicValueFactory& BasicVals, const llvm::APInt& I,
bool isUnsigned);
@@ -212,7 +212,7 @@ public:
static Loc MakeVal(const MemRegion* R);
- static Loc MakeVal(AddrLabelExpr* E);
+ static Loc MakeVal(const AddrLabelExpr* E);
static Loc MakeNull(BasicValueFactory &BasicVals);
diff --git a/include/clang/Analysis/PathSensitive/Store.h b/include/clang/Analysis/PathSensitive/Store.h
index 1f081f4eb0d0..0c5df2e98e17 100644
--- a/include/clang/Analysis/PathSensitive/Store.h
+++ b/include/clang/Analysis/PathSensitive/Store.h
@@ -14,12 +14,12 @@
#ifndef LLVM_CLANG_ANALYSIS_STORE_H
#define LLVM_CLANG_ANALYSIS_STORE_H
-#include "clang/Analysis/PathSensitive/SVals.h"
#include "clang/Analysis/PathSensitive/MemRegion.h"
+#include "clang/Analysis/PathSensitive/SVals.h"
#include "clang/Analysis/PathSensitive/ValueManager.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
-#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallVector.h"
#include <iosfwd>
@@ -45,10 +45,10 @@ protected:
StoreManager(GRStateManager &stateMgr);
protected:
- virtual const GRState* AddRegionView(const GRState* St,
- const MemRegion* View,
- const MemRegion* Base) {
- return St;
+ virtual const GRState *AddRegionView(const GRState *state,
+ const MemRegion *view,
+ const MemRegion *base) {
+ return state;
}
public:
@@ -61,7 +61,7 @@ public:
/// expected type of the returned value. This is used if the value is
/// lazily computed.
/// \return The value bound to the location \c loc.
- virtual SVal Retrieve(const GRState* state, Loc loc,
+ virtual SVal Retrieve(const GRState *state, Loc loc,
QualType T = QualType()) = 0;
/// Return a state with the specified value bound to the given location.
@@ -71,7 +71,7 @@ public:
/// \return A pointer to a GRState object that contains the same bindings as
/// \c state with the addition of having the value specified by \c val bound
/// to the location given for \c loc.
- virtual const GRState* Bind(const GRState* state, Loc loc, SVal val) = 0;
+ virtual const GRState *Bind(const GRState *state, Loc loc, SVal val) = 0;
virtual Store Remove(Store St, Loc L) = 0;
@@ -79,9 +79,9 @@ public:
/// in 'store' plus the bindings for the CompoundLiteral. 'R' is the region
/// for the compound literal and 'BegInit' and 'EndInit' represent an
/// array of initializer values.
- virtual const GRState* BindCompoundLiteral(const GRState* St,
- const CompoundLiteralExpr* CL,
- SVal V) = 0;
+ virtual const GRState *BindCompoundLiteral(const GRState *state,
+ const CompoundLiteralExpr* cl,
+ SVal v) = 0;
/// getInitialStore - Returns the initial "empty" store representing the
/// value bindings upon entry to an analyzed function.
@@ -94,51 +94,52 @@ public:
/// getSubRegionMap - Returns an opaque map object that clients can query
/// to get the subregions of a given MemRegion object. It is the
// caller's responsibility to 'delete' the returned map.
- virtual SubRegionMap* getSubRegionMap(const GRState *state) = 0;
+ virtual SubRegionMap *getSubRegionMap(const GRState *state) = 0;
- virtual SVal getLValueVar(const GRState* St, const VarDecl* VD) = 0;
+ virtual SVal getLValueVar(const GRState *state, const VarDecl *vd) = 0;
- virtual SVal getLValueString(const GRState* St, const StringLiteral* S) = 0;
+ virtual SVal getLValueString(const GRState *state,
+ const StringLiteral* sl) = 0;
- virtual SVal getLValueCompoundLiteral(const GRState* St,
- const CompoundLiteralExpr* CL) = 0;
+ virtual SVal getLValueCompoundLiteral(const GRState *state,
+ const CompoundLiteralExpr* cl) = 0;
- virtual SVal getLValueIvar(const GRState* St, const ObjCIvarDecl* D,
- SVal Base) = 0;
+ virtual SVal getLValueIvar(const GRState *state, const ObjCIvarDecl* decl,
+ SVal base) = 0;
- virtual SVal getLValueField(const GRState* St, SVal Base,
+ virtual SVal getLValueField(const GRState *state, SVal base,
const FieldDecl* D) = 0;
- virtual SVal getLValueElement(const GRState* St, QualType elementType,
- SVal Base, SVal Offset) = 0;
+ virtual SVal getLValueElement(const GRState *state, QualType elementType,
+ SVal base, SVal offset) = 0;
- virtual SVal getSizeInElements(const GRState* St, const MemRegion* R) {
+ // FIXME: Make out-of-line.
+ virtual SVal getSizeInElements(const GRState *state, const MemRegion *region){
return UnknownVal();
}
/// ArrayToPointer - Used by GRExprEngine::VistCast to handle implicit
/// conversions between arrays and pointers.
virtual SVal ArrayToPointer(Loc Array) = 0;
-
class CastResult {
- const GRState* State;
- const MemRegion* R;
+ const GRState *state;
+ const MemRegion *region;
public:
- const GRState* getState() const { return State; }
- const MemRegion* getRegion() const { return R; }
- CastResult(const GRState* s, const MemRegion* r = 0) : State(s), R(r) {}
+ const GRState *getState() const { return state; }
+ const MemRegion* getRegion() const { return region; }
+ CastResult(const GRState *s, const MemRegion* r = 0) : state(s), region(r){}
};
/// CastRegion - Used by GRExprEngine::VisitCast to handle casts from
/// a MemRegion* to a specific location type. 'R' is the region being
/// casted and 'CastToTy' the result type of the cast.
- virtual CastResult CastRegion(const GRState* state, const MemRegion* R,
+ virtual CastResult CastRegion(const GRState *state, const MemRegion *region,
QualType CastToTy);
/// EvalBinOp - Perform pointer arithmetic.
- virtual SVal EvalBinOp(const GRState *state,
- BinaryOperator::Opcode Op, Loc L, NonLoc R) {
+ virtual SVal EvalBinOp(const GRState *state, BinaryOperator::Opcode Op,
+ Loc lhs, NonLoc rhs) {
return UnknownVal();
}
@@ -147,24 +148,27 @@ public:
/// method returns NULL.
virtual const MemRegion* getSelfRegion(Store store) = 0;
- virtual Store
- RemoveDeadBindings(const GRState* state, Stmt* Loc, SymbolReaper& SymReaper,
- llvm::SmallVectorImpl<const MemRegion*>& RegionRoots) = 0;
+ virtual Store RemoveDeadBindings(const GRState *state,
+ Stmt* Loc, SymbolReaper& SymReaper,
+ llvm::SmallVectorImpl<const MemRegion*>& RegionRoots) = 0;
- virtual const GRState* BindDecl(const GRState* St, const VarDecl* VD,
- SVal InitVal) = 0;
+ virtual const GRState *BindDecl(const GRState *state, const VarDecl *vd,
+ SVal initVal) = 0;
- virtual const GRState* BindDeclWithNoInit(const GRState* St,
- const VarDecl* VD) = 0;
+ virtual const GRState *BindDeclWithNoInit(const GRState *state,
+ const VarDecl *vd) = 0;
- virtual const GRState* setExtent(const GRState* St,
- const MemRegion* R, SVal Extent) {
- return St;
+ // FIXME: Make out-of-line.
+ virtual const GRState *setExtent(const GRState *state,
+ const MemRegion *region, SVal extent) {
+ return state;
}
- virtual const GRState* setDefaultValue(const GRState* St,
- const MemRegion* R, SVal V) {
- return St;
+ // FIXME: Make out-of-line.
+ virtual const GRState *setDefaultValue(const GRState *state,
+ const MemRegion *region,
+ SVal val) {
+ return state;
}
virtual void print(Store store, std::ostream& Out,
@@ -174,13 +178,14 @@ public:
public:
virtual ~BindingsHandler();
virtual bool HandleBinding(StoreManager& SMgr, Store store,
- const MemRegion* R, SVal val) = 0;
+ const MemRegion *region, SVal val) = 0;
};
/// iterBindings - Iterate over the bindings in the Store.
virtual void iterBindings(Store store, BindingsHandler& f) = 0;
};
+// FIXME: Do we still need this?
/// SubRegionMap - An abstract interface that represents a queryable map
/// between MemRegion objects and their subregions.
class SubRegionMap {
@@ -193,12 +198,14 @@ public:
virtual bool Visit(const MemRegion* Parent, const MemRegion* SubRegion) = 0;
};
- virtual bool iterSubRegions(const MemRegion* R, Visitor& V) const = 0;
+ virtual bool iterSubRegions(const MemRegion *region, Visitor& V) const = 0;
};
-
-StoreManager* CreateBasicStoreManager(GRStateManager& StMgr);
-StoreManager* CreateRegionStoreManager(GRStateManager& StMgr);
-
+
+// FIXME: Do we need to pass GRStateManager anymore?
+StoreManager *CreateBasicStoreManager(GRStateManager& StMgr);
+StoreManager *CreateRegionStoreManager(GRStateManager& StMgr);
+StoreManager *CreateFieldsOnlyRegionStoreManager(GRStateManager& StMgr);
+
} // end clang namespace
#endif
diff --git a/include/clang/Analysis/PathSensitive/SymbolManager.h b/include/clang/Analysis/PathSensitive/SymbolManager.h
index d424526d4eb0..d074e30333d4 100644
--- a/include/clang/Analysis/PathSensitive/SymbolManager.h
+++ b/include/clang/Analysis/PathSensitive/SymbolManager.h
@@ -83,19 +83,25 @@ typedef const SymbolData* SymbolRef;
class SymbolRegionValue : public SymbolData {
const MemRegion *R;
+ // We may cast the region to another type, so the expected type of the symbol
+ // may be different from the region's original type.
+ QualType T;
+
public:
- SymbolRegionValue(SymbolID sym, const MemRegion *r)
- : SymbolData(RegionValueKind, sym), R(r) {}
+ SymbolRegionValue(SymbolID sym, const MemRegion *r, QualType t = QualType())
+ : SymbolData(RegionValueKind, sym), R(r), T(t) {}
const MemRegion* getRegion() const { return R; }
- static void Profile(llvm::FoldingSetNodeID& profile, const MemRegion* R) {
+ static void Profile(llvm::FoldingSetNodeID& profile, const MemRegion* R,
+ QualType T) {
profile.AddInteger((unsigned) RegionValueKind);
profile.AddPointer(R);
+ T.Profile(profile);
}
virtual void Profile(llvm::FoldingSetNodeID& profile) {
- Profile(profile, R);
+ Profile(profile, R, T);
}
QualType getType(ASTContext&) const;
@@ -240,7 +246,8 @@ public:
static bool canSymbolicate(QualType T);
/// Make a unique symbol for MemRegion R according to its kind.
- const SymbolRegionValue* getRegionValueSymbol(const MemRegion* R);
+ const SymbolRegionValue* getRegionValueSymbol(const MemRegion* R,
+ QualType T = QualType());
const SymbolConjured* getConjuredSymbol(const Stmt* E, QualType T,
unsigned VisitCount,
const void* SymbolTag = 0);
diff --git a/include/clang/Analysis/PathSensitive/ValueManager.h b/include/clang/Analysis/PathSensitive/ValueManager.h
index 89af975de7af..b86f4e875304 100644
--- a/include/clang/Analysis/PathSensitive/ValueManager.h
+++ b/include/clang/Analysis/PathSensitive/ValueManager.h
@@ -81,7 +81,7 @@ public:
SVal makeZeroArrayIndex();
/// GetRegionValueSymbolVal - make a unique symbol for value of R.
- SVal getRegionValueSymbolVal(const MemRegion* R);
+ SVal getRegionValueSymbolVal(const MemRegion* R, QualType T = QualType());
SVal getConjuredSymbolVal(const Expr *E, unsigned Count);
SVal getConjuredSymbolVal(const Expr* E, QualType T, unsigned Count);
diff --git a/include/clang/Basic/Builtins.h b/include/clang/Basic/Builtins.h
index 6463a4f6e51b..f770c5089eec 100644
--- a/include/clang/Basic/Builtins.h
+++ b/include/clang/Basic/Builtins.h
@@ -53,13 +53,12 @@ class Context {
const Info *TSRecords;
unsigned NumTSRecords;
public:
- Context() : TSRecords(0), NumTSRecords(0) {}
+ Context(const TargetInfo &Target);
/// InitializeBuiltins - Mark the identifiers for all the builtins with their
/// appropriate builtin ID # and mark any non-portable builtin identifiers as
/// such.
- void InitializeBuiltins(IdentifierTable &Table, const TargetInfo &Target,
- bool NoBuiltins = false);
+ void InitializeBuiltins(IdentifierTable &Table, bool NoBuiltins = false);
/// \brief Popular the vector with the names of all of the builtins.
void GetBuiltinNames(llvm::SmallVectorImpl<const char *> &Names,
diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index 501807df77a3..2896f7988c01 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -30,6 +30,7 @@ def : DiagGroup<"conversion">;
def : DiagGroup<"declaration-after-statement">;
def : DiagGroup<"disabled-optimization">;
def : DiagGroup<"discard-qual">;
+def : DiagGroup<"div-by-zero">;
def EmptyBody : DiagGroup<"empty-body">;
def ExtraTokens : DiagGroup<"extra-tokens">;
@@ -40,6 +41,7 @@ def FourByteMultiChar : DiagGroup<"four-char-constants">;
def : DiagGroup<"init-self">;
def : DiagGroup<"inline">;
def : DiagGroup<"int-to-pointer-cast">;
+def : DiagGroup<"invalid-pch">;
def : DiagGroup<"missing-braces">;
def : DiagGroup<"missing-declarations">;
def : DiagGroup<"missing-format-attribute">;
@@ -91,6 +93,8 @@ def UnusedLabel : DiagGroup<"unused-label">;
def UnusedParameter : DiagGroup<"unused-parameter">;
def UnusedValue : DiagGroup<"unused-value">;
def UnusedVariable : DiagGroup<"unused-variable">;
+def ReadOnlySetterAttrs : DiagGroup<"readonly-setter-attrs">;
+def UndeclaredSelector : DiagGroup<"undeclared-selector">;
def : DiagGroup<"variadic-macros">;
def VectorConversions : DiagGroup<"vector-conversions">; // clang specific
def VolatileRegisterVar : DiagGroup<"volatile-register-var">;
@@ -112,7 +116,9 @@ def Format2 : DiagGroup<"format=2",
[FormatNonLiteral, FormatSecurity, FormatY2K]>;
-def Extra : DiagGroup<"extra">;
+def Extra : DiagGroup<"extra", [
+ UnusedParameter
+ ]>;
def Most : DiagGroup<"most", [
Comment,
@@ -127,7 +133,9 @@ def Most : DiagGroup<"most", [
UnusedValue,
UnusedVariable,
VectorConversions,
- VolatileRegisterVar
+ VolatileRegisterVar,
+ ReadOnlySetterAttrs,
+ UndeclaredSelector
]>;
// -Wall is -Wmost -Wparentheses
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index e2b9eb7a20b8..d65a97eb7067 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -108,6 +108,8 @@ def err_expected_semi_after_method_proto : Error<
"expected ';' after method prototype">;
def err_expected_semi_after_namespace_name : Error<
"expected ';' after namespace name">;
+def err_unexpected_namespace_attributes_alias : Error<
+ "attributes can not be specified on namespace alias">;
def err_expected_semi_after_attribute_list : Error<
"expected ';' after attribute list">;
def err_expected_semi_after_static_assert : Error<
@@ -152,6 +154,10 @@ def err_unknown_typename : Error<
"unknown type name %0">;
def err_use_of_tag_name_without_tag : Error<
"use of tagged type %0 without '%1' tag">;
+def err_expected_ident_in_using : Error<
+ "expected an identifier in using directive">;
+def err_unexpected_template_spec_in_using : Error<
+ "use of template specialization in using directive not allowed">;
/// Objective-C parser diagnostics
@@ -212,6 +218,8 @@ def ext_ellipsis_exception_spec : Extension<
"exception specification of '...' is a Microsoft extension">;
def err_expected_catch : Error<"expected catch">;
def err_expected_lbrace_or_comma : Error<"expected '{' or ','">;
+def err_using_namespace_in_class : Error<
+ "'using namespace' in class not allowed">;
// C++ derived classes
def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">;
@@ -287,5 +295,5 @@ def warn_pragma_unused_expected_var : Warning<
"expected '#pragma unused' argument to be a variable name">;
def warn_pragma_unused_expected_punc : Warning<
"expected ')' or ',' in '#pragma unused'">;
-
+
} // end of Parser diagnostics
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index fa4f430591b2..755cfce4d85b 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -72,6 +72,8 @@ def ext_anon_param_requires_type_specifier : Extension<
def err_bad_variable_name : Error<
"'%0' cannot be the name of a variable or data member">;
def err_parameter_name_omitted : Error<"parameter name omitted">;
+def warn_unused_parameter : Warning<"unused parameter %0">,
+ InGroup<UnusedParameter>, DefaultIgnore;
def warn_decl_in_param_list : Warning<
"declaration of %0 will not be visible outside of this function">;
@@ -90,6 +92,10 @@ def warn_use_out_of_scope_declaration : Warning<
"use of out-of-scope declaration of %0">;
def err_inline_non_function : Error<
"'inline' can only appear on functions">;
+def err_using_requires_qualname : Error<
+ "using declaration requires a qualified name">;
+def err_using_typename_non_type : Error<
+ "'typename' keyword used on a non-type">;
def err_invalid_thread : Error<
"'__thread' is only allowed on variable declarations">;
@@ -240,7 +246,9 @@ def error_duplicate_ivar_use : Error<
def error_property_implemented : Error<"property %0 is already implemented">;
def warn_objc_property_attr_mutually_exclusive : Warning<
"property attributes '%0' and '%1' are mutually exclusive">,
- InGroup<DiagGroup<"readonly-setter-attrs">>, DefaultIgnore;
+ InGroup<ReadOnlySetterAttrs>, DefaultIgnore;
+def warn_undeclared_selector : Warning<
+ "undeclared selector %0">, InGroup<UndeclaredSelector>, DefaultIgnore;
// C++ declarations
def err_static_assert_expression_is_not_constant : Error<
@@ -571,6 +579,14 @@ def err_param_default_argument_references_this : Error<
def err_param_default_argument_nonfunc : Error<
"default arguments can only be specified for parameters in a function "
"declaration">;
+def err_defining_default_ctor : Error<
+ "cannot define the default constructor for %0, because %select{base class|member}1 "
+ "%2 does not have any implicit default constructor">;
+def note_previous_class_decl : Note<
+ "%0 declared here">;
+def err_unintialized_member : Error<
+ "cannot define the implicit default constructor for %0, because "
+ "%select{reference|const}1 member %2 cannot be default-initialized">;
def err_use_of_default_argument_to_function_declared_later : Error<
"use of default argument to function %0 that is declared later in class %1">;
diff --git a/include/clang/Basic/SourceLocation.h b/include/clang/Basic/SourceLocation.h
index 2405c2fe7db7..7d78087d9db5 100644
--- a/include/clang/Basic/SourceLocation.h
+++ b/include/clang/Basic/SourceLocation.h
@@ -145,6 +145,10 @@ inline bool operator<(const SourceLocation &LHS, const SourceLocation &RHS) {
return LHS.getRawEncoding() < RHS.getRawEncoding();
}
+inline bool operator<=(const SourceLocation &LHS, const SourceLocation &RHS) {
+ return LHS.getRawEncoding() <= RHS.getRawEncoding();
+}
+
/// SourceRange - a trival tuple used to represent a source range.
class SourceRange {
SourceLocation B;
diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h
index 57ae9a45114d..bcfb83b8942c 100644
--- a/include/clang/Basic/SourceManager.h
+++ b/include/clang/Basic/SourceManager.h
@@ -68,7 +68,12 @@ namespace SrcMgr {
/// NumLines - The number of lines in this ContentCache. This is only valid
/// if SourceLineCache is non-null.
unsigned NumLines;
-
+
+ /// FirstFID - First FileID that was created for this ContentCache.
+ /// Represents the first source inclusion of the file associated with this
+ /// ContentCache.
+ mutable FileID FirstFID;
+
/// getBuffer - Returns the memory buffer for the associated content.
const llvm::MemoryBuffer *getBuffer() const;
@@ -624,6 +629,13 @@ public:
//===--------------------------------------------------------------------===//
// Other miscellaneous methods.
//===--------------------------------------------------------------------===//
+
+ /// \brief Get the source location for the given file:line:col triplet.
+ ///
+ /// If the source file is included multiple times, the source location will
+ /// be based upon the first inclusion.
+ SourceLocation getLocation(const FileEntry *SourceFile,
+ unsigned Line, unsigned Col) const;
// Iterators over FileInfos.
typedef llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*>
diff --git a/include/clang/Driver/Options.def b/include/clang/Driver/Options.def
index 7045f145ee51..abd07a92b1a2 100644
--- a/include/clang/Driver/Options.def
+++ b/include/clang/Driver/Options.def
@@ -565,9 +565,9 @@ OPTION("-print-file-name=", print_file_name_EQ, Joined, INVALID, INVALID, "", 0,
OPTION("-print-ivar-layout", print_ivar_layout, Flag, INVALID, INVALID, "", 0, 0, 0)
OPTION("-print-libgcc-file-name", print_libgcc_file_name, Flag, INVALID, INVALID, "", 0,
"Print the library path for \"libgcc.a\"", 0)
-OPTION("-print-multi-directory", print_multi_directory, Flag, INVALID, INVALID, "u", 0, 0, 0)
-OPTION("-print-multi-lib", print_multi_lib, Flag, INVALID, INVALID, "u", 0, 0, 0)
-OPTION("-print-multi-os-directory", print_multi_os_directory, Flag, INVALID, INVALID, "u", 0, 0, 0)
+OPTION("-print-multi-directory", print_multi_directory, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-print-multi-lib", print_multi_lib, Flag, INVALID, INVALID, "", 0, 0, 0)
+OPTION("-print-multi-os-directory", print_multi_os_directory, Flag, INVALID, INVALID, "", 0, 0, 0)
OPTION("-print-prog-name=", print_prog_name_EQ, Joined, INVALID, INVALID, "", 0,
"Print the full program path of <name>", "<name>")
OPTION("-print-search-dirs", print_search_dirs, Flag, INVALID, INVALID, "", 0,
diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h
index 6196c130266d..c9d0ef197dae 100644
--- a/include/clang/Driver/ToolChain.h
+++ b/include/clang/Driver/ToolChain.h
@@ -50,6 +50,8 @@ public:
// Accessors
const HostInfo &getHost() const { return Host; }
+ const llvm::Triple &getTriple() const { return Triple; }
+
std::string getArchName() const { return Triple.getArchName(); }
std::string getPlatform() const { return Triple.getVendorName(); }
std::string getOS() const { return Triple.getOSName(); }
diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h
new file mode 100644
index 000000000000..68c06f5dcee6
--- /dev/null
+++ b/include/clang/Frontend/ASTUnit.h
@@ -0,0 +1,75 @@
+//===--- ASTUnit.h - ASTUnit utility ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// ASTUnit utility class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_ASTUNIT_H
+#define LLVM_CLANG_FRONTEND_ASTUNIT_H
+
+#include "llvm/ADT/OwningPtr.h"
+#include <string>
+
+namespace clang {
+ class FileManager;
+ class FileEntry;
+ class SourceManager;
+ class DiagnosticClient;
+ class Diagnostic;
+ class HeaderSearch;
+ class TargetInfo;
+ class Preprocessor;
+ class ASTContext;
+ class Decl;
+
+/// \brief Utility class for loading a ASTContext from a PCH file.
+///
+class ASTUnit {
+ llvm::OwningPtr<SourceManager> SourceMgr;
+ llvm::OwningPtr<DiagnosticClient> DiagClient;
+ llvm::OwningPtr<Diagnostic> Diags;
+ llvm::OwningPtr<HeaderSearch> HeaderInfo;
+ llvm::OwningPtr<TargetInfo> Target;
+ llvm::OwningPtr<Preprocessor> PP;
+ llvm::OwningPtr<ASTContext> Ctx;
+
+ ASTUnit(const ASTUnit&); // do not implement
+ ASTUnit &operator=(const ASTUnit &); // do not implement
+ ASTUnit();
+
+public:
+ ~ASTUnit();
+
+ const SourceManager &getSourceManager() const { return *SourceMgr.get(); }
+ SourceManager &getSourceManager() { return *SourceMgr.get(); }
+
+ const Preprocessor &getPreprocessor() const { return *PP.get(); }
+ Preprocessor &getPreprocessor() { return *PP.get(); }
+
+ const ASTContext &getASTContext() const { return *Ctx.get(); }
+ ASTContext &getASTContext() { return *Ctx.get(); }
+
+ /// \brief Create a ASTUnit from a PCH file.
+ ///
+ /// \param Filename PCH filename
+ ///
+ /// \param FileMgr The FileManager to use
+ ///
+ /// \param ErrMsg Error message to report if the PCH file could not be loaded
+ ///
+ /// \returns the initialized ASTUnit or NULL if the PCH failed to load
+ static ASTUnit *LoadFromPCHFile(const std::string &Filename,
+ FileManager &FileMgr,
+ std::string *ErrMsg = 0);
+};
+
+} // namespace clang
+
+#endif
diff --git a/include/clang/Frontend/DeclContextXML.def b/include/clang/Frontend/DeclContextXML.def
new file mode 100644
index 000000000000..39ed5f9432b6
--- /dev/null
+++ b/include/clang/Frontend/DeclContextXML.def
@@ -0,0 +1,113 @@
+//===-- DeclContextXML.def - Metadata about Context XML nodes ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the XML context info database as written in the
+// <ReferenceSection>/<Contexts> sub-nodes of the XML document. Type nodes
+// are referred by "context" reference attributes throughout the document.
+// A context node never contains sub-nodes.
+// The semantics of the attributes and enums are mostly self-documenting
+// by looking at the appropriate internally used functions and values.
+// The following macros are used:
+//
+// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete
+// context of class CLASS where CLASS is a class name used internally by clang.
+// After a NODE_XML the definition of all (optional) attributes of that context
+// node and possible sub-nodes follows.
+//
+// END_NODE_XML - Closes the attribute definition of the current node.
+//
+// ID_ATTRIBUTE_XML - Context nodes have an "id" attribute containing a
+// string, which value uniquely identify that statement. Other nodes may refer
+// by "context" attributes to this value.
+//
+// TYPE_ATTRIBUTE_XML( FN ) - Context nodes may refer to the ids of type
+// nodes by a "type" attribute, if they create a type during declaration.
+// For instance 'struct S;' creates both a context 'S::' and a type 'S'.
+// Contexts and types always have different ids, however declarations and
+// contexts may share the same ids. FN is internally used by clang.
+//
+// ATTRIBUTE_XML( FN, NAME ) - An attribute named NAME. FN is internally
+// used by clang. A boolean attribute have the values "0" or "1".
+//
+// ATTRIBUTE_ENUM[_OPT]_XML( FN, NAME ) - An attribute named NAME. The value
+// is an enumeration defined with ENUM_XML macros immediately following after
+// that macro. An optional attribute is ommited, if the particular enum is the
+// empty string. FN is internally used by clang.
+//
+// ENUM_XML( VALUE, NAME ) - An enumeration element named NAME. VALUE is
+// internally used by clang.
+//
+// END_ENUM_XML - Closes the enumeration definition of the current attribute.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TYPE_ATTRIBUTE_XML
+# define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type")
+#endif
+
+#ifndef CONTEXT_ATTRIBUTE_XML
+# define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context")
+#endif
+
+NODE_XML(TranslationUnitDecl, "TranslationUnit")
+ ID_ATTRIBUTE_XML
+END_NODE_XML
+
+NODE_XML(FunctionDecl, "Function")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+ TYPE_ATTRIBUTE_XML(getType()->getAsFunctionType())
+END_NODE_XML
+
+NODE_XML(NamespaceDecl, "Namespace")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+END_NODE_XML
+
+NODE_XML(RecordDecl, "Record")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+ TYPE_ATTRIBUTE_XML(getTypeForDecl())
+END_NODE_XML
+
+NODE_XML(EnumDecl, "Enum")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+ TYPE_ATTRIBUTE_XML(getTypeForDecl())
+END_NODE_XML
+
+NODE_XML(LinkageSpecDecl, "LinkageSpec")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_ENUM_OPT_XML(getLanguage(), "lang")
+ ENUM_XML(LinkageSpecDecl::lang_c, "C")
+ ENUM_XML(LinkageSpecDecl::lang_cxx, "CXX")
+ END_ENUM_XML
+END_NODE_XML
+
+//===----------------------------------------------------------------------===//
+#undef NODE_XML
+#undef ID_ATTRIBUTE_XML
+#undef TYPE_ATTRIBUTE_XML
+#undef ATTRIBUTE_XML
+#undef ATTRIBUTE_SPECIAL_XML
+#undef ATTRIBUTE_OPT_XML
+#undef ATTRIBUTE_ENUM_XML
+#undef ATTRIBUTE_ENUM_OPT_XML
+#undef ATTRIBUTE_FILE_LOCATION_XML
+#undef ENUM_XML
+#undef END_ENUM_XML
+#undef END_NODE_XML
+#undef SUB_NODE_XML
+#undef SUB_NODE_SEQUENCE_XML
+#undef SUB_NODE_OPT_XML
diff --git a/include/clang/Frontend/DeclXML.def b/include/clang/Frontend/DeclXML.def
new file mode 100644
index 000000000000..956d9719f9f4
--- /dev/null
+++ b/include/clang/Frontend/DeclXML.def
@@ -0,0 +1,250 @@
+//===-- DeclXML.def - Metadata about Decl XML nodes ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the XML statement database structure as written in
+// <TranslationUnit> sub-nodes of the XML document.
+// The semantics of the attributes and enums are mostly self-documenting
+// by looking at the appropriate internally used functions and values.
+// The following macros are used:
+//
+// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete
+// statement of class CLASS where CLASS is a class name used internally by clang.
+// After a NODE_XML the definition of all (optional) attributes of that statement
+// node and possible sub-nodes follows.
+//
+// END_NODE_XML - Closes the attribute definition of the current node.
+//
+// ID_ATTRIBUTE_XML - Some statement nodes have an "id" attribute containing a
+// string, which value uniquely identify that statement. Other nodes may refer
+// by reference attributes to this value (currently used only for Label).
+//
+// TYPE_ATTRIBUTE_XML( FN ) - Type nodes refer to the result type id of an
+// expression by a "type" attribute. FN is internally used by clang.
+//
+// ATTRIBUTE_XML( FN, NAME ) - An attribute named NAME. FN is internally
+// used by clang. A boolean attribute have the values "0" or "1".
+//
+// ATTRIBUTE_SPECIAL_XML( FN, NAME ) - An attribute named NAME which deserves
+// a special handling. See the appropriate documentations.
+//
+// ATTRIBUTE_FILE_LOCATION_XML - A bunch of attributes denoting the location of
+// a statement in the source file(s).
+//
+// ATTRIBUTE_OPT_XML( FN, NAME ) - An optional attribute named NAME.
+// Optional attributes are omitted for boolean types, if the value is false,
+// for integral types, if the value is null and for strings,
+// if the value is the empty string. FN is internally used by clang.
+//
+// ATTRIBUTE_ENUM[_OPT]_XML( FN, NAME ) - An attribute named NAME. The value
+// is an enumeration defined with ENUM_XML macros immediately following after
+// that macro. An optional attribute is ommited, if the particular enum is the
+// empty string. FN is internally used by clang.
+//
+// ENUM_XML( VALUE, NAME ) - An enumeration element named NAME. VALUE is
+// internally used by clang.
+//
+// END_ENUM_XML - Closes the enumeration definition of the current attribute.
+//
+// SUB_NODE_XML( CLASS ) - A mandatory sub-node of class CLASS or its sub-classes.
+//
+// SUB_NODE_OPT_XML( CLASS ) - An optional sub-node of class CLASS or its sub-classes.
+//
+// SUB_NODE_SEQUENCE_XML( CLASS ) - Zero or more sub-nodes of class CLASS or
+// its sub-classes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef ATTRIBUTE_FILE_LOCATION_XML
+# define ATTRIBUTE_FILE_LOCATION_XML \
+ ATTRIBUTE_XML(getFilename(), "file") \
+ ATTRIBUTE_XML(getLine(), "line") \
+ ATTRIBUTE_XML(getColumn(), "col") \
+ ATTRIBUTE_OPT_XML(getFilename(), "endfile") \
+ ATTRIBUTE_OPT_XML(getLine(), "endline") \
+ ATTRIBUTE_OPT_XML(getColumn(), "endcol")
+#endif
+
+#ifndef TYPE_ATTRIBUTE_XML
+# define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type")
+#endif
+
+#ifndef CONTEXT_ATTRIBUTE_XML
+# define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context")
+#endif
+
+//NODE_XML(TranslationUnitDecl, "TranslationUnit")
+// SUB_NODE_SEQUENCE_XML(Decl)
+//END_NODE_XML
+
+NODE_XML(Decl, "FIXME_Decl")
+ ATTRIBUTE_FILE_LOCATION_XML
+END_NODE_XML
+
+NODE_XML(FunctionDecl, "Function")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+ TYPE_ATTRIBUTE_XML(getType()->getAsFunctionType()->getResultType())
+ ATTRIBUTE_XML(getType()->getAsFunctionType(), "function_type")
+ ATTRIBUTE_ENUM_OPT_XML(getStorageClass(), "storage_class")
+ ENUM_XML(FunctionDecl::None, "")
+ ENUM_XML(FunctionDecl::Extern, "extern")
+ ENUM_XML(FunctionDecl::Static, "static")
+ ENUM_XML(FunctionDecl::PrivateExtern, "__private_extern__")
+ END_ENUM_XML
+ ATTRIBUTE_OPT_XML(isInline(), "inline")
+ //ATTRIBUTE_OPT_XML(isVariadic(), "variadic") // in the type reference
+ ATTRIBUTE_XML(getNumParams(), "num_args")
+ SUB_NODE_SEQUENCE_XML(ParmVarDecl)
+ //SUB_NODE_OPT_XML("Body")
+END_NODE_XML
+
+NODE_XML(CXXMethodDecl, "CXXMethodDecl")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+ TYPE_ATTRIBUTE_XML(getType()->getAsFunctionType()->getResultType())
+ ATTRIBUTE_XML(getType()->getAsFunctionType(), "function_type")
+ ATTRIBUTE_OPT_XML(isInline(), "inline")
+ ATTRIBUTE_OPT_XML(isStatic(), "static")
+ ATTRIBUTE_OPT_XML(isVirtual(), "virtual")
+ ATTRIBUTE_XML(getNumParams(), "num_args")
+ SUB_NODE_SEQUENCE_XML(ParmVarDecl)
+ //SUB_NODE_OPT_XML("Body")
+END_NODE_XML
+
+//NODE_XML("Body")
+// SUB_NODE_XML(Stmt)
+//END_NODE_XML
+
+NODE_XML(NamespaceDecl, "Namespace")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+END_NODE_XML
+
+NODE_XML(UsingDirectiveDecl, "UsingDirective")
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+ ATTRIBUTE_XML(getNominatedNamespace(), "ref")
+END_NODE_XML
+
+NODE_XML(NamespaceAliasDecl, "NamespaceAlias")
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+ ATTRIBUTE_XML(getNamespace(), "ref")
+END_NODE_XML
+
+NODE_XML(RecordDecl, "Record")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+ ATTRIBUTE_OPT_XML(isDefinition() == false, "forward")
+ ATTRIBUTE_XML(getTypeForDecl(), "type") // refers to the type this decl creates
+ SUB_NODE_SEQUENCE_XML(FieldDecl)
+END_NODE_XML
+
+NODE_XML(EnumDecl, "Enum")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+ ATTRIBUTE_OPT_XML(isDefinition() == false, "forward")
+ ATTRIBUTE_SPECIAL_XML(getIntegerType(), "type") // is NULL in pure declarations thus deserves special handling
+ SUB_NODE_SEQUENCE_XML(EnumConstantDecl) // only present in definition
+END_NODE_XML
+
+NODE_XML(EnumConstantDecl, "EnumConstant")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_XML(getInitVal().toString(10, true), "value") // integer
+ SUB_NODE_OPT_XML(Expr) // init expr of this constant
+END_NODE_XML
+
+NODE_XML(FieldDecl, "Field")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_OPT_XML(isMutable(), "mutable")
+ ATTRIBUTE_OPT_XML(isBitField(), "bitfield")
+ SUB_NODE_OPT_XML(Expr) // init expr of a bit field
+END_NODE_XML
+
+NODE_XML(TypedefDecl, "Typedef")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+ TYPE_ATTRIBUTE_XML(getUnderlyingType())
+END_NODE_XML
+
+NODE_XML(VarDecl, "Var")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_ENUM_OPT_XML(getStorageClass(), "storage_class")
+ ENUM_XML(VarDecl::None, "")
+ ENUM_XML(VarDecl::Auto, "auto")
+ ENUM_XML(VarDecl::Register, "register")
+ ENUM_XML(VarDecl::Extern, "extern")
+ ENUM_XML(VarDecl::Static, "static")
+ ENUM_XML(VarDecl::PrivateExtern, "__private_extern__")
+ END_ENUM_XML
+ SUB_NODE_OPT_XML(Expr) // init expr
+END_NODE_XML
+
+NODE_XML(ParmVarDecl, "ParmVar")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_XML(getNameAsString(), "name")
+ TYPE_ATTRIBUTE_XML(getType())
+ SUB_NODE_OPT_XML(Expr) // default argument expression
+END_NODE_XML
+
+NODE_XML(LinkageSpecDecl, "LinkageSpec")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getDeclContext(), "context")
+ ATTRIBUTE_ENUM_OPT_XML(getLanguage(), "lang")
+ ENUM_XML(LinkageSpecDecl::lang_c, "C")
+ ENUM_XML(LinkageSpecDecl::lang_cxx, "CXX")
+ END_ENUM_XML
+END_NODE_XML
+
+
+//===----------------------------------------------------------------------===//
+#undef NODE_XML
+#undef ID_ATTRIBUTE_XML
+#undef TYPE_ATTRIBUTE_XML
+#undef ATTRIBUTE_XML
+#undef ATTRIBUTE_SPECIAL_XML
+#undef ATTRIBUTE_OPT_XML
+#undef ATTRIBUTE_ENUM_XML
+#undef ATTRIBUTE_ENUM_OPT_XML
+#undef ATTRIBUTE_FILE_LOCATION_XML
+#undef ENUM_XML
+#undef END_ENUM_XML
+#undef END_NODE_XML
+#undef SUB_NODE_XML
+#undef SUB_NODE_SEQUENCE_XML
+#undef SUB_NODE_OPT_XML
diff --git a/include/clang/Frontend/DocumentXML.def b/include/clang/Frontend/DocumentXML.def
new file mode 100644
index 000000000000..4c52bd84422f
--- /dev/null
+++ b/include/clang/Frontend/DocumentXML.def
@@ -0,0 +1,75 @@
+//===-- DocumentXML.def - Metadata about Document XML nodes -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the XML root database structure as written in
+// an AST XML document.
+// The following macros are used:
+//
+// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete
+// statement of class CLASS where CLASS is a class name used internally by clang.
+// After a NODE_XML the definition of all (optional) attributes of that statement
+// node and possible sub-nodes follows.
+//
+// END_NODE_XML - Closes the attribute definition of the current node.
+//
+// ID_ATTRIBUTE_XML - Some nodes have an "id" attribute containing a
+// string, which value uniquely identify the entity represented by that node.
+// Other nodes may refer by reference attributes to this value.
+//
+// ATTRIBUTE_SPECIAL_XML( FN, NAME ) - An attribute named NAME which deserves
+// a special handling. See the appropriate documentations.
+//
+// SUB_NODE_XML( CLASS ) - A mandatory sub-node of class CLASS or its sub-classes.
+//
+// SUB_NODE_SEQUENCE_XML( CLASS ) - Zero or more sub-nodes of class CLASS or
+// its sub-classes.
+//
+//===----------------------------------------------------------------------===//
+
+ROOT_NODE_XML("CLANG_XML")
+ ATTRIBUTE_SPECIAL_XML(ignore, "version") // special retrieving needed
+ SUB_NODE_XML("TranslationUnit")
+ SUB_NODE_XML("ReferenceSection")
+END_NODE_XML
+
+NODE_XML("TranslationUnit")
+ SUB_NODE_SEQUENCE_XML(Decl)
+END_NODE_XML
+
+NODE_XML("ReferenceSection")
+ SUB_NODE_XML("Types")
+ SUB_NODE_XML("Contexts")
+ SUB_NODE_XML("Files")
+END_NODE_XML
+
+NODE_XML("Types")
+ SUB_NODE_SEQUENCE_XML(Type)
+END_NODE_XML
+
+NODE_XML("Contexts")
+ SUB_NODE_SEQUENCE_XML(DeclContext)
+END_NODE_XML
+
+NODE_XML("Files")
+ SUB_NODE_SEQUENCE_XML("File")
+END_NODE_XML
+
+NODE_XML("File")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_SPECIAL_XML(ignore, "name") // special retrieving needed, denotes the source file name
+END_NODE_XML
+
+
+//===----------------------------------------------------------------------===//
+#undef NODE_XML
+#undef ID_ATTRIBUTE_XML
+#undef ATTRIBUTE_SPECIAL_XML
+#undef END_NODE_XML
+#undef SUB_NODE_XML
+#undef SUB_NODE_SEQUENCE_XML
diff --git a/include/clang/Frontend/DocumentXML.h b/include/clang/Frontend/DocumentXML.h
index 99db717190dd..4ed11e153ce3 100644
--- a/include/clang/Frontend/DocumentXML.h
+++ b/include/clang/Frontend/DocumentXML.h
@@ -17,6 +17,7 @@
#include <string>
#include <map>
+#include <stack>
#include "clang/AST/Type.h"
#include "clang/AST/TypeOrdering.h"
#include "llvm/Support/raw_ostream.h"
@@ -30,6 +31,7 @@ class Decl;
class NamedDecl;
class FunctionDecl;
class ASTContext;
+class LabelStmt;
//---------------------------------------------------------
namespace XML
@@ -50,26 +52,37 @@ class DocumentXML
{
public:
DocumentXML(const std::string& rootName, llvm::raw_ostream& out);
- ~DocumentXML();
void initialize(ASTContext &Context);
void PrintDecl(Decl *D);
void PrintStmt(const Stmt *S); // defined in StmtXML.cpp
-
void finalize();
DocumentXML& addSubNode(const std::string& name); // also enters the sub node, returns *this
DocumentXML& toParent(); // returns *this
+ void addAttribute(const char* pName, const QualType& pType);
+ void addAttribute(const char* pName, bool value);
+
+ template<class T>
+ void addAttribute(const char* pName, const T* value)
+ {
+ addPtrAttribute(pName, value);
+ }
+
+ template<class T>
+ void addAttribute(const char* pName, T* value)
+ {
+ addPtrAttribute(pName, value);
+ }
+
template<class T>
void addAttribute(const char* pName, const T& value);
- void addTypeAttribute(const QualType& pType);
- void addRefAttribute(const NamedDecl* D);
+ template<class T>
+ void addAttributeOptional(const char* pName, const T& value);
- enum tContextUsage { CONTEXT_AS_CONTEXT, CONTEXT_AS_ID };
- void addContextAttribute(const DeclContext *DC, tContextUsage usage = CONTEXT_AS_CONTEXT);
void addSourceFileAttribute(const std::string& fileName);
PresumedLoc addLocation(const SourceLocation& Loc);
@@ -81,13 +94,9 @@ private:
DocumentXML(const DocumentXML&); // not defined
DocumentXML& operator=(const DocumentXML&); // not defined
- struct NodeXML;
-
- NodeXML* Root;
- NodeXML* CurrentNode; // always after Root
+ std::stack<std::string> NodeStack;
llvm::raw_ostream& Out;
ASTContext *Ctx;
- int CurrentIndent;
bool HasCurrentNodeSubNodes;
@@ -96,15 +105,38 @@ private:
XML::IdMap<const Type*> BasicTypes;
XML::IdMap<std::string> SourceFiles;
XML::IdMap<const NamedDecl*> Decls;
+ XML::IdMap<const LabelStmt*> Labels;
void addContextsRecursively(const DeclContext *DC);
- void addBasicTypeRecursively(const Type* pType);
+ void addTypeRecursively(const Type* pType);
void addTypeRecursively(const QualType& pType);
- void PrintFunctionDecl(FunctionDecl *FD);
- void addDeclIdAttribute(const NamedDecl* D);
- void addTypeIdAttribute(const Type* pType);
void Indent();
+
+ // forced pointer dispatch:
+ void addPtrAttribute(const char* pName, const Type* pType);
+ void addPtrAttribute(const char* pName, const NamedDecl* D);
+ void addPtrAttribute(const char* pName, const DeclContext* D);
+ void addPtrAttribute(const char* pName, const NamespaceDecl* D); // disambiguation
+ void addPtrAttribute(const char* pName, const LabelStmt* L);
+ void addPtrAttribute(const char* pName, const char* text);
+
+ // defined in TypeXML.cpp:
+ void addParentTypes(const Type* pType);
+ void writeTypeToXML(const Type* pType);
+ void writeTypeToXML(const QualType& pType);
+ class TypeAdder;
+ friend class TypeAdder;
+
+ // defined in DeclXML.cpp:
+ void writeDeclToXML(Decl *D);
+ class DeclPrinter;
+ friend class DeclPrinter;
+
+ // for addAttributeOptional:
+ static bool isDefault(unsigned value) { return value == 0; }
+ static bool isDefault(bool value) { return !value; }
+ static bool isDefault(const std::string& value) { return value.empty(); }
};
//--------------------------------------------------------- inlines
@@ -122,6 +154,28 @@ inline void DocumentXML::addAttribute(const char* pName, const T& value)
}
//---------------------------------------------------------
+inline void DocumentXML::addPtrAttribute(const char* pName, const char* text)
+{
+ Out << ' ' << pName << "=\"" << text << "\"";
+}
+
+//---------------------------------------------------------
+inline void DocumentXML::addAttribute(const char* pName, bool value)
+{
+ addPtrAttribute(pName, value ? "1" : "0");
+}
+
+//---------------------------------------------------------
+template<class T>
+inline void DocumentXML::addAttributeOptional(const char* pName, const T& value)
+{
+ if (!isDefault(value))
+ {
+ addAttribute(pName, value);
+ }
+}
+
+//---------------------------------------------------------
} //namespace clang
diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h
index 0862cd6390f4..e546a12c49e9 100644
--- a/include/clang/Frontend/PCHBitCodes.h
+++ b/include/clang/Frontend/PCHBitCodes.h
@@ -386,8 +386,8 @@ namespace clang {
TYPE_OBJC_INTERFACE = 21,
/// \brief An ObjCQualifiedInterfaceType record.
TYPE_OBJC_QUALIFIED_INTERFACE = 22,
- /// \brief An ObjCQualifiedIdType record.
- TYPE_OBJC_QUALIFIED_ID = 23
+ /// \brief An ObjCObjectPointerType record.
+ TYPE_OBJC_OBJECT_POINTER = 23
};
/// \brief The type IDs for special types constructed by semantic
diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h
index 1e00ae34137d..b3ed36434312 100644
--- a/include/clang/Frontend/PCHReader.h
+++ b/include/clang/Frontend/PCHReader.h
@@ -53,6 +53,82 @@ class NamedDecl;
class Preprocessor;
class Sema;
class SwitchCase;
+class PCHReader;
+class HeaderFileInfo;
+
+/// \brief Abstract interface for callback invocations by the PCHReader.
+///
+/// While reading a PCH file, the PCHReader will call the methods of the
+/// listener to pass on specific information. Some of the listener methods can
+/// return true to indicate to the PCHReader that the information (and
+/// consequently the PCH file) is invalid.
+class PCHReaderListener {
+public:
+ virtual ~PCHReaderListener();
+
+ /// \brief Receives the language options.
+ ///
+ /// \returns true to indicate the options are invalid or false otherwise.
+ virtual bool ReadLanguageOptions(const LangOptions &LangOpts) {
+ return false;
+ }
+
+ /// \brief Receives the target triple.
+ ///
+ /// \returns true to indicate the target triple is invalid or false otherwise.
+ virtual bool ReadTargetTriple(const std::string &Triple) {
+ return false;
+ }
+
+ /// \brief Receives the contents of the predefines buffer.
+ ///
+ /// \param PCHPredef The start of the predefines buffer in the PCH
+ /// file.
+ ///
+ /// \param PCHPredefLen The length of the predefines buffer in the PCH
+ /// file.
+ ///
+ /// \param PCHBufferID The FileID for the PCH predefines buffer.
+ ///
+ /// \param SuggestedPredefines If necessary, additional definitions are added
+ /// here.
+ ///
+ /// \returns true to indicate the predefines are invalid or false otherwise.
+ virtual bool ReadPredefinesBuffer(const char *PCHPredef,
+ unsigned PCHPredefLen,
+ FileID PCHBufferID,
+ std::string &SuggestedPredefines) {
+ return false;
+ }
+
+ /// \brief Receives a HeaderFileInfo entry.
+ virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI) {}
+
+ /// \brief Receives __COUNTER__ value.
+ virtual void ReadCounter(unsigned Value) {}
+};
+
+/// \brief PCHReaderListener implementation to validate the information of
+/// the PCH file against an initialized Preprocessor.
+class PCHValidator : public PCHReaderListener {
+ Preprocessor &PP;
+ PCHReader &Reader;
+
+ unsigned NumHeaderInfos;
+
+public:
+ PCHValidator(Preprocessor &PP, PCHReader &Reader)
+ : PP(PP), Reader(Reader), NumHeaderInfos(0) {}
+
+ virtual bool ReadLanguageOptions(const LangOptions &LangOpts);
+ virtual bool ReadTargetTriple(const std::string &Triple);
+ virtual bool ReadPredefinesBuffer(const char *PCHPredef,
+ unsigned PCHPredefLen,
+ FileID PCHBufferID,
+ std::string &SuggestedPredefines);
+ virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI);
+ virtual void ReadCounter(unsigned Value);
+};
/// \brief Reads a precompiled head containing the contents of a
/// translation unit.
@@ -75,12 +151,19 @@ public:
enum PCHReadResult { Success, Failure, IgnorePCH };
private:
+ /// \ brief The receiver of some callbacks invoked by PCHReader.
+ llvm::OwningPtr<PCHReaderListener> Listener;
+
+ SourceManager &SourceMgr;
+ FileManager &FileMgr;
+ Diagnostic &Diags;
+
/// \brief The semantic analysis object that will be processing the
/// PCH file and the translation unit that uses it.
Sema *SemaObj;
/// \brief The preprocessor that will be loading the source file.
- Preprocessor &PP;
+ Preprocessor *PP;
/// \brief The AST context into which we'll read the PCH file.
ASTContext *Context;
@@ -328,12 +411,33 @@ private:
public:
typedef llvm::SmallVector<uint64_t, 64> RecordData;
- explicit PCHReader(Preprocessor &PP, ASTContext *Context);
+ /// \brief Load the PCH file and validate its contents against the given
+ /// Preprocessor.
+ PCHReader(Preprocessor &PP, ASTContext *Context);
+
+ /// \brief Load the PCH file without using any pre-initialized Preprocessor.
+ ///
+ /// The necessary information to initialize a Preprocessor later can be
+ /// obtained by setting a PCHReaderListener.
+ PCHReader(SourceManager &SourceMgr, FileManager &FileMgr, Diagnostic &Diags);
~PCHReader();
/// \brief Load the precompiled header designated by the given file
/// name.
PCHReadResult ReadPCH(const std::string &FileName);
+
+ /// \brief Set the PCH callbacks listener.
+ void setListener(PCHReaderListener *listener) {
+ Listener.reset(listener);
+ }
+
+ /// \brief Set the Preprocessor to use.
+ void setPreprocessor(Preprocessor &pp) {
+ PP = &pp;
+ }
+
+ /// \brief Sets and initializes the given Context.
+ void InitializeContext(ASTContext &Context);
/// \brief Retrieve the name of the original source file name
const std::string &getOriginalSourceFile() { return OriginalFileName; }
diff --git a/include/clang/Frontend/StmtXML.def b/include/clang/Frontend/StmtXML.def
new file mode 100644
index 000000000000..26430f740d91
--- /dev/null
+++ b/include/clang/Frontend/StmtXML.def
@@ -0,0 +1,517 @@
+//===-- StmtXML.def - Metadata about Stmt XML nodes ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the XML statement database structure as written in
+// <TranslationUnit> sub-nodes of the XML document.
+// The semantics of the attributes and enums are mostly self-documenting
+// by looking at the appropriate internally used functions and values.
+// The following macros are used:
+//
+// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete
+// statement of class CLASS where CLASS is a class name used internally by clang.
+// After a NODE_XML the definition of all (optional) attributes of that statement
+// node and possible sub-nodes follows.
+//
+// END_NODE_XML - Closes the attribute definition of the current node.
+//
+// ID_ATTRIBUTE_XML - Some statement nodes have an "id" attribute containing a
+// string, which value uniquely identify that statement. Other nodes may refer
+// by reference attributes to this value (currently used only for Label).
+//
+// TYPE_ATTRIBUTE_XML( FN ) - Type nodes refer to the result type id of an
+// expression by a "type" attribute. FN is internally used by clang.
+//
+// ATTRIBUTE_XML( FN, NAME ) - An attribute named NAME. FN is internally
+// used by clang. A boolean attribute have the values "0" or "1".
+//
+// ATTRIBUTE_SPECIAL_XML( FN, NAME ) - An attribute named NAME which deserves
+// a special handling. See the appropriate documentations.
+//
+// ATTRIBUTE_FILE_LOCATION_XML - A bunch of attributes denoting the location of
+// a statement in the source file(s).
+//
+// ATTRIBUTE_OPT_XML( FN, NAME ) - An optional attribute named NAME.
+// Optional attributes are omitted for boolean types, if the value is false,
+// for integral types, if the value is null and for strings,
+// if the value is the empty string. FN is internally used by clang.
+//
+// ATTRIBUTE_ENUM[_OPT]_XML( FN, NAME ) - An attribute named NAME. The value
+// is an enumeration defined with ENUM_XML macros immediately following after
+// that macro. An optional attribute is ommited, if the particular enum is the
+// empty string. FN is internally used by clang.
+//
+// ENUM_XML( VALUE, NAME ) - An enumeration element named NAME. VALUE is
+// internally used by clang.
+//
+// END_ENUM_XML - Closes the enumeration definition of the current attribute.
+//
+// SUB_NODE_XML( CLASS ) - A mandatory sub-node of class CLASS or its sub-classes.
+//
+// SUB_NODE_OPT_XML( CLASS ) - An optional sub-node of class CLASS or its sub-classes.
+//
+// SUB_NODE_SEQUENCE_XML( CLASS ) - Zero or more sub-nodes of class CLASS or
+// its sub-classes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef ATTRIBUTE_FILE_LOCATION_XML
+# define ATTRIBUTE_FILE_LOCATION_XML \
+ ATTRIBUTE_XML(getFilename(), "file") \
+ ATTRIBUTE_XML(getLine(), "line") \
+ ATTRIBUTE_XML(getColumn(), "col") \
+ ATTRIBUTE_OPT_XML(getFilename(), "endfile") \
+ ATTRIBUTE_OPT_XML(getLine(), "endline") \
+ ATTRIBUTE_OPT_XML(getColumn(), "endcol")
+#endif
+
+#ifndef TYPE_ATTRIBUTE_XML
+# define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type")
+#endif
+
+#ifndef CONTEXT_ATTRIBUTE_XML
+# define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context")
+#endif
+
+
+NODE_XML(NullStmt, "NullStmt")
+ ATTRIBUTE_FILE_LOCATION_XML
+END_NODE_XML
+
+NODE_XML(CompoundStmt, "CompoundStmt")
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(size(), "num_stmts")
+ SUB_NODE_SEQUENCE_XML(Stmt)
+END_NODE_XML
+
+NODE_XML(CaseStmt, "CaseStmt") // case expr: body;
+ ATTRIBUTE_FILE_LOCATION_XML
+ SUB_NODE_XML(Stmt) // body
+ SUB_NODE_XML(Expr) // expr
+ SUB_NODE_XML(Expr) // rhs expr in gc extension: case expr .. expr: body;
+END_NODE_XML
+
+NODE_XML(DefaultStmt, "DefaultStmt") // default: body;
+ ATTRIBUTE_FILE_LOCATION_XML
+ SUB_NODE_XML(Stmt) // body
+END_NODE_XML
+
+NODE_XML(LabelStmt, "LabelStmt") // Label: body;
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getName(), "name") // string
+ SUB_NODE_XML(Stmt) // body
+END_NODE_XML
+
+NODE_XML(IfStmt, "IfStmt") // if (cond) stmt1; else stmt2;
+ ATTRIBUTE_FILE_LOCATION_XML
+ SUB_NODE_XML(Expr) // cond
+ SUB_NODE_XML(Stmt) // stmt1
+ SUB_NODE_XML(Stmt) // stmt2
+END_NODE_XML
+
+NODE_XML(SwitchStmt, "SwitchStmt") // switch (cond) body;
+ ATTRIBUTE_FILE_LOCATION_XML
+ SUB_NODE_XML(Expr) // cond
+ SUB_NODE_XML(Stmt) // body
+END_NODE_XML
+
+NODE_XML(WhileStmt, "WhileStmt") // while (cond) body;
+ ATTRIBUTE_FILE_LOCATION_XML
+ SUB_NODE_XML(Expr) // cond
+ SUB_NODE_XML(Stmt) // body
+END_NODE_XML
+
+NODE_XML(DoStmt, "DoStmt") // do body while (cond);
+ ATTRIBUTE_FILE_LOCATION_XML
+ SUB_NODE_XML(Expr) // cond
+ SUB_NODE_XML(Stmt) // body
+END_NODE_XML
+
+NODE_XML(ForStmt, "ForStmt") // for (init; cond; inc) body;
+ ATTRIBUTE_FILE_LOCATION_XML
+ SUB_NODE_XML(Stmt) // init
+ SUB_NODE_XML(Expr) // cond
+ SUB_NODE_XML(Expr) // inc
+ SUB_NODE_XML(Stmt) // body
+END_NODE_XML
+
+NODE_XML(GotoStmt, "GotoStmt") // goto label;
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getLabel()->getName(), "name") // informal string
+ ATTRIBUTE_XML(getLabel(), "ref") // id string
+END_NODE_XML
+
+NODE_XML(IndirectGotoStmt, "IndirectGotoStmt") // goto expr;
+ ATTRIBUTE_FILE_LOCATION_XML
+ SUB_NODE_XML(Expr) // expr
+END_NODE_XML
+
+NODE_XML(ContinueStmt, "ContinueStmt") // continue
+ ATTRIBUTE_FILE_LOCATION_XML
+END_NODE_XML
+
+NODE_XML(BreakStmt, "BreakStmt") // break
+ ATTRIBUTE_FILE_LOCATION_XML
+END_NODE_XML
+
+NODE_XML(ReturnStmt, "ReturnStmt") // return expr;
+ ATTRIBUTE_FILE_LOCATION_XML
+ SUB_NODE_XML(Expr) // expr
+END_NODE_XML
+
+NODE_XML(AsmStmt, "AsmStmt") // GNU inline-assembly statement extension
+ ATTRIBUTE_FILE_LOCATION_XML
+ // FIXME
+END_NODE_XML
+
+NODE_XML(DeclStmt, "DeclStmt") // a declaration statement
+ ATTRIBUTE_FILE_LOCATION_XML
+ SUB_NODE_SEQUENCE_XML(Decl)
+END_NODE_XML
+
+// C++ statements
+NODE_XML(CXXTryStmt, "CXXTryStmt") // try CompoundStmt CXXCatchStmt1 CXXCatchStmt2 ..
+ ATTRIBUTE_FILE_LOCATION_XML
+ ATTRIBUTE_XML(getNumHandlers(), "num_handlers")
+ SUB_NODE_XML(CompoundStmt)
+ SUB_NODE_SEQUENCE_XML(CXXCatchStmt)
+END_NODE_XML
+
+NODE_XML(CXXCatchStmt, "CXXCatchStmt") // catch (decl) Stmt
+ ATTRIBUTE_FILE_LOCATION_XML
+ SUB_NODE_XML(VarDecl)
+ SUB_NODE_XML(Stmt)
+END_NODE_XML
+
+// Expressions
+NODE_XML(PredefinedExpr, "PredefinedExpr")
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_ENUM_XML(getIdentType(), "kind")
+ ENUM_XML(PredefinedExpr::Func, "__func__")
+ ENUM_XML(PredefinedExpr::Function, "__FUNCTION__")
+ ENUM_XML(PredefinedExpr::PrettyFunction, "__PRETTY_FUNCTION__")
+ END_ENUM_XML
+END_NODE_XML
+
+NODE_XML(DeclRefExpr, "DeclRefExpr") // an expression referring to a declared entity
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_XML(getDecl(), "ref") // id string of the declaration
+ ATTRIBUTE_XML(getDecl()->getNameAsString(), "name") // informal
+ //ATTRIBUTE_ENUM_XML(getDecl()->getKind(), "kind") // really needed here?
+END_NODE_XML
+
+NODE_XML(IntegerLiteral, "IntegerLiteral")
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_XML(getValue(), "value") // (signed) integer
+END_NODE_XML
+
+NODE_XML(CharacterLiteral, "CharacterLiteral")
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_XML(getValue(), "value") // unsigned
+END_NODE_XML
+
+NODE_XML(FloatingLiteral, "FloatingLiteral")
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ // FIXME: output float as written in source (no approximation or the like)
+ //ATTRIBUTE_XML(getValueAsApproximateDouble(), "value") // float
+END_NODE_XML
+
+NODE_XML(StringLiteral, "StringLiteral")
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_SPECIAL_XML(getStrData(), "value") // string, special handling for escaping needed
+ ATTRIBUTE_OPT_XML(isWide(), "is_wide") // boolean
+END_NODE_XML
+
+NODE_XML(UnaryOperator, "UnaryOperator") // op(expr) or (expr)op
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_ENUM_XML(getOpcode(), "kind")
+ ENUM_XML(UnaryOperator::PostInc, "postinc")
+ ENUM_XML(UnaryOperator::PostDec, "postdec")
+ ENUM_XML(UnaryOperator::PreInc, "preinc")
+ ENUM_XML(UnaryOperator::PreDec, "predec")
+ ENUM_XML(UnaryOperator::AddrOf, "addrof")
+ ENUM_XML(UnaryOperator::Deref, "deref")
+ ENUM_XML(UnaryOperator::Plus, "plus")
+ ENUM_XML(UnaryOperator::Minus, "minus")
+ ENUM_XML(UnaryOperator::Not, "not") // bitwise not
+ ENUM_XML(UnaryOperator::LNot, "lnot") // boolean not
+ ENUM_XML(UnaryOperator::Real, "__real")
+ ENUM_XML(UnaryOperator::Imag, "__imag")
+ ENUM_XML(UnaryOperator::Extension, "__extension__")
+ ENUM_XML(UnaryOperator::OffsetOf, "__builtin_offsetof")
+ END_ENUM_XML
+ SUB_NODE_XML(Expr) // expr
+END_NODE_XML
+
+NODE_XML(BinaryOperator, "BinaryOperator") // (expr1) op (expr2)
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_ENUM_XML(getOpcode(), "kind")
+ ENUM_XML(BinaryOperator::PtrMemD , "ptrmemd")
+ ENUM_XML(BinaryOperator::PtrMemI , "ptrmemi")
+ ENUM_XML(BinaryOperator::Mul , "mul")
+ ENUM_XML(BinaryOperator::Div , "div")
+ ENUM_XML(BinaryOperator::Rem , "rem")
+ ENUM_XML(BinaryOperator::Add , "add")
+ ENUM_XML(BinaryOperator::Sub , "sub")
+ ENUM_XML(BinaryOperator::Shl , "shl")
+ ENUM_XML(BinaryOperator::Shr , "shr")
+ ENUM_XML(BinaryOperator::LT , "lt")
+ ENUM_XML(BinaryOperator::GT , "gt")
+ ENUM_XML(BinaryOperator::LE , "le")
+ ENUM_XML(BinaryOperator::GE , "ge")
+ ENUM_XML(BinaryOperator::EQ , "eq")
+ ENUM_XML(BinaryOperator::NE , "ne")
+ ENUM_XML(BinaryOperator::And , "and") // bitwise and
+ ENUM_XML(BinaryOperator::Xor , "xor")
+ ENUM_XML(BinaryOperator::Or , "or") // bitwise or
+ ENUM_XML(BinaryOperator::LAnd , "land") // boolean and
+ ENUM_XML(BinaryOperator::LOr , "lor") // boolean or
+ ENUM_XML(BinaryOperator::Assign , "assign")
+ ENUM_XML(BinaryOperator::MulAssign, "mulassign")
+ ENUM_XML(BinaryOperator::DivAssign, "divassign")
+ ENUM_XML(BinaryOperator::RemAssign, "remassign")
+ ENUM_XML(BinaryOperator::AddAssign, "addassign")
+ ENUM_XML(BinaryOperator::SubAssign, "subassign")
+ ENUM_XML(BinaryOperator::ShlAssign, "shlassign")
+ ENUM_XML(BinaryOperator::ShrAssign, "shrassign")
+ ENUM_XML(BinaryOperator::AndAssign, "andassign")
+ ENUM_XML(BinaryOperator::XorAssign, "xorassign")
+ ENUM_XML(BinaryOperator::OrAssign , "orassign")
+ ENUM_XML(BinaryOperator::Comma , "comma")
+ END_ENUM_XML
+ SUB_NODE_XML(Expr) // expr1
+ SUB_NODE_XML(Expr) // expr2
+END_NODE_XML
+
+// FIXME: is there a special class needed or is BinaryOperator sufficient?
+//NODE_XML(CompoundAssignOperator, "CompoundAssignOperator")
+
+NODE_XML(ConditionalOperator, "ConditionalOperator") // expr1 ? expr2 : expr3
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ SUB_NODE_XML(Expr) // expr1
+ SUB_NODE_XML(Expr) // expr2
+ SUB_NODE_XML(Expr) // expr3
+END_NODE_XML
+
+NODE_XML(SizeOfAlignOfExpr, "SizeOfAlignOfExpr") // sizeof(expr) or alignof(expr)
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_XML(isSizeOf(), "is_sizeof")
+ ATTRIBUTE_XML(isArgumentType(), "is_type") // "1" if expr denotes a type
+ ATTRIBUTE_SPECIAL_XML(getArgumentType(), "type_ref") // optional, denotes the type of expr, if is_type=="1", special handling needed since getArgumentType() could assert
+ SUB_NODE_OPT_XML(Expr) // expr, if is_type=="0"
+END_NODE_XML
+
+NODE_XML(ArraySubscriptExpr, "ArraySubscriptExpr") // expr1[expr2]
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ SUB_NODE_XML(Expr) // expr1
+ SUB_NODE_XML(Expr) // expr2
+END_NODE_XML
+
+NODE_XML(CallExpr, "CallExpr") // fnexpr(arg1, arg2, ...)
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_XML(getNumArgs(), "num_args") // unsigned
+ SUB_NODE_XML(Expr) // fnexpr
+ SUB_NODE_SEQUENCE_XML(Expr) // arg1..argN
+END_NODE_XML
+
+NODE_XML(MemberExpr, "MemberExpr") // expr->F or expr.F
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_XML(isArrow(), "is_deref")
+ ATTRIBUTE_XML(getMemberDecl(), "ref") // refers to F
+ ATTRIBUTE_XML(getMemberDecl()->getNameAsString(), "name") // informal
+ SUB_NODE_XML(Expr) // expr
+END_NODE_XML
+
+NODE_XML(CStyleCastExpr, "CStyleCastExpr") // (type)expr
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_XML(getTypeAsWritten(), "type_ref") // denotes the type as written in the source code
+ SUB_NODE_XML(Expr) // expr
+END_NODE_XML
+
+NODE_XML(ImplicitCastExpr, "ImplicitCastExpr")
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ SUB_NODE_XML(Expr)
+END_NODE_XML
+
+NODE_XML(CompoundLiteralExpr, "CompoundLiteralExpr") // [C99 6.5.2.5]
+ SUB_NODE_XML(Expr) // init
+END_NODE_XML
+
+NODE_XML(ExtVectorElementExpr, "ExtVectorElementExpr")
+ SUB_NODE_XML(Expr) // base
+END_NODE_XML
+
+NODE_XML(InitListExpr, "InitListExpr") // struct foo x = { expr1, { expr2, expr3 } };
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_OPT_XML(getInitializedFieldInUnion(), "field_ref") // if a union is initialized, this refers to the initialized union field id
+ ATTRIBUTE_XML(getNumInits(), "num_inits") // unsigned
+ SUB_NODE_SEQUENCE_XML(Expr) // expr1..exprN
+END_NODE_XML
+
+NODE_XML(DesignatedInitExpr, "DesignatedInitExpr")
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+END_NODE_XML
+
+NODE_XML(ImplicitValueInitExpr, "ImplicitValueInitExpr") // Implicit value initializations occur within InitListExpr
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+END_NODE_XML
+
+NODE_XML(VAArgExpr, "VAArgExpr") // used for the builtin function __builtin_va_start(expr)
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ SUB_NODE_XML(Expr) // expr
+END_NODE_XML
+
+NODE_XML(ParenExpr, "ParenExpr") // this represents a parethesized expression "(expr)". Only formed if full location information is requested.
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ SUB_NODE_XML(Expr) // expr
+END_NODE_XML
+
+// GNU Extensions
+NODE_XML(AddrLabelExpr, "AddrLabelExpr") // the GNU address of label extension, representing &&label.
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_XML(getLabel(), "ref") // id string
+ SUB_NODE_XML(LabelStmt) // expr
+END_NODE_XML
+
+NODE_XML(StmtExpr, "StmtExpr") // StmtExpr contains a single CompoundStmt node, which it evaluates and takes the value of the last subexpression.
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ SUB_NODE_XML(CompoundStmt)
+END_NODE_XML
+
+NODE_XML(TypesCompatibleExpr, "TypesCompatibleExpr") // GNU builtin-in function __builtin_types_compatible_p
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_XML(getArgType1(), "type1_ref") // id of type1
+ ATTRIBUTE_XML(getArgType2(), "type2_ref") // id of type2
+END_NODE_XML
+
+NODE_XML(ChooseExpr, "ChooseExpr") // GNU builtin-in function __builtin_choose_expr(expr1, expr2, expr3)
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ SUB_NODE_XML(Expr) // expr1
+ SUB_NODE_XML(Expr) // expr2
+ SUB_NODE_XML(Expr) // expr3
+END_NODE_XML
+
+NODE_XML(GNUNullExpr, "GNUNullExpr") // GNU __null extension
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+END_NODE_XML
+
+// C++ Expressions
+NODE_XML(CXXOperatorCallExpr, "CXXOperatorCallExpr") // fnexpr(arg1, arg2, ...)
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_XML(getNumArgs(), "num_args") // unsigned
+ SUB_NODE_XML(Expr) // fnexpr
+ SUB_NODE_SEQUENCE_XML(Expr) // arg1..argN
+END_NODE_XML
+
+NODE_XML(CXXNamedCastExpr, "CXXNamedCastExpr") // xxx_cast<type>(expr)
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_ENUM_XML(getStmtClass(), "kind")
+ ENUM_XML(Stmt::CXXStaticCastExprClass, "static_cast")
+ ENUM_XML(Stmt::CXXDynamicCastExprClass, "dynamic_cast")
+ ENUM_XML(Stmt::CXXReinterpretCastExprClass, "reinterpret_cast")
+ ENUM_XML(Stmt::CXXConstCastExprClass, "const_cast")
+ END_ENUM_XML
+ ATTRIBUTE_XML(getTypeAsWritten(), "type_ref") // denotes the type as written in the source code
+ SUB_NODE_XML(Expr) // expr
+END_NODE_XML
+
+NODE_XML(CXXMemberCallExpr, "CXXMemberCallExpr") // fnexpr(arg1, arg2, ...)
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_XML(getNumArgs(), "num_args") // unsigned
+ SUB_NODE_XML(Expr) // fnexpr
+ SUB_NODE_SEQUENCE_XML(Expr) // arg1..argN
+END_NODE_XML
+
+NODE_XML(CXXBoolLiteralExpr, "CXXBoolLiteralExpr")
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_XML(getValue(), "value") // boolean
+END_NODE_XML
+
+NODE_XML(CXXNullPtrLiteralExpr, "CXXNullPtrLiteralExpr") // [C++0x 2.14.7] C++ Pointer Literal
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+END_NODE_XML
+
+NODE_XML(CXXTypeidExpr, "CXXTypeidExpr") // typeid(expr)
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_XML(isTypeOperand(), "is_type") // "1" if expr denotes a type
+ ATTRIBUTE_SPECIAL_XML(getTypeOperand(), "type_ref") // optional, denotes the type of expr, if is_type=="1", special handling needed since getTypeOperand() could assert
+ SUB_NODE_OPT_XML(Expr) // expr, if is_type=="0"
+END_NODE_XML
+
+NODE_XML(CXXThisExpr, "CXXThisExpr") // this
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+END_NODE_XML
+
+NODE_XML(CXXThrowExpr, "CXXThrowExpr") // throw (expr);
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ SUB_NODE_XML(Expr) // NULL in case of "throw;"
+END_NODE_XML
+
+NODE_XML(CXXDefaultArgExpr, "CXXDefaultArgExpr")
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_XML(getParam(), "ref") // id of the parameter declaration (the expression is a subnode of the declaration)
+END_NODE_XML
+
+NODE_XML(CXXConditionDeclExpr, "CXXConditionDeclExpr")
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ SUB_NODE_XML(VarDecl) // a CXXConditionDeclExpr owns the declaration
+END_NODE_XML
+
+
+//===----------------------------------------------------------------------===//
+#undef NODE_XML
+#undef ID_ATTRIBUTE_XML
+#undef TYPE_ATTRIBUTE_XML
+#undef ATTRIBUTE_XML
+#undef ATTRIBUTE_SPECIAL_XML
+#undef ATTRIBUTE_OPT_XML
+#undef ATTRIBUTE_ENUM_XML
+#undef ATTRIBUTE_ENUM_OPT_XML
+#undef ATTRIBUTE_FILE_LOCATION_XML
+#undef ENUM_XML
+#undef END_ENUM_XML
+#undef END_NODE_XML
+#undef SUB_NODE_XML
+#undef SUB_NODE_SEQUENCE_XML
+#undef SUB_NODE_OPT_XML
diff --git a/include/clang/Frontend/TypeXML.def b/include/clang/Frontend/TypeXML.def
new file mode 100644
index 000000000000..2a78fd9f75b1
--- /dev/null
+++ b/include/clang/Frontend/TypeXML.def
@@ -0,0 +1,277 @@
+//===-- TypeXML.def - Metadata about Type XML nodes ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the XML type info database as written in the
+// <ReferenceSection>/<Types> sub-nodes of the XML document. Type nodes
+// are referred by "type" reference attributes throughout the document.
+// A type node never contains sub-nodes.
+// The semantics of the attributes and enums are mostly self-documenting
+// by looking at the appropriate internally used functions and values.
+// The following macros are used:
+//
+// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete
+// type of class CLASS where CLASS is a class name used internally by clang.
+// After a NODE_XML the definition of all (optional) attributes of that type
+// node follows.
+//
+// END_NODE_XML - Closes the attribute definition of the current node.
+//
+// ID_ATTRIBUTE_XML - Each type node has an "id" attribute containing a
+// string, which value uniquely identify the type. Other nodes may refer
+// by "type" reference attributes to this value.
+//
+// TYPE_ATTRIBUTE_XML( FN ) - Type nodes may refer to the ids of other type
+// nodes by a "type" attribute. FN is internally used by clang.
+//
+// CONTEXT_ATTRIBUTE_XML( FN ) - Type nodes may refer to the ids of their
+// declaration contexts by a "context" attribute. FN is internally used by
+// clang.
+//
+// ATTRIBUTE_XML( FN, NAME ) - An attribute named NAME. FN is internally
+// used by clang. A boolean attribute have the values "0" or "1".
+//
+// ATTRIBUTE_OPT_XML( FN, NAME ) - An optional attribute named NAME.
+// Optional attributes are omitted for boolean types, if the value is false,
+// for integral types, if the value is null and for strings,
+// if the value is the empty string. FN is internally used by clang.
+//
+// ATTRIBUTE_ENUM[_OPT]_XML( FN, NAME ) - An attribute named NAME. The value
+// is an enumeration defined with ENUM_XML macros immediately following after
+// that macro. An optional attribute is ommited, if the particular enum is the
+// empty string. FN is internally used by clang.
+//
+// ENUM_XML( VALUE, NAME ) - An enumeration element named NAME. VALUE is
+// internally used by clang.
+//
+// END_ENUM_XML - Closes the enumeration definition of the current attribute.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TYPE_ATTRIBUTE_XML
+# define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type")
+#endif
+
+#ifndef CONTEXT_ATTRIBUTE_XML
+# define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context")
+#endif
+
+
+NODE_XML(QualType, "CvQualifiedType")
+ ID_ATTRIBUTE_XML
+ TYPE_ATTRIBUTE_XML(getTypePtr()) // the qualified type, e.g. for 'T* const' it's 'T*'
+ ATTRIBUTE_OPT_XML(isConstQualified(), "const") // boolean
+ ATTRIBUTE_OPT_XML(isVolatileQualified(), "volatile") // boolean
+ ATTRIBUTE_OPT_XML(isRestrictQualified(), "restrict") // boolean
+END_NODE_XML
+
+NODE_XML(ExtQualType, "ExtQualType")
+ ID_ATTRIBUTE_XML
+ TYPE_ATTRIBUTE_XML(getBaseType())
+ ATTRIBUTE_OPT_XML(getAddressSpace(), "adress_space") // unsigned: Address Space ID - The address space ID this type is qualified with.
+ ATTRIBUTE_ENUM_OPT_XML(getObjCGCAttr(), "objc_gc") // GC __weak/__strong attributes
+ ENUM_XML(QualType::GCNone, "")
+ ENUM_XML(QualType::Weak, "weak")
+ ENUM_XML(QualType::Strong, "strong")
+ END_ENUM_XML
+END_NODE_XML
+
+NODE_XML(BuiltinType, "FundamentalType")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_ENUM_XML(getKind(), "kind")
+ ENUM_XML(BuiltinType::Void, "void")
+ ENUM_XML(BuiltinType::Bool, "bool")
+ ENUM_XML(BuiltinType::Char_U, "char") // not explicitely qualified char, depends on target platform
+ ENUM_XML(BuiltinType::Char_S, "char") // not explicitely qualified char, depends on target platform
+ ENUM_XML(BuiltinType::SChar, "signed char")
+ ENUM_XML(BuiltinType::Short, "short");
+ ENUM_XML(BuiltinType::Int, "int");
+ ENUM_XML(BuiltinType::Long, "long");
+ ENUM_XML(BuiltinType::LongLong, "long long");
+ ENUM_XML(BuiltinType::Int128, "__int128_t");
+ ENUM_XML(BuiltinType::UChar, "unsigned char");
+ ENUM_XML(BuiltinType::UShort, "unsigned short");
+ ENUM_XML(BuiltinType::UInt, "unsigned int");
+ ENUM_XML(BuiltinType::ULong, "unsigned long");
+ ENUM_XML(BuiltinType::ULongLong, "unsigned long long");
+ ENUM_XML(BuiltinType::UInt128, "__uint128_t");
+ ENUM_XML(BuiltinType::Float, "float");
+ ENUM_XML(BuiltinType::Double, "double");
+ ENUM_XML(BuiltinType::LongDouble, "long double");
+ ENUM_XML(BuiltinType::WChar, "wchar_t");
+ ENUM_XML(BuiltinType::NullPtr, "nullptr_t"); // This is the type of C++0x 'nullptr'.
+ ENUM_XML(BuiltinType::Overload, "overloaded");
+ ENUM_XML(BuiltinType::Dependent, "dependent");
+ END_ENUM_XML
+END_NODE_XML
+
+NODE_XML(FixedWidthIntType, "FixedWidthIntType")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_XML(getWidth(), "width") // unsigned
+ ATTRIBUTE_XML(isSigned(), "is_signed") // boolean
+END_NODE_XML
+
+NODE_XML(PointerType, "PointerType")
+ ID_ATTRIBUTE_XML
+ TYPE_ATTRIBUTE_XML(getPointeeType())
+END_NODE_XML
+
+NODE_XML(LValueReferenceType, "ReferenceType")
+ ID_ATTRIBUTE_XML
+ TYPE_ATTRIBUTE_XML(getPointeeType())
+END_NODE_XML
+
+NODE_XML(RValueReferenceType, "ReferenceType")
+ ID_ATTRIBUTE_XML
+ TYPE_ATTRIBUTE_XML(getPointeeType())
+END_NODE_XML
+
+NODE_XML(FunctionNoProtoType, "FunctionNoProtoType")
+ ID_ATTRIBUTE_XML
+END_NODE_XML
+
+NODE_XML(FunctionProtoType, "FunctionType")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_XML(getResultType(), "result_type")
+ ATTRIBUTE_OPT_XML(isVariadic(), "variadic")
+END_NODE_XML
+
+NODE_XML(TypedefType, "Typedef")
+ ID_ATTRIBUTE_XML
+ TYPE_ATTRIBUTE_XML(getDecl()->getUnderlyingType())
+ ATTRIBUTE_XML(getDecl()->getNameAsString(), "name") // string
+ CONTEXT_ATTRIBUTE_XML(getDecl()->getDeclContext())
+END_NODE_XML
+
+NODE_XML(ComplexType, "ComplexType") // C99 complex types (_Complex float etc)
+ ID_ATTRIBUTE_XML
+ TYPE_ATTRIBUTE_XML(getElementType())
+END_NODE_XML
+
+NODE_XML(BlockPointerType, "BlockPointerType")
+ ID_ATTRIBUTE_XML
+ TYPE_ATTRIBUTE_XML(getPointeeType()) // alway refers to a function type
+END_NODE_XML
+
+NODE_XML(MemberPointerType, "MemberPointerType")
+ ID_ATTRIBUTE_XML
+ TYPE_ATTRIBUTE_XML(getPointeeType())
+ ATTRIBUTE_XML(getClass(), "class_type") // refers to the class type id of which the pointee is a member
+END_NODE_XML
+
+NODE_XML(ConstantArrayType, "ArrayType")
+ ID_ATTRIBUTE_XML
+ TYPE_ATTRIBUTE_XML(getElementType())
+ ATTRIBUTE_XML(getSize(), "size") // unsigned
+ ATTRIBUTE_ENUM_OPT_XML(getSizeModifier(), "size_modifier")
+ ENUM_XML(ArrayType::Normal, "")
+ ENUM_XML(ArrayType::Static, "static")
+ ENUM_XML(ArrayType::Star, "star")
+ END_ENUM_XML
+ ATTRIBUTE_OPT_XML(getIndexTypeQualifier(), "index_type_qualifier") // unsigned
+END_NODE_XML
+
+NODE_XML(IncompleteArrayType, "IncompleteArrayType")
+ ID_ATTRIBUTE_XML
+ TYPE_ATTRIBUTE_XML(getElementType())
+END_NODE_XML
+
+NODE_XML(VariableArrayType, "VariableArrayType")
+ ID_ATTRIBUTE_XML
+ TYPE_ATTRIBUTE_XML(getElementType())
+ // note: the size expression is print at the point of declaration
+END_NODE_XML
+
+NODE_XML(DependentSizedArrayType, "DependentSizedArrayType")
+ ID_ATTRIBUTE_XML
+ TYPE_ATTRIBUTE_XML(getElementType())
+ // FIXME: how to deal with size expression?
+END_NODE_XML
+
+NODE_XML(VectorType, "VectorType")
+ ID_ATTRIBUTE_XML
+ TYPE_ATTRIBUTE_XML(getElementType())
+ ATTRIBUTE_XML(getNumElements(), "size") // unsigned
+END_NODE_XML
+
+NODE_XML(ExtVectorType, "ExtVectorType")
+ ID_ATTRIBUTE_XML
+ TYPE_ATTRIBUTE_XML(getElementType())
+ ATTRIBUTE_XML(getNumElements(), "size") // unsigned
+END_NODE_XML
+
+NODE_XML(TypeOfExprType, "TypeOfExprType")
+ ID_ATTRIBUTE_XML
+ // note: the typeof expression is print at the point of use
+END_NODE_XML
+
+NODE_XML(TypeOfType, "TypeOfType")
+ ID_ATTRIBUTE_XML
+ TYPE_ATTRIBUTE_XML(getUnderlyingType())
+END_NODE_XML
+
+
+NODE_XML(RecordType, "Record")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_XML(getDecl()->getNameAsString(), "name") // string
+ ATTRIBUTE_ENUM_XML(getDecl()->getTagKind(), "kind")
+ ENUM_XML(TagDecl::TK_struct, "struct")
+ ENUM_XML(TagDecl::TK_union, "union")
+ ENUM_XML(TagDecl::TK_class, "class")
+ END_ENUM_XML
+ CONTEXT_ATTRIBUTE_XML(getDecl()->getDeclContext())
+END_NODE_XML
+
+NODE_XML(EnumType, "Enum")
+ ID_ATTRIBUTE_XML
+ ATTRIBUTE_XML(getDecl()->getNameAsString(), "name") // string
+ CONTEXT_ATTRIBUTE_XML(getDecl()->getDeclContext())
+END_NODE_XML
+
+NODE_XML(TemplateTypeParmType, "TemplateTypeParmType")
+ ID_ATTRIBUTE_XML
+END_NODE_XML
+
+NODE_XML(TemplateSpecializationType, "TemplateSpecializationType")
+ ID_ATTRIBUTE_XML
+END_NODE_XML
+
+NODE_XML(QualifiedNameType, "QualifiedNameType")
+ ID_ATTRIBUTE_XML
+ TYPE_ATTRIBUTE_XML(getNamedType())
+END_NODE_XML
+
+NODE_XML(TypenameType, "TypenameType")
+ ID_ATTRIBUTE_XML
+END_NODE_XML
+
+NODE_XML(ObjCInterfaceType, "ObjCInterfaceType")
+ ID_ATTRIBUTE_XML
+END_NODE_XML
+
+NODE_XML(ObjCQualifiedInterfaceType, "ObjCQualifiedInterfaceType")
+ ID_ATTRIBUTE_XML
+END_NODE_XML
+
+NODE_XML(ObjCObjectPointerType, "ObjCObjectPointerType")
+ ID_ATTRIBUTE_XML
+END_NODE_XML
+
+
+//===----------------------------------------------------------------------===//
+#undef NODE_XML
+#undef ID_ATTRIBUTE_XML
+#undef TYPE_ATTRIBUTE_XML
+#undef CONTEXT_ATTRIBUTE_XML
+#undef ATTRIBUTE_XML
+#undef ATTRIBUTE_OPT_XML
+#undef ATTRIBUTE_ENUM_XML
+#undef ATTRIBUTE_ENUM_OPT_XML
+#undef ENUM_XML
+#undef END_ENUM_XML
+#undef END_NODE_XML
diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h
index f1207e4f0f73..5b57521f6751 100644
--- a/include/clang/Parse/Action.h
+++ b/include/clang/Parse/Action.h
@@ -248,6 +248,19 @@ public:
virtual void ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
}
+ /// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse an
+ /// initializer for the declaration 'Dcl'.
+ /// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a
+ /// static data member of class X, names should be looked up in the scope of
+ /// class X.
+ virtual void ActOnCXXEnterDeclInitializer(Scope *S, DeclPtrTy Dcl) {
+ }
+
+ /// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an
+ /// initializer for the declaration 'Dcl'.
+ virtual void ActOnCXXExitDeclInitializer(Scope *S, DeclPtrTy Dcl) {
+ }
+
/// ActOnDeclarator - This callback is invoked when a declarator is parsed and
/// 'Init' specifies the initializer if any. This is for things like:
/// "int X = 4" or "typedef int foo".
@@ -624,6 +637,18 @@ public:
// Expression Parsing Callbacks.
//===--------------------------------------------------------------------===//
+ /// \brief Notifies the action when the parser is processing an unevaluated
+ /// operand.
+ ///
+ /// \param UnevaluatedOperand true to indicate that the parser is processing
+ /// an unevaluated operand, or false otherwise.
+ ///
+ /// \returns whether the the action module was previously in an unevaluated
+ /// operand.
+ virtual bool setUnevaluatedOperand(bool UnevaluatedOperand) {
+ return false;
+ }
+
// Primary Expressions.
/// \brief Retrieve the source range that corresponds to the given
@@ -907,6 +932,15 @@ public:
IdentifierInfo *Ident) {
return DeclPtrTy();
}
+
+ /// ActOnUsingDirective - This is called when using-directive is parsed.
+ virtual DeclPtrTy ActOnUsingDeclaration(Scope *CurScope,
+ SourceLocation UsingLoc,
+ const CXXScopeSpec &SS,
+ SourceLocation IdentLoc,
+ IdentifierInfo *TargetName,
+ AttributeList *AttrList,
+ bool IsTypeName);
/// ActOnParamDefaultArgument - Parse default argument for function parameter
virtual void ActOnParamDefaultArgument(DeclPtrTy param,
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index d613ae132935..75458d821e8e 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -105,6 +105,24 @@ class Parser {
}
};
+ /// \brief RAII object that enters an unevaluated operand.
+ class EnterUnevaluatedOperand {
+ /// \brief The action object.
+ Action &Actions;
+
+ /// \brief Whether we were previously within an unevaluated operand.
+ bool PreviouslyInUnevaluatedOperand;
+
+ public:
+ explicit EnterUnevaluatedOperand(Action &Actions) : Actions(Actions) {
+ PreviouslyInUnevaluatedOperand = Actions.setUnevaluatedOperand(true);
+ }
+
+ ~EnterUnevaluatedOperand() {
+ Actions.setUnevaluatedOperand(PreviouslyInUnevaluatedOperand);
+ }
+ };
+
public:
Parser(Preprocessor &PP, Action &Actions);
~Parser();
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 7ed9e45fcee9..b80142fef309 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -222,7 +222,7 @@ const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const {
unsigned ASTContext::getDeclAlignInBytes(const Decl *D) {
unsigned Align = Target.getCharWidth();
- if (const AlignedAttr* AA = D->getAttr<AlignedAttr>())
+ if (const AlignedAttr* AA = D->getAttr<AlignedAttr>(*this))
Align = std::max(Align, AA->getAlignment());
if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
@@ -369,7 +369,7 @@ ASTContext::getTypeInfo(const Type *T) {
// FIXME: Pointers into different addr spaces could have different sizes and
// alignment requirements: getPointerInfo should take an AddrSpace.
return getTypeInfo(QualType(cast<ExtQualType>(T)->getBaseType(), 0));
- case Type::ObjCQualifiedId:
+ case Type::ObjCObjectPointer:
case Type::ObjCQualifiedInterface:
Width = Target.getPointerWidth(0);
Align = Target.getPointerAlign(0);
@@ -445,7 +445,7 @@ ASTContext::getTypeInfo(const Type *T) {
case Type::Typedef: {
const TypedefDecl *Typedef = cast<TypedefType>(T)->getDecl();
- if (const AlignedAttr *Aligned = Typedef->getAttr<AlignedAttr>()) {
+ if (const AlignedAttr *Aligned = Typedef->getAttr<AlignedAttr>(*this)) {
Align = Aligned->getAlignment();
Width = getTypeSize(Typedef->getUnderlyingType().getTypePtr());
} else
@@ -505,7 +505,7 @@ void ASTRecordLayout::LayoutField(const FieldDecl *FD, unsigned FieldNo,
// FIXME: Should this override struct packing? Probably we want to
// take the minimum?
- if (const PackedAttr *PA = FD->getAttr<PackedAttr>())
+ if (const PackedAttr *PA = FD->getAttr<PackedAttr>(Context))
FieldPacking = PA->getAlignment();
if (const Expr *BitWidthExpr = FD->getBitWidth()) {
@@ -525,7 +525,7 @@ void ASTRecordLayout::LayoutField(const FieldDecl *FD, unsigned FieldNo,
FieldAlign = FieldInfo.second;
if (FieldPacking)
FieldAlign = std::min(FieldAlign, FieldPacking);
- if (const AlignedAttr *AA = FD->getAttr<AlignedAttr>())
+ if (const AlignedAttr *AA = FD->getAttr<AlignedAttr>(Context))
FieldAlign = std::max(FieldAlign, AA->getAlignment());
// Check if we need to add padding to give the field the correct
@@ -565,7 +565,7 @@ void ASTRecordLayout::LayoutField(const FieldDecl *FD, unsigned FieldNo,
// is smaller than the specified packing?
if (FieldPacking)
FieldAlign = std::min(FieldAlign, std::max(8U, FieldPacking));
- if (const AlignedAttr *AA = FD->getAttr<AlignedAttr>())
+ if (const AlignedAttr *AA = FD->getAttr<AlignedAttr>(Context))
FieldAlign = std::max(FieldAlign, AA->getAlignment());
// Round up the current record size to the field's alignment boundary.
@@ -731,10 +731,10 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D,
}
unsigned StructPacking = 0;
- if (const PackedAttr *PA = D->getAttr<PackedAttr>())
+ if (const PackedAttr *PA = D->getAttr<PackedAttr>(*this))
StructPacking = PA->getAlignment();
- if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
+ if (const AlignedAttr *AA = D->getAttr<AlignedAttr>(*this))
NewEntry->SetAlignment(std::max(NewEntry->getAlignment(),
AA->getAlignment()));
@@ -783,10 +783,10 @@ const ASTRecordLayout &ASTContext::getASTRecordLayout(const RecordDecl *D) {
bool IsUnion = D->isUnion();
unsigned StructPacking = 0;
- if (const PackedAttr *PA = D->getAttr<PackedAttr>())
+ if (const PackedAttr *PA = D->getAttr<PackedAttr>(*this))
StructPacking = PA->getAlignment();
- if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
+ if (const AlignedAttr *AA = D->getAttr<AlignedAttr>(*this))
NewEntry->SetAlignment(std::max(NewEntry->getAlignment(),
AA->getAlignment()));
@@ -1269,6 +1269,18 @@ QualType ASTContext::getExtVectorType(QualType vecType, unsigned NumElts) {
return QualType(New, 0);
}
+QualType ASTContext::getDependentSizedExtVectorType(QualType vecType,
+ Expr *SizeExpr,
+ SourceLocation AttrLoc) {
+ DependentSizedExtVectorType *New =
+ new (*this,8) DependentSizedExtVectorType(vecType, QualType(),
+ SizeExpr, AttrLoc);
+
+ DependentSizedExtVectorTypes.push_back(New);
+ Types.push_back(New);
+ return QualType(New, 0);
+}
+
/// getFunctionNoProtoType - Return a K&R style C function type like 'int()'.
///
QualType ASTContext::getFunctionNoProtoType(QualType ResultTy) {
@@ -1414,11 +1426,13 @@ QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl) {
}
/// \brief Retrieve the template type parameter type for a template
-/// parameter with the given depth, index, and (optionally) name.
+/// parameter or parameter pack with the given depth, index, and (optionally)
+/// name.
QualType ASTContext::getTemplateTypeParmType(unsigned Depth, unsigned Index,
+ bool ParameterPack,
IdentifierInfo *Name) {
llvm::FoldingSetNodeID ID;
- TemplateTypeParmType::Profile(ID, Depth, Index, Name);
+ TemplateTypeParmType::Profile(ID, Depth, Index, ParameterPack, Name);
void *InsertPos = 0;
TemplateTypeParmType *TypeParm
= TemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos);
@@ -1426,11 +1440,12 @@ QualType ASTContext::getTemplateTypeParmType(unsigned Depth, unsigned Index,
if (TypeParm)
return QualType(TypeParm, 0);
- if (Name)
- TypeParm = new (*this, 8) TemplateTypeParmType(Depth, Index, Name,
- getTemplateTypeParmType(Depth, Index));
- else
- TypeParm = new (*this, 8) TemplateTypeParmType(Depth, Index);
+ if (Name) {
+ QualType Canon = getTemplateTypeParmType(Depth, Index, ParameterPack);
+ TypeParm = new (*this, 8) TemplateTypeParmType(Depth, Index, ParameterPack,
+ Name, Canon);
+ } else
+ TypeParm = new (*this, 8) TemplateTypeParmType(Depth, Index, ParameterPack);
Types.push_back(TypeParm);
TemplateTypeParmTypes.InsertNode(TypeParm, InsertPos);
@@ -1563,6 +1578,31 @@ static void SortAndUniqueProtocols(ObjCProtocolDecl **&Protocols,
NumProtocols = ProtocolsEnd-Protocols;
}
+/// getObjCObjectPointerType - Return a ObjCObjectPointerType type for
+/// the given interface decl and the conforming protocol list.
+QualType ASTContext::getObjCObjectPointerType(ObjCInterfaceDecl *Decl,
+ ObjCProtocolDecl **Protocols,
+ unsigned NumProtocols) {
+ // Sort the protocol list alphabetically to canonicalize it.
+ if (NumProtocols)
+ SortAndUniqueProtocols(Protocols, NumProtocols);
+
+ llvm::FoldingSetNodeID ID;
+ ObjCObjectPointerType::Profile(ID, Decl, Protocols, NumProtocols);
+
+ void *InsertPos = 0;
+ if (ObjCObjectPointerType *QT =
+ ObjCObjectPointerTypes.FindNodeOrInsertPos(ID, InsertPos))
+ return QualType(QT, 0);
+
+ // No Match;
+ ObjCObjectPointerType *QType =
+ new (*this,8) ObjCObjectPointerType(Decl, Protocols, NumProtocols);
+
+ Types.push_back(QType);
+ ObjCObjectPointerTypes.InsertNode(QType, InsertPos);
+ return QualType(QType, 0);
+}
/// getObjCQualifiedInterfaceType - Return a ObjCQualifiedInterfaceType type for
/// the given interface decl and the conforming protocol list.
@@ -1592,23 +1632,7 @@ QualType ASTContext::getObjCQualifiedInterfaceType(ObjCInterfaceDecl *Decl,
/// and the conforming protocol list.
QualType ASTContext::getObjCQualifiedIdType(ObjCProtocolDecl **Protocols,
unsigned NumProtocols) {
- // Sort the protocol list alphabetically to canonicalize it.
- SortAndUniqueProtocols(Protocols, NumProtocols);
-
- llvm::FoldingSetNodeID ID;
- ObjCQualifiedIdType::Profile(ID, Protocols, NumProtocols);
-
- void *InsertPos = 0;
- if (ObjCQualifiedIdType *QT =
- ObjCQualifiedIdTypes.FindNodeOrInsertPos(ID, InsertPos))
- return QualType(QT, 0);
-
- // No Match;
- ObjCQualifiedIdType *QType =
- new (*this,8) ObjCQualifiedIdType(Protocols, NumProtocols);
- Types.push_back(QType);
- ObjCQualifiedIdTypes.InsertNode(QType, InsertPos);
- return QualType(QType, 0);
+ return getObjCObjectPointerType(0, Protocols, NumProtocols);
}
/// getTypeOfExprType - Unlike many "get<Type>" functions, we can't unique
@@ -2398,9 +2422,9 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
if (FD || EncodingProperty) {
// Note that we do extended encoding of protocol qualifer list
// Only when doing ivar or property encoding.
- const ObjCQualifiedIdType *QIDT = T->getAsObjCQualifiedIdType();
+ const ObjCObjectPointerType *QIDT = T->getAsObjCQualifiedIdType();
S += '"';
- for (ObjCQualifiedIdType::qual_iterator I = QIDT->qual_begin(),
+ for (ObjCObjectPointerType::qual_iterator I = QIDT->qual_begin(),
E = QIDT->qual_end(); I != E; ++I) {
S += '<';
S += (*I)->getNameAsString();
@@ -2758,7 +2782,7 @@ QualType ASTContext::getFromTargetType(unsigned Type) const {
bool ASTContext::isObjCNSObjectType(QualType Ty) const {
if (TypedefType *TDT = dyn_cast<TypedefType>(Ty)) {
if (TypedefDecl *TD = TDT->getDecl())
- if (TD->getAttr<ObjCNSObjectAttr>())
+ if (TD->getAttr<ObjCNSObjectAttr>(*const_cast<ASTContext*>(this)))
return true;
}
return false;
@@ -3283,7 +3307,8 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) {
return QualType();
}
- case Type::ObjCQualifiedId:
+ case Type::ObjCObjectPointer:
+ // FIXME: finish
// Distinct qualified id's are not compatible.
return QualType();
case Type::FixedWidthInt:
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index a3e406b2452e..bf63932011a2 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -315,6 +315,12 @@ void VarDecl::Destroy(ASTContext& C) {
VarDecl::~VarDecl() {
}
+SourceRange VarDecl::getSourceRange() const {
+ if (getInit())
+ return SourceRange(getLocation(), getInit()->getLocEnd());
+ return SourceRange(getLocation(), getLocation());
+}
+
bool VarDecl::isTentativeDefinition(ASTContext &Context) const {
if (!isFileVarDecl() || Context.getLangOptions().CPlusPlus)
return false;
@@ -371,6 +377,12 @@ Stmt *FunctionDecl::getBodyIfAvailable() const {
return 0;
}
+void FunctionDecl::setBody(Stmt *B) {
+ Body = B;
+ if (B && EndRangeLoc < B->getLocEnd())
+ EndRangeLoc = B->getLocEnd();
+}
+
bool FunctionDecl::isMain() const {
return getDeclContext()->getLookupContext()->isTranslationUnit() &&
getIdentifier() && getIdentifier()->isStr("main");
@@ -380,13 +392,14 @@ bool FunctionDecl::isExternC(ASTContext &Context) const {
// In C, any non-static, non-overloadable function has external
// linkage.
if (!Context.getLangOptions().CPlusPlus)
- return getStorageClass() != Static && !getAttr<OverloadableAttr>();
+ return getStorageClass() != Static && !getAttr<OverloadableAttr>(Context);
for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit();
DC = DC->getParent()) {
if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) {
if (Linkage->getLanguage() == LinkageSpecDecl::lang_c)
- return getStorageClass() != Static && !getAttr<OverloadableAttr>();
+ return getStorageClass() != Static &&
+ !getAttr<OverloadableAttr>(Context);
break;
}
@@ -451,7 +464,7 @@ unsigned FunctionDecl::getBuiltinID(ASTContext &Context) const {
if (isa<LinkageSpecDecl>(getDeclContext()) &&
cast<LinkageSpecDecl>(getDeclContext())->getLanguage()
== LinkageSpecDecl::lang_c &&
- !getAttr<OverloadableAttr>())
+ !getAttr<OverloadableAttr>(Context))
return BuiltinID;
// Not a builtin
@@ -480,6 +493,10 @@ void FunctionDecl::setParams(ASTContext& C, ParmVarDecl **NewParamInfo,
void *Mem = C.Allocate(sizeof(ParmVarDecl*)*NumParams);
ParamInfo = new (Mem) ParmVarDecl*[NumParams];
memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams);
+
+ // Update source range.
+ if (EndRangeLoc < NewParamInfo[NumParams-1]->getLocEnd())
+ EndRangeLoc = NewParamInfo[NumParams-1]->getLocEnd();
}
}
@@ -496,25 +513,25 @@ unsigned FunctionDecl::getMinRequiredArguments() const {
return NumRequiredArgs;
}
-bool FunctionDecl::hasActiveGNUInlineAttribute() const {
- if (!isInline() || !hasAttr<GNUInlineAttr>())
+bool FunctionDecl::hasActiveGNUInlineAttribute(ASTContext &Context) const {
+ if (!isInline() || !hasAttr<GNUInlineAttr>(Context))
return false;
for (const FunctionDecl *FD = getPreviousDeclaration(); FD;
FD = FD->getPreviousDeclaration()) {
- if (FD->isInline() && !FD->hasAttr<GNUInlineAttr>())
+ if (FD->isInline() && !FD->hasAttr<GNUInlineAttr>(Context))
return false;
}
return true;
}
-bool FunctionDecl::isExternGNUInline() const {
- if (!hasActiveGNUInlineAttribute())
+bool FunctionDecl::isExternGNUInline(ASTContext &Context) const {
+ if (!hasActiveGNUInlineAttribute(Context))
return false;
for (const FunctionDecl *FD = this; FD; FD = FD->getPreviousDeclaration())
- if (FD->getStorageClass() == Extern && FD->hasAttr<GNUInlineAttr>())
+ if (FD->getStorageClass() == Extern && FD->hasAttr<GNUInlineAttr>(Context))
return true;
return false;
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index a39a506de0ae..02e71d7a8681 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -38,12 +38,6 @@ using namespace clang;
static bool StatSwitch = false;
-// This keeps track of all decl attributes. Since so few decls have attrs, we
-// keep them in a hash map instead of wasting space in the Decl class.
-typedef llvm::DenseMap<const Decl*, Attr*> DeclAttrMapTy;
-
-static DeclAttrMapTy *DeclAttrs = 0;
-
const char *Decl::getDeclKindName() const {
switch (DeclKind) {
default: assert(0 && "Declaration not in DeclNodes.def!");
@@ -170,6 +164,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case ParmVar:
case OriginalParmVar:
case NonTypeTemplateParm:
+ case Using:
case ObjCMethod:
case ObjCContainer:
case ObjCCategory:
@@ -224,11 +219,8 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
}
}
-void Decl::addAttr(Attr *NewAttr) {
- if (!DeclAttrs)
- DeclAttrs = new DeclAttrMapTy();
-
- Attr *&ExistingAttr = (*DeclAttrs)[this];
+void Decl::addAttr(ASTContext &Context, Attr *NewAttr) {
+ Attr *&ExistingAttr = Context.getDeclAttrs(this);
NewAttr->setNext(ExistingAttr);
ExistingAttr = NewAttr;
@@ -236,25 +228,19 @@ void Decl::addAttr(Attr *NewAttr) {
HasAttrs = true;
}
-void Decl::invalidateAttrs() {
+void Decl::invalidateAttrs(ASTContext &Context) {
if (!HasAttrs) return;
-
+
HasAttrs = false;
- (*DeclAttrs)[this] = 0;
- DeclAttrs->erase(this);
-
- if (DeclAttrs->empty()) {
- delete DeclAttrs;
- DeclAttrs = 0;
- }
+ Context.eraseDeclAttrs(this);
}
-const Attr *Decl::getAttrsImpl() const {
+const Attr *Decl::getAttrsImpl(ASTContext &Context) const {
assert(HasAttrs && "getAttrs() should verify this!");
- return (*DeclAttrs)[this];
+ return Context.getDeclAttrs(this);
}
-void Decl::swapAttrs(Decl *RHS) {
+void Decl::swapAttrs(ASTContext &Context, Decl *RHS) {
bool HasLHSAttr = this->HasAttrs;
bool HasRHSAttr = RHS->HasAttrs;
@@ -263,17 +249,17 @@ void Decl::swapAttrs(Decl *RHS) {
// If 'this' has no attrs, swap the other way.
if (!HasLHSAttr)
- return RHS->swapAttrs(this);
+ return RHS->swapAttrs(Context, this);
// Handle the case when both decls have attrs.
if (HasRHSAttr) {
- std::swap((*DeclAttrs)[this], (*DeclAttrs)[RHS]);
+ std::swap(Context.getDeclAttrs(this), Context.getDeclAttrs(RHS));
return;
}
// Otherwise, LHS has an attr and RHS doesn't.
- (*DeclAttrs)[RHS] = (*DeclAttrs)[this];
- (*DeclAttrs).erase(this);
+ Context.getDeclAttrs(RHS) = Context.getDeclAttrs(this);
+ Context.eraseDeclAttrs(this);
this->HasAttrs = false;
RHS->HasAttrs = true;
}
@@ -282,12 +268,8 @@ void Decl::swapAttrs(Decl *RHS) {
void Decl::Destroy(ASTContext &C) {
// Free attributes for this decl.
if (HasAttrs) {
- DeclAttrMapTy::iterator it = DeclAttrs->find(this);
- assert(it != DeclAttrs->end() && "No attrs found but HasAttrs is true!");
-
- // release attributes.
- it->second->Destroy(C);
- invalidateAttrs();
+ C.getDeclAttrs(this)->Destroy(C);
+ invalidateAttrs(C);
HasAttrs = false;
}
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 8430da2be6b1..7a930d78c123 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -128,36 +128,33 @@ bool CXXRecordDecl::hasConstCopyAssignment(ASTContext &Context) const {
void
CXXRecordDecl::addedConstructor(ASTContext &Context,
CXXConstructorDecl *ConDecl) {
- if (!ConDecl->isImplicit()) {
- // Note that we have a user-declared constructor.
- UserDeclaredConstructor = true;
-
- // C++ [dcl.init.aggr]p1:
- // An aggregate is an array or a class (clause 9) with no
- // user-declared constructors (12.1) [...].
- Aggregate = false;
-
- // C++ [class]p4:
- // A POD-struct is an aggregate class [...]
- PlainOldData = false;
-
- // C++ [class.ctor]p5:
- // A constructor is trivial if it is an implicitly-declared default
- // constructor.
- HasTrivialConstructor = false;
+ assert(!ConDecl->isImplicit() && "addedConstructor - not for implicit decl");
+ // Note that we have a user-declared constructor.
+ UserDeclaredConstructor = true;
+
+ // C++ [dcl.init.aggr]p1:
+ // An aggregate is an array or a class (clause 9) with no
+ // user-declared constructors (12.1) [...].
+ Aggregate = false;
+
+ // C++ [class]p4:
+ // A POD-struct is an aggregate class [...]
+ PlainOldData = false;
+
+ // C++ [class.ctor]p5:
+ // A constructor is trivial if it is an implicitly-declared default
+ // constructor.
+ HasTrivialConstructor = false;
- // Note when we have a user-declared copy constructor, which will
- // suppress the implicit declaration of a copy constructor.
- if (ConDecl->isCopyConstructor(Context))
- UserDeclaredCopyConstructor = true;
- }
+ // Note when we have a user-declared copy constructor, which will
+ // suppress the implicit declaration of a copy constructor.
+ if (ConDecl->isCopyConstructor(Context))
+ UserDeclaredCopyConstructor = true;
}
void CXXRecordDecl::addedAssignmentOperator(ASTContext &Context,
CXXMethodDecl *OpDecl) {
// We're interested specifically in copy assignment operators.
- // Unlike addedConstructor, this method is not called for implicit
- // declarations.
const FunctionProtoType *FnType = OpDecl->getType()->getAsFunctionProtoType();
assert(FnType && "Overloaded operator has no proto function type.");
assert(FnType->getNumArgs() == 1 && !FnType->isVariadic());
@@ -187,10 +184,28 @@ void CXXRecordDecl::addConversionFunction(ASTContext &Context,
Conversions.addOverload(ConvDecl);
}
+
+CXXConstructorDecl *
+CXXRecordDecl::getDefaultConstructor(ASTContext &Context) {
+ QualType ClassType = Context.getTypeDeclType(this);
+ DeclarationName ConstructorName
+ = Context.DeclarationNames.getCXXConstructorName(
+ Context.getCanonicalType(ClassType.getUnqualifiedType()));
+
+ DeclContext::lookup_const_iterator Con, ConEnd;
+ for (llvm::tie(Con, ConEnd) = lookup(Context, ConstructorName);
+ Con != ConEnd; ++Con) {
+ CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
+ if (Constructor->isDefaultConstructor())
+ return Constructor;
+ }
+ return 0;
+}
+
const CXXDestructorDecl *
CXXRecordDecl::getDestructor(ASTContext &Context) {
QualType ClassType = Context.getTypeDeclType(this);
-
+
DeclarationName Name
= Context.DeclarationNames.getCXXDestructorName(ClassType);
@@ -428,6 +443,14 @@ NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC,
Qualifier, IdentLoc, Namespace);
}
+UsingDecl *UsingDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, SourceRange NNR, SourceLocation TargetNL,
+ SourceLocation UL, NamedDecl* Target,
+ NestedNameSpecifier* TargetNNS, bool IsTypeNameArg) {
+ return new (C) UsingDecl(DC, L, NNR, TargetNL, UL, Target,
+ TargetNNS, IsTypeNameArg);
+}
+
StaticAssertDecl *StaticAssertDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L, Expr *AssertExpr,
StringLiteral *Message) {
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index 5b1bf9b3afc5..23c26378757f 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -190,7 +190,7 @@ TemplateTypeParmDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L, unsigned D, unsigned P,
IdentifierInfo *Id, bool Typename,
bool ParameterPack) {
- QualType Type = C.getTemplateTypeParmType(D, P, Id);
+ QualType Type = C.getTemplateTypeParmType(D, P, ParameterPack, Id);
return new (C) TemplateTypeParmDecl(DC, L, Id, Typename, Type, ParameterPack);
}
@@ -238,6 +238,22 @@ TemplateArgument::TemplateArgument(Expr *E) : Kind(Expression) {
StartLoc = E->getSourceRange().getBegin();
}
+/// \brief Construct a template argument pack.
+TemplateArgument::TemplateArgument(SourceLocation Loc, TemplateArgument *args,
+ unsigned NumArgs, bool CopyArgs)
+ : Kind(Pack) {
+ Args.NumArgs = NumArgs;
+ Args.CopyArgs = CopyArgs;
+ if (!Args.CopyArgs) {
+ Args.Args = args;
+ return;
+ }
+
+ Args.Args = new TemplateArgument[NumArgs];
+ for (unsigned I = 0; I != NumArgs; ++I)
+ Args.Args[I] = args[I];
+}
+
//===----------------------------------------------------------------------===//
// TemplateArgumentListBuilder Implementation
//===----------------------------------------------------------------------===//
@@ -249,25 +265,28 @@ void TemplateArgumentListBuilder::push_back(const TemplateArgument& Arg) {
break;
}
- if (!isAddingFromParameterPack()) {
- // Add begin and end indicies.
- Indices.push_back(Args.size());
- Indices.push_back(Args.size());
- }
-
- Args.push_back(Arg);
+ FlatArgs.push_back(Arg);
+
+ if (!isAddingFromParameterPack())
+ StructuredArgs.push_back(Arg);
}
void TemplateArgumentListBuilder::BeginParameterPack() {
assert(!isAddingFromParameterPack() && "Already adding to parameter pack!");
-
- Indices.push_back(Args.size());
+
+ PackBeginIndex = FlatArgs.size();
}
void TemplateArgumentListBuilder::EndParameterPack() {
assert(isAddingFromParameterPack() && "Not adding to parameter pack!");
+
+ unsigned NumArgs = FlatArgs.size() - PackBeginIndex;
+ TemplateArgument *Args = NumArgs ? &FlatArgs[PackBeginIndex] : 0;
+
+ StructuredArgs.push_back(TemplateArgument(SourceLocation(), Args, NumArgs,
+ /*CopyArgs=*/false));
- Indices.push_back(Args.size());
+ PackBeginIndex = std::numeric_limits<unsigned>::max();
}
//===----------------------------------------------------------------------===//
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 309be4175ffa..4a3ad2641ef4 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -456,7 +456,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 &Context) const {
// Don't warn if the expr is type dependent. The type could end up
// instantiating to void.
if (isTypeDependent())
@@ -469,7 +469,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, Context);
case UnaryOperatorClass: {
const UnaryOperator *UO = cast<UnaryOperator>(this);
@@ -492,7 +492,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
return false;
break;
case UnaryOperator::Extension:
- return UO->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2);
+ return UO->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Context);
}
Loc = UO->getOperatorLoc();
R1 = UO->getSubExpr()->getSourceRange();
@@ -502,8 +502,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, Context) ||
+ BO->getLHS()->isUnusedResultAWarning(Loc, R1, R2, Context);
if (BO->isAssignmentOp())
return false;
@@ -519,9 +519,10 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
// The condition must be evaluated, but if either the LHS or RHS is a
// warning, warn about them.
const ConditionalOperator *Exp = cast<ConditionalOperator>(this);
- if (Exp->getLHS() && Exp->getLHS()->isUnusedResultAWarning(Loc, R1, R2))
+ if (Exp->getLHS() &&
+ Exp->getLHS()->isUnusedResultAWarning(Loc, R1, R2, Context))
return true;
- return Exp->getRHS()->isUnusedResultAWarning(Loc, R1, R2);
+ return Exp->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Context);
}
case MemberExprClass:
@@ -554,8 +555,8 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
// If the callee has attribute pure, const, or warn_unused_result, warn
// about it. void foo() { strlen("bar"); } should warn.
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CalleeDRE->getDecl()))
- if (FD->getAttr<WarnUnusedResultAttr>() ||
- FD->getAttr<PureAttr>() || FD->getAttr<ConstAttr>()) {
+ if (FD->getAttr<WarnUnusedResultAttr>(Context) ||
+ FD->getAttr<PureAttr>(Context) || FD->getAttr<ConstAttr>(Context)) {
Loc = CE->getCallee()->getLocStart();
R1 = CE->getCallee()->getSourceRange();
@@ -578,7 +579,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, Context);
Loc = cast<StmtExpr>(this)->getLParenLoc();
R1 = getSourceRange();
@@ -588,8 +589,8 @@ 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, Context);
Loc = cast<CStyleCastExpr>(this)->getLParenLoc();
R1 = cast<CStyleCastExpr>(this)->getSubExpr()->getSourceRange();
return true;
@@ -597,8 +598,8 @@ 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, Context);
Loc = cast<CXXFunctionalCastExpr>(this)->getTypeBeginLoc();
R1 = cast<CXXFunctionalCastExpr>(this)->getSubExpr()->getSourceRange();
return true;
@@ -606,11 +607,11 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
case ImplicitCastExprClass:
// Check the operand, since implicit casts are inserted by Sema
return cast<ImplicitCastExpr>(this)
- ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2);
+ ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Context);
case CXXDefaultArgExprClass:
return cast<CXXDefaultArgExpr>(this)
- ->getExpr()->isUnusedResultAWarning(Loc, R1, R2);
+ ->getExpr()->isUnusedResultAWarning(Loc, R1, R2, Context);
case CXXNewExprClass:
// FIXME: In theory, there might be new expressions that don't have side
@@ -619,7 +620,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
return false;
case CXXExprWithTemporariesClass:
return cast<CXXExprWithTemporaries>(this)
- ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2);
+ ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Context);
}
}
@@ -1570,7 +1571,7 @@ ObjCSelectorExpr *ObjCSelectorExpr::Clone(ASTContext &C) const {
}
ObjCProtocolExpr *ObjCProtocolExpr::Clone(ASTContext &C) const {
- return new (C) ObjCProtocolExpr(getType(), Protocol, AtLoc, RParenLoc);
+ return new (C) ObjCProtocolExpr(getType(), TheProtocol, AtLoc, RParenLoc);
}
// constructor for class messages.
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index 8fd66a29817d..18c0f77ab29e 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -306,10 +306,11 @@ void CXXConstructExpr::Destroy(ASTContext &C) {
CXXExprWithTemporaries::CXXExprWithTemporaries(Expr *subexpr,
CXXTemporary **temps,
unsigned numtemps,
- bool destroytemps)
+ bool shoulddestroytemps)
: Expr(CXXExprWithTemporariesClass, subexpr->getType(),
subexpr->isTypeDependent(), subexpr->isValueDependent()),
- SubExpr(subexpr), Temps(0), NumTemps(numtemps), DestroyTemps(destroytemps) {
+ SubExpr(subexpr), Temps(0), NumTemps(numtemps),
+ ShouldDestroyTemps(shoulddestroytemps) {
if (NumTemps > 0) {
Temps = new CXXTemporary*[NumTemps];
for (unsigned i = 0; i < NumTemps; ++i)
@@ -321,9 +322,9 @@ CXXExprWithTemporaries *CXXExprWithTemporaries::Create(ASTContext &C,
Expr *SubExpr,
CXXTemporary **Temps,
unsigned NumTemps,
- bool DestroyTemps) {
+ bool ShouldDestroyTemps){
return new (C) CXXExprWithTemporaries(SubExpr, Temps, NumTemps,
- DestroyTemps);
+ ShouldDestroyTemps);
}
void CXXExprWithTemporaries::Destroy(ASTContext &C) {
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 710da6386133..b300940824de 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -643,7 +643,8 @@ void StmtPrinter::VisitUnaryOperator(UnaryOperator *Node) {
if (!Node->isPostfix()) {
OS << UnaryOperator::getOpcodeStr(Node->getOpcode());
- // Print a space if this is an "identifier operator" like __real.
+ // Print a space if this is an "identifier operator" like __real, or if
+ // it might be concatenated incorrectly like '+'.
switch (Node->getOpcode()) {
default: break;
case UnaryOperator::Real:
@@ -651,6 +652,11 @@ void StmtPrinter::VisitUnaryOperator(UnaryOperator *Node) {
case UnaryOperator::Extension:
OS << ' ';
break;
+ case UnaryOperator::Plus:
+ case UnaryOperator::Minus:
+ if (isa<UnaryOperator>(Node->getSubExpr()))
+ OS << ' ';
+ break;
}
}
PrintExpr(Node->getSubExpr());
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index e304f5422636..7b45b21e5d0c 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -50,6 +50,13 @@ void DependentSizedArrayType::Destroy(ASTContext& C) {
C.Deallocate(this);
}
+void DependentSizedExtVectorType::Destroy(ASTContext& C) {
+ if (SizeExpr)
+ SizeExpr->Destroy(C);
+ this->~DependentSizedExtVectorType();
+ C.Deallocate(this);
+}
+
/// getArrayElementTypeNoTypeQual - If this is an array type, return the
/// element type of the array, potentially with type qualifiers missing.
/// This method should never be used when type qualifiers are meaningful.
@@ -555,6 +562,12 @@ const ObjCInterfaceType *Type::getAsObjCInterfaceType() const {
return dyn_cast<ObjCInterfaceType>(CanonicalType.getUnqualifiedType());
}
+const ObjCObjectPointerType *Type::getAsObjCObjectPointerType() const {
+ // There is no sugar for ObjCObjectPointerType's, just return the
+ // canonical type pointer if it is the right class.
+ return dyn_cast<ObjCObjectPointerType>(CanonicalType.getUnqualifiedType());
+}
+
const ObjCQualifiedInterfaceType *
Type::getAsObjCQualifiedInterfaceType() const {
// There is no sugar for ObjCQualifiedInterfaceType's, just return the
@@ -562,10 +575,14 @@ Type::getAsObjCQualifiedInterfaceType() const {
return dyn_cast<ObjCQualifiedInterfaceType>(CanonicalType.getUnqualifiedType());
}
-const ObjCQualifiedIdType *Type::getAsObjCQualifiedIdType() const {
+const ObjCObjectPointerType *Type::getAsObjCQualifiedIdType() const {
// There is no sugar for ObjCQualifiedIdType's, just return the canonical
// type pointer if it is the right class.
- return dyn_cast<ObjCQualifiedIdType>(CanonicalType.getUnqualifiedType());
+ if (const ObjCObjectPointerType *OPT = getAsObjCObjectPointerType()) {
+ if (OPT->isObjCQualifiedIdType())
+ return OPT;
+ }
+ return 0;
}
const TemplateTypeParmType *Type::getAsTemplateTypeParmType() const {
@@ -770,7 +787,7 @@ bool Type::isScalarType() const {
isa<BlockPointerType>(CanonicalType) ||
isa<MemberPointerType>(CanonicalType) ||
isa<ComplexType>(CanonicalType) ||
- isa<ObjCQualifiedIdType>(CanonicalType);
+ isa<ObjCObjectPointerType>(CanonicalType);
}
/// \brief Determines whether the type is a C++ aggregate type or C
@@ -857,7 +874,7 @@ bool Type::isPODType() const {
case MemberPointer:
case Vector:
case ExtVector:
- case ObjCQualifiedId:
+ case ObjCObjectPointer:
return true;
case Enum:
@@ -912,7 +929,7 @@ bool Type::isSpecifierType() const {
case Typename:
case ObjCInterface:
case ObjCQualifiedInterface:
- case ObjCQualifiedId:
+ case ObjCObjectPointer:
return true;
default:
return false;
@@ -973,28 +990,30 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID) {
getNumExceptions(), exception_begin());
}
-void ObjCQualifiedInterfaceType::Profile(llvm::FoldingSetNodeID &ID,
- const ObjCInterfaceDecl *Decl,
- ObjCProtocolDecl **protocols,
- unsigned NumProtocols) {
+void ObjCObjectPointerType::Profile(llvm::FoldingSetNodeID &ID,
+ const ObjCInterfaceDecl *Decl,
+ ObjCProtocolDecl **protocols,
+ unsigned NumProtocols) {
ID.AddPointer(Decl);
for (unsigned i = 0; i != NumProtocols; i++)
ID.AddPointer(protocols[i]);
}
-void ObjCQualifiedInterfaceType::Profile(llvm::FoldingSetNodeID &ID) {
+void ObjCObjectPointerType::Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getDecl(), &Protocols[0], getNumProtocols());
}
-void ObjCQualifiedIdType::Profile(llvm::FoldingSetNodeID &ID,
- ObjCProtocolDecl **protocols,
- unsigned NumProtocols) {
+void ObjCQualifiedInterfaceType::Profile(llvm::FoldingSetNodeID &ID,
+ const ObjCInterfaceDecl *Decl,
+ ObjCProtocolDecl **protocols,
+ unsigned NumProtocols) {
+ ID.AddPointer(Decl);
for (unsigned i = 0; i != NumProtocols; i++)
ID.AddPointer(protocols[i]);
}
-void ObjCQualifiedIdType::Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, &Protocols[0], getNumProtocols());
+void ObjCQualifiedInterfaceType::Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getDecl(), &Protocols[0], getNumProtocols());
}
/// LookThroughTypedefs - Return the ultimate type this typedef corresponds to
@@ -1068,6 +1087,10 @@ anyDependentTemplateArguments(const TemplateArgument *Args, unsigned NumArgs) {
Args[Idx].getAsExpr()->isValueDependent())
return true;
break;
+
+ case TemplateArgument::Pack:
+ assert(0 && "FIXME: Implement!");
+ break;
}
}
@@ -1352,6 +1375,19 @@ void DependentSizedArrayType::getAsStringInternal(std::string &S, const Printing
getElementType().getAsStringInternal(S, Policy);
}
+void DependentSizedExtVectorType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
+ getElementType().getAsStringInternal(S, Policy);
+
+ S += " __attribute__((ext_vector_type(";
+ if (getSizeExpr()) {
+ std::string SStr;
+ llvm::raw_string_ostream s(SStr);
+ getSizeExpr()->printPretty(s, 0, Policy);
+ S += s.str();
+ }
+ S += ")))";
+}
+
void VectorType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {
// FIXME: We prefer to print the size directly here, but have no way
// to get the size of the type.
@@ -1476,6 +1512,9 @@ TemplateSpecializationType::PrintTemplateArgumentList(
Args[Arg].getAsExpr()->printPretty(s, 0, Policy);
break;
}
+ case TemplateArgument::Pack:
+ assert(0 && "FIXME: Implement!");
+ break;
}
// If this is the first argument and its string representation
@@ -1566,6 +1605,30 @@ void ObjCInterfaceType::getAsStringInternal(std::string &InnerString, const Prin
InnerString = getDecl()->getIdentifier()->getName() + InnerString;
}
+void ObjCObjectPointerType::getAsStringInternal(std::string &InnerString,
+ const PrintingPolicy &Policy) const {
+ if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'.
+ InnerString = ' ' + InnerString;
+
+ std::string ObjCQIString;
+
+ if (getDecl())
+ ObjCQIString = getDecl()->getNameAsString();
+ else
+ ObjCQIString = "id";
+
+ if (!qual_empty()) {
+ ObjCQIString += '<';
+ for (qual_iterator I = qual_begin(), E = qual_end(); I != E; ++I) {
+ ObjCQIString += (*I)->getNameAsString();
+ if (I+1 != E)
+ ObjCQIString += ',';
+ }
+ ObjCQIString += '>';
+ }
+ InnerString = ObjCQIString + InnerString;
+}
+
void
ObjCQualifiedInterfaceType::getAsStringInternal(std::string &InnerString,
const PrintingPolicy &Policy) const {
@@ -1585,20 +1648,6 @@ ObjCQualifiedInterfaceType::getAsStringInternal(std::string &InnerString,
InnerString = ObjCQIString + InnerString;
}
-void ObjCQualifiedIdType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const {
- if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'.
- InnerString = ' ' + InnerString;
- std::string ObjCQIString = "id";
- ObjCQIString += '<';
- for (qual_iterator I = qual_begin(), E = qual_end(); I != E; ++I) {
- ObjCQIString += (*I)->getNameAsString();
- if (I+1 != E)
- ObjCQIString += ',';
- }
- ObjCQIString += '>';
- InnerString = ObjCQIString + InnerString;
-}
-
void TagType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const {
if (Policy.SuppressTag)
return;
diff --git a/lib/Analysis/BasicConstraintManager.cpp b/lib/Analysis/BasicConstraintManager.cpp
index b2722141d955..ffa8a8625bdf 100644
--- a/lib/Analysis/BasicConstraintManager.cpp
+++ b/lib/Analysis/BasicConstraintManager.cpp
@@ -51,39 +51,39 @@ class VISIBILITY_HIDDEN BasicConstraintManager
GRState::IntSetTy::Factory ISetFactory;
public:
BasicConstraintManager(GRStateManager& statemgr)
- : SimpleConstraintManager(statemgr), ISetFactory(statemgr.getAllocator()) {}
+ : ISetFactory(statemgr.getAllocator()) {}
- const GRState* AssumeSymNE(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible);
+ const GRState* AssumeSymNE(const GRState* state, SymbolRef sym,
+ const llvm::APSInt& V);
- const GRState* AssumeSymEQ(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible);
+ const GRState* AssumeSymEQ(const GRState* state, SymbolRef sym,
+ const llvm::APSInt& V);
- const GRState* AssumeSymLT(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible);
+ const GRState* AssumeSymLT(const GRState* state, SymbolRef sym,
+ const llvm::APSInt& V);
- const GRState* AssumeSymGT(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible);
+ const GRState* AssumeSymGT(const GRState* state, SymbolRef sym,
+ const llvm::APSInt& V);
- const GRState* AssumeSymGE(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible);
+ const GRState* AssumeSymGE(const GRState* state, SymbolRef sym,
+ const llvm::APSInt& V);
- const GRState* AssumeSymLE(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible);
+ const GRState* AssumeSymLE(const GRState* state, SymbolRef sym,
+ const llvm::APSInt& V);
- const GRState* AddEQ(const GRState* St, SymbolRef sym, const llvm::APSInt& V);
+ const GRState* AddEQ(const GRState* state, SymbolRef sym, const llvm::APSInt& V);
- const GRState* AddNE(const GRState* St, SymbolRef sym, const llvm::APSInt& V);
+ const GRState* AddNE(const GRState* state, SymbolRef sym, const llvm::APSInt& V);
- const llvm::APSInt* getSymVal(const GRState* St, SymbolRef sym) const;
- bool isNotEqual(const GRState* St, SymbolRef sym, const llvm::APSInt& V)
+ const llvm::APSInt* getSymVal(const GRState* state, SymbolRef sym) const;
+ bool isNotEqual(const GRState* state, SymbolRef sym, const llvm::APSInt& V)
const;
- bool isEqual(const GRState* St, SymbolRef sym, const llvm::APSInt& V)
+ bool isEqual(const GRState* state, SymbolRef sym, const llvm::APSInt& V)
const;
- const GRState* RemoveDeadBindings(const GRState* St, SymbolReaper& SymReaper);
+ const GRState* RemoveDeadBindings(const GRState* state, SymbolReaper& SymReaper);
- void print(const GRState* St, std::ostream& Out,
+ void print(const GRState* state, std::ostream& Out,
const char* nl, const char *sep);
};
@@ -95,87 +95,77 @@ ConstraintManager* clang::CreateBasicConstraintManager(GRStateManager& StateMgr)
}
const GRState*
-BasicConstraintManager::AssumeSymNE(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible) {
+BasicConstraintManager::AssumeSymNE(const GRState *state, SymbolRef sym,
+ const llvm::APSInt& V) {
// First, determine if sym == X, where X != V.
- if (const llvm::APSInt* X = getSymVal(St, sym)) {
- isFeasible = (*X != V);
- return St;
+ if (const llvm::APSInt* X = getSymVal(state, sym)) {
+ bool isFeasible = (*X != V);
+ return isFeasible ? state : NULL;
}
// Second, determine if sym != V.
- if (isNotEqual(St, sym, V)) {
- isFeasible = true;
- return St;
- }
+ if (isNotEqual(state, sym, V))
+ return state;
// If we reach here, sym is not a constant and we don't know if it is != V.
// Make that assumption.
- isFeasible = true;
- return AddNE(St, sym, V);
+ return AddNE(state, sym, V);
}
-const GRState*
-BasicConstraintManager::AssumeSymEQ(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible) {
+const GRState *BasicConstraintManager::AssumeSymEQ(const GRState *state,
+ SymbolRef sym,
+ const llvm::APSInt &V) {
// First, determine if sym == X, where X != V.
- if (const llvm::APSInt* X = getSymVal(St, sym)) {
- isFeasible = *X == V;
- return St;
+ if (const llvm::APSInt* X = getSymVal(state, sym)) {
+ bool isFeasible = *X == V;
+ return isFeasible ? state : NULL;
}
// Second, determine if sym != V.
- if (isNotEqual(St, sym, V)) {
- isFeasible = false;
- return St;
- }
+ if (isNotEqual(state, sym, V))
+ return NULL;
// If we reach here, sym is not a constant and we don't know if it is == V.
// Make that assumption.
-
- isFeasible = true;
- return AddEQ(St, sym, V);
+ return AddEQ(state, sym, V);
}
// These logic will be handled in another ConstraintManager.
-const GRState*
-BasicConstraintManager::AssumeSymLT(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible) {
-
+const GRState *BasicConstraintManager::AssumeSymLT(const GRState *state,
+ SymbolRef sym,
+ const llvm::APSInt& V) {
// Is 'V' the smallest possible value?
if (V == llvm::APSInt::getMinValue(V.getBitWidth(), V.isUnsigned())) {
// sym cannot be any value less than 'V'. This path is infeasible.
- isFeasible = false;
- return St;
+ return NULL;
}
// FIXME: For now have assuming x < y be the same as assuming sym != V;
- return AssumeSymNE(St, sym, V, isFeasible);
+ return AssumeSymNE(state, sym, V);
}
-const GRState*
-BasicConstraintManager::AssumeSymGT(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible) {
+const GRState *BasicConstraintManager::AssumeSymGT(const GRState *state,
+ SymbolRef sym,
+ const llvm::APSInt& V) {
// Is 'V' the largest possible value?
if (V == llvm::APSInt::getMaxValue(V.getBitWidth(), V.isUnsigned())) {
// sym cannot be any value greater than 'V'. This path is infeasible.
- isFeasible = false;
- return St;
+ return NULL;
}
// FIXME: For now have assuming x > y be the same as assuming sym != V;
- return AssumeSymNE(St, sym, V, isFeasible);
+ return AssumeSymNE(state, sym, V);
}
-const GRState*
-BasicConstraintManager::AssumeSymGE(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible) {
+const GRState *BasicConstraintManager::AssumeSymGE(const GRState *state,
+ SymbolRef sym,
+ const llvm::APSInt &V) {
// Reject a path if the value of sym is a constant X and !(X >= V).
- if (const llvm::APSInt* X = getSymVal(St, sym)) {
- isFeasible = *X >= V;
- return St;
+ if (const llvm::APSInt *X = getSymVal(state, sym)) {
+ bool isFeasible = *X >= V;
+ return isFeasible ? state : NULL;
}
// Sym is not a constant, but it is worth looking to see if V is the
@@ -183,28 +173,25 @@ BasicConstraintManager::AssumeSymGE(const GRState* St, SymbolRef sym,
if (V == llvm::APSInt::getMaxValue(V.getBitWidth(), V.isUnsigned())) {
// If we know that sym != V, then this condition is infeasible since
// there is no other value greater than V.
- isFeasible = !isNotEqual(St, sym, V);
+ bool isFeasible = !isNotEqual(state, sym, V);
// If the path is still feasible then as a consequence we know that
// 'sym == V' because we cannot have 'sym > V' (no larger values).
// Add this constraint.
- if (isFeasible)
- return AddEQ(St, sym, V);
+ return isFeasible ? AddEQ(state, sym, V) : NULL;
}
- else
- isFeasible = true;
- return St;
+ return state;
}
const GRState*
-BasicConstraintManager::AssumeSymLE(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible) {
+BasicConstraintManager::AssumeSymLE(const GRState* state, SymbolRef sym,
+ const llvm::APSInt& V) {
// Reject a path if the value of sym is a constant X and !(X <= V).
- if (const llvm::APSInt* X = getSymVal(St, sym)) {
- isFeasible = *X <= V;
- return St;
+ if (const llvm::APSInt* X = getSymVal(state, sym)) {
+ bool isFeasible = *X <= V;
+ return isFeasible ? state : NULL;
}
// Sym is not a constant, but it is worth looking to see if V is the
@@ -212,64 +199,57 @@ BasicConstraintManager::AssumeSymLE(const GRState* St, SymbolRef sym,
if (V == llvm::APSInt::getMinValue(V.getBitWidth(), V.isUnsigned())) {
// If we know that sym != V, then this condition is infeasible since
// there is no other value less than V.
- isFeasible = !isNotEqual(St, sym, V);
+ bool isFeasible = !isNotEqual(state, sym, V);
// If the path is still feasible then as a consequence we know that
// 'sym == V' because we cannot have 'sym < V' (no smaller values).
// Add this constraint.
- if (isFeasible)
- return AddEQ(St, sym, V);
+ return isFeasible ? AddEQ(state, sym, V) : NULL;
}
- else
- isFeasible = true;
- return St;
+ return state;
}
-const GRState* BasicConstraintManager::AddEQ(const GRState* St, SymbolRef sym,
+const GRState* BasicConstraintManager::AddEQ(const GRState* state, SymbolRef sym,
const llvm::APSInt& V) {
// Create a new state with the old binding replaced.
- GRStateRef state(St, StateMgr);
- return state.set<ConstEq>(sym, &V);
+ return state->set<ConstEq>(sym, &V);
}
-const GRState* BasicConstraintManager::AddNE(const GRState* St, SymbolRef sym,
+const GRState* BasicConstraintManager::AddNE(const GRState* state, SymbolRef sym,
const llvm::APSInt& V) {
- GRStateRef state(St, StateMgr);
-
// First, retrieve the NE-set associated with the given symbol.
- ConstNotEqTy::data_type* T = state.get<ConstNotEq>(sym);
+ ConstNotEqTy::data_type* T = state->get<ConstNotEq>(sym);
GRState::IntSetTy S = T ? *T : ISetFactory.GetEmptySet();
-
// Now add V to the NE set.
S = ISetFactory.Add(S, &V);
// Create a new state with the old binding replaced.
- return state.set<ConstNotEq>(sym, S);
+ return state->set<ConstNotEq>(sym, S);
}
-const llvm::APSInt* BasicConstraintManager::getSymVal(const GRState* St,
+const llvm::APSInt* BasicConstraintManager::getSymVal(const GRState* state,
SymbolRef sym) const {
- const ConstEqTy::data_type* T = St->get<ConstEq>(sym);
+ const ConstEqTy::data_type* T = state->get<ConstEq>(sym);
return T ? *T : NULL;
}
-bool BasicConstraintManager::isNotEqual(const GRState* St, SymbolRef sym,
+bool BasicConstraintManager::isNotEqual(const GRState* state, SymbolRef sym,
const llvm::APSInt& V) const {
// Retrieve the NE-set associated with the given symbol.
- const ConstNotEqTy::data_type* T = St->get<ConstNotEq>(sym);
+ const ConstNotEqTy::data_type* T = state->get<ConstNotEq>(sym);
// See if V is present in the NE-set.
return T ? T->contains(&V) : false;
}
-bool BasicConstraintManager::isEqual(const GRState* St, SymbolRef sym,
+bool BasicConstraintManager::isEqual(const GRState* state, SymbolRef sym,
const llvm::APSInt& V) const {
// Retrieve the EQ-set associated with the given symbol.
- const ConstEqTy::data_type* T = St->get<ConstEq>(sym);
+ const ConstEqTy::data_type* T = state->get<ConstEq>(sym);
// See if V is present in the EQ-set.
return T ? **T == V : false;
}
@@ -277,35 +257,34 @@ bool BasicConstraintManager::isEqual(const GRState* St, SymbolRef sym,
/// Scan all symbols referenced by the constraints. If the symbol is not alive
/// as marked in LSymbols, mark it as dead in DSymbols.
const GRState*
-BasicConstraintManager::RemoveDeadBindings(const GRState* St,
+BasicConstraintManager::RemoveDeadBindings(const GRState* state,
SymbolReaper& SymReaper) {
- GRStateRef state(St, StateMgr);
- ConstEqTy CE = state.get<ConstEq>();
- ConstEqTy::Factory& CEFactory = state.get_context<ConstEq>();
+ ConstEqTy CE = state->get<ConstEq>();
+ ConstEqTy::Factory& CEFactory = state->get_context<ConstEq>();
for (ConstEqTy::iterator I = CE.begin(), E = CE.end(); I!=E; ++I) {
SymbolRef sym = I.getKey();
if (SymReaper.maybeDead(sym)) CE = CEFactory.Remove(CE, sym);
}
- state = state.set<ConstEq>(CE);
+ state = state->set<ConstEq>(CE);
- ConstNotEqTy CNE = state.get<ConstNotEq>();
- ConstNotEqTy::Factory& CNEFactory = state.get_context<ConstNotEq>();
+ ConstNotEqTy CNE = state->get<ConstNotEq>();
+ ConstNotEqTy::Factory& CNEFactory = state->get_context<ConstNotEq>();
for (ConstNotEqTy::iterator I = CNE.begin(), E = CNE.end(); I != E; ++I) {
SymbolRef sym = I.getKey();
if (SymReaper.maybeDead(sym)) CNE = CNEFactory.Remove(CNE, sym);
}
- return state.set<ConstNotEq>(CNE);
+ return state->set<ConstNotEq>(CNE);
}
-void BasicConstraintManager::print(const GRState* St, std::ostream& Out,
+void BasicConstraintManager::print(const GRState* state, std::ostream& Out,
const char* nl, const char *sep) {
// Print equality constraints.
- ConstEqTy CE = St->get<ConstEq>();
+ ConstEqTy CE = state->get<ConstEq>();
if (!CE.isEmpty()) {
Out << nl << sep << "'==' constraints:";
@@ -319,7 +298,7 @@ void BasicConstraintManager::print(const GRState* St, std::ostream& Out,
// Print != constraints.
- ConstNotEqTy CNE = St->get<ConstNotEq>();
+ ConstNotEqTy CNE = state->get<ConstNotEq>();
if (!CNE.isEmpty()) {
Out << nl << sep << "'!=' constraints:";
diff --git a/lib/Analysis/BasicObjCFoundationChecks.cpp b/lib/Analysis/BasicObjCFoundationChecks.cpp
index 98e9551d4b3d..aa85769157e7 100644
--- a/lib/Analysis/BasicObjCFoundationChecks.cpp
+++ b/lib/Analysis/BasicObjCFoundationChecks.cpp
@@ -66,9 +66,6 @@ class VISIBILITY_HIDDEN BasicObjCFoundationChecks : public GRSimpleAPICheck {
APIMisuse *BT;
BugReporter& BR;
ASTContext &Ctx;
- GRStateManager* VMgr;
-
- SVal GetSVal(const GRState* St, Expr* E) { return VMgr->GetSVal(St, E); }
bool isNSString(ObjCInterfaceType* T, const char* suffix);
bool AuditNSString(NodeTy* N, ObjCMessageExpr* ME);
@@ -79,9 +76,8 @@ class VISIBILITY_HIDDEN BasicObjCFoundationChecks : public GRSimpleAPICheck {
bool CheckNilArg(NodeTy* N, unsigned Arg);
public:
- BasicObjCFoundationChecks(ASTContext& ctx, GRStateManager* vmgr,
- BugReporter& br)
- : BT(0), BR(br), Ctx(ctx), VMgr(vmgr) {}
+ BasicObjCFoundationChecks(ASTContext& ctx, BugReporter& br)
+ : BT(0), BR(br), Ctx(ctx) {}
bool Audit(ExplodedNode<GRState>* N, GRStateManager&);
@@ -106,10 +102,8 @@ private:
GRSimpleAPICheck*
-clang::CreateBasicObjCFoundationChecks(ASTContext& Ctx,
- GRStateManager* VMgr, BugReporter& BR) {
-
- return new BasicObjCFoundationChecks(Ctx, VMgr, BR);
+clang::CreateBasicObjCFoundationChecks(ASTContext& Ctx, BugReporter& BR) {
+ return new BasicObjCFoundationChecks(Ctx, BR);
}
@@ -157,7 +151,7 @@ bool BasicObjCFoundationChecks::CheckNilArg(NodeTy* N, unsigned Arg) {
Expr * E = ME->getArg(Arg);
- if (isNil(GetSVal(N->getState(), E))) {
+ if (isNil(N->getState()->getSVal(E))) {
WarnNilArg(N, ME, Arg);
return true;
}
@@ -259,14 +253,11 @@ class VISIBILITY_HIDDEN AuditCFNumberCreate : public GRSimpleAPICheck {
// approach makes this class more stateless.
ASTContext& Ctx;
IdentifierInfo* II;
- GRStateManager* VMgr;
BugReporter& BR;
-
- SVal GetSVal(const GRState* St, Expr* E) { return VMgr->GetSVal(St, E); }
-
+
public:
- AuditCFNumberCreate(ASTContext& ctx, GRStateManager* vmgr, BugReporter& br)
- : BT(0), Ctx(ctx), II(&Ctx.Idents.get("CFNumberCreate")), VMgr(vmgr), BR(br){}
+ AuditCFNumberCreate(ASTContext& ctx, BugReporter& br)
+ : BT(0), Ctx(ctx), II(&Ctx.Idents.get("CFNumberCreate")), BR(br){}
~AuditCFNumberCreate() {}
@@ -374,14 +365,14 @@ static const char* GetCFNumberTypeStr(uint64_t i) {
bool AuditCFNumberCreate::Audit(ExplodedNode<GRState>* N,GRStateManager&){
CallExpr* CE = cast<CallExpr>(cast<PostStmt>(N->getLocation()).getStmt());
Expr* Callee = CE->getCallee();
- SVal CallV = GetSVal(N->getState(), Callee);
+ SVal CallV = N->getState()->getSVal(Callee);
const FunctionDecl* FD = CallV.getAsFunctionDecl();
if (!FD || FD->getIdentifier() != II || CE->getNumArgs()!=3)
return false;
// Get the value of the "theType" argument.
- SVal TheTypeVal = GetSVal(N->getState(), CE->getArg(1));
+ SVal TheTypeVal = N->getState()->getSVal(CE->getArg(1));
// FIXME: We really should allow ranges of valid theType values, and
// bifurcate the state appropriately.
@@ -400,7 +391,7 @@ bool AuditCFNumberCreate::Audit(ExplodedNode<GRState>* N,GRStateManager&){
// Look at the value of the integer being passed by reference. Essentially
// we want to catch cases where the value passed in is not equal to the
// size of the type being created.
- SVal TheValueExpr = GetSVal(N->getState(), CE->getArg(2));
+ SVal TheValueExpr = N->getState()->getSVal(CE->getArg(2));
// FIXME: Eventually we should handle arbitrary locations. We can do this
// by having an enhanced memory model that does low-level typing.
@@ -469,9 +460,8 @@ void AuditCFNumberCreate::AddError(const TypedRegion* R, Expr* Ex,
}
GRSimpleAPICheck*
-clang::CreateAuditCFNumberCreate(ASTContext& Ctx,
- GRStateManager* VMgr, BugReporter& BR) {
- return new AuditCFNumberCreate(Ctx, VMgr, BR);
+clang::CreateAuditCFNumberCreate(ASTContext& Ctx, BugReporter& BR) {
+ return new AuditCFNumberCreate(Ctx, BR);
}
//===----------------------------------------------------------------------===//
@@ -479,13 +469,12 @@ clang::CreateAuditCFNumberCreate(ASTContext& Ctx,
void clang::RegisterAppleChecks(GRExprEngine& Eng) {
ASTContext& Ctx = Eng.getContext();
- GRStateManager* VMgr = &Eng.getStateManager();
BugReporter &BR = Eng.getBugReporter();
- Eng.AddCheck(CreateBasicObjCFoundationChecks(Ctx, VMgr, BR),
+ Eng.AddCheck(CreateBasicObjCFoundationChecks(Ctx, BR),
Stmt::ObjCMessageExprClass);
- Eng.AddCheck(CreateAuditCFNumberCreate(Ctx, VMgr, BR),
+ Eng.AddCheck(CreateAuditCFNumberCreate(Ctx, BR),
Stmt::CallExprClass);
RegisterNSErrorChecks(BR, Eng);
diff --git a/lib/Analysis/BasicObjCFoundationChecks.h b/lib/Analysis/BasicObjCFoundationChecks.h
index 6c594ea72199..5c9701ecdd36 100644
--- a/lib/Analysis/BasicObjCFoundationChecks.h
+++ b/lib/Analysis/BasicObjCFoundationChecks.h
@@ -33,11 +33,9 @@ class BugReporter;
class GRExprEngine;
GRSimpleAPICheck* CreateBasicObjCFoundationChecks(ASTContext& Ctx,
- GRStateManager* VMgr,
BugReporter& BR);
GRSimpleAPICheck* CreateAuditCFNumberCreate(ASTContext& Ctx,
- GRStateManager* VMgr,
BugReporter& BR);
void RegisterNSErrorChecks(BugReporter& BR, GRExprEngine &Eng);
diff --git a/lib/Analysis/BasicStore.cpp b/lib/Analysis/BasicStore.cpp
index 2dd46c385343..fcb405d2d20d 100644
--- a/lib/Analysis/BasicStore.cpp
+++ b/lib/Analysis/BasicStore.cpp
@@ -45,15 +45,14 @@ public:
~BasicStoreManager() {}
- SubRegionMap* getSubRegionMap(const GRState *state) {
+ SubRegionMap *getSubRegionMap(const GRState *state) {
return new BasicStoreSubRegionMap();
}
SVal Retrieve(const GRState *state, Loc loc, QualType T = QualType());
- const GRState* Bind(const GRState* St, Loc L, SVal V) {
- Store store = BindInternal(St->getStore(), L, V);
- return StateMgr.MakeStateWithStore(St, store);
+ const GRState *Bind(const GRState *state, Loc L, SVal V) {
+ return state->makeWithStore(BindInternal(state->getStore(), L, V));
}
Store scanForIvars(Stmt *B, const Decl* SelfDecl, Store St);
@@ -67,19 +66,19 @@ public:
return Loc::MakeVal(MRMgr.getVarRegion(VD));
}
- const GRState* BindCompoundLiteral(const GRState* St,
- const CompoundLiteralExpr* CL,
- SVal V) {
- return St;
+ const GRState *BindCompoundLiteral(const GRState *state,
+ const CompoundLiteralExpr* cl,
+ SVal val) {
+ return state;
}
- SVal getLValueVar(const GRState* St, const VarDecl* VD);
- SVal getLValueString(const GRState* St, const StringLiteral* S);
- SVal getLValueCompoundLiteral(const GRState* St,
+ SVal getLValueVar(const GRState *state, const VarDecl* VD);
+ SVal getLValueString(const GRState *state, const StringLiteral* S);
+ SVal getLValueCompoundLiteral(const GRState *state,
const CompoundLiteralExpr* CL);
- SVal getLValueIvar(const GRState* St, const ObjCIvarDecl* D, SVal Base);
- SVal getLValueField(const GRState* St, SVal Base, const FieldDecl* D);
- SVal getLValueElement(const GRState* St, QualType elementType,
+ SVal getLValueIvar(const GRState *state, const ObjCIvarDecl* D, SVal Base);
+ SVal getLValueField(const GRState *state, SVal Base, const FieldDecl* D);
+ SVal getLValueElement(const GRState *state, QualType elementType,
SVal Base, SVal Offset);
/// ArrayToPointer - Used by GRExprEngine::VistCast to handle implicit
@@ -92,23 +91,19 @@ public:
const MemRegion* getSelfRegion(Store) { return SelfRegion; }
/// RemoveDeadBindings - Scans a BasicStore of 'state' for dead values.
- /// It returns a new Store with these values removed, and populates LSymbols
- /// and DSymbols with the known set of live and dead symbols respectively.
- Store
- RemoveDeadBindings(const GRState* state, Stmt* Loc,
+ /// It returns a new Store with these values removed.
+ Store RemoveDeadBindings(const GRState *state, Stmt* Loc,
SymbolReaper& SymReaper,
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots);
void iterBindings(Store store, BindingsHandler& f);
- const GRState* BindDecl(const GRState* St, const VarDecl* VD, SVal InitVal) {
- Store store = BindDeclInternal(St->getStore(), VD, &InitVal);
- return StateMgr.MakeStateWithStore(St, store);
+ const GRState *BindDecl(const GRState *state, const VarDecl* VD, SVal InitVal) {
+ return state->makeWithStore(BindDeclInternal(state->getStore(),VD, &InitVal));
}
- const GRState* BindDeclWithNoInit(const GRState* St, const VarDecl* VD) {
- Store store = BindDeclInternal(St->getStore(), VD, 0);
- return StateMgr.MakeStateWithStore(St, store);
+ const GRState *BindDeclWithNoInit(const GRState *state, const VarDecl* VD) {
+ return state->makeWithStore(BindDeclInternal(state->getStore(), VD, 0));
}
Store BindDeclInternal(Store store, const VarDecl* VD, SVal* InitVal);
@@ -130,21 +125,21 @@ StoreManager* clang::CreateBasicStoreManager(GRStateManager& StMgr) {
return new BasicStoreManager(StMgr);
}
-SVal BasicStoreManager::getLValueVar(const GRState* St, const VarDecl* VD) {
+SVal BasicStoreManager::getLValueVar(const GRState *state, const VarDecl* VD) {
return Loc::MakeVal(MRMgr.getVarRegion(VD));
}
-SVal BasicStoreManager::getLValueString(const GRState* St,
+SVal BasicStoreManager::getLValueString(const GRState *state,
const StringLiteral* S) {
return Loc::MakeVal(MRMgr.getStringRegion(S));
}
-SVal BasicStoreManager::getLValueCompoundLiteral(const GRState* St,
+SVal BasicStoreManager::getLValueCompoundLiteral(const GRState *state,
const CompoundLiteralExpr* CL){
return Loc::MakeVal(MRMgr.getCompoundLiteralRegion(CL));
}
-SVal BasicStoreManager::getLValueIvar(const GRState* St, const ObjCIvarDecl* D,
+SVal BasicStoreManager::getLValueIvar(const GRState *state, const ObjCIvarDecl* D,
SVal Base) {
if (Base.isUnknownOrUndef())
@@ -162,7 +157,7 @@ SVal BasicStoreManager::getLValueIvar(const GRState* St, const ObjCIvarDecl* D,
return UnknownVal();
}
-SVal BasicStoreManager::getLValueField(const GRState* St, SVal Base,
+SVal BasicStoreManager::getLValueField(const GRState *state, SVal Base,
const FieldDecl* D) {
if (Base.isUnknownOrUndef())
@@ -194,7 +189,7 @@ SVal BasicStoreManager::getLValueField(const GRState* St, SVal Base,
return Loc::MakeVal(MRMgr.getFieldRegion(D, BaseR));
}
-SVal BasicStoreManager::getLValueElement(const GRState* St,
+SVal BasicStoreManager::getLValueElement(const GRState *state,
QualType elementType,
SVal Base, SVal Offset) {
@@ -248,7 +243,7 @@ SVal BasicStoreManager::getLValueElement(const GRState* St,
if (BaseR)
return Loc::MakeVal(MRMgr.getElementRegion(elementType, UnknownVal(),
- BaseR));
+ BaseR, getContext()));
else
return UnknownVal();
}
@@ -274,7 +269,7 @@ static bool isHigherOrderRawPtr(QualType T, ASTContext &C) {
}
}
-SVal BasicStoreManager::Retrieve(const GRState* state, Loc loc, QualType T) {
+SVal BasicStoreManager::Retrieve(const GRState *state, Loc loc, QualType T) {
if (isa<UnknownVal>(loc))
return UnknownVal();
@@ -390,7 +385,7 @@ Store BasicStoreManager::Remove(Store store, Loc loc) {
}
Store
-BasicStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc,
+BasicStoreManager::RemoveDeadBindings(const GRState *state, Stmt* Loc,
SymbolReaper& SymReaper,
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots)
{
diff --git a/lib/Analysis/BugReporter.cpp b/lib/Analysis/BugReporter.cpp
index 32998e1c4256..5dbbfc33e426 100644
--- a/lib/Analysis/BugReporter.cpp
+++ b/lib/Analysis/BugReporter.cpp
@@ -336,7 +336,7 @@ GetMostRecentVarDeclBinding(const ExplodedNode<GRState>* N,
if (!DR)
continue;
- SVal Y = VMgr.GetSVal(N->getState(), DR);
+ SVal Y = N->getState()->getSVal(DR);
if (X != Y)
continue;
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp
index f5ca322b6884..c58ceb419324 100644
--- a/lib/Analysis/CFRefCount.cpp
+++ b/lib/Analysis/CFRefCount.cpp
@@ -971,8 +971,12 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
// FIXME: This should all be refactored into a chain of "summary lookup"
// filters.
+ assert (ScratchArgs.isEmpty());
+
switch (strlen(FName)) {
default: break;
+
+
case 17:
// Handle: id NSMakeCollectable(CFTypeRef)
if (!memcmp(FName, "NSMakeCollectable", 17)) {
@@ -980,13 +984,55 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
? getUnarySummary(FT, cfmakecollectable)
: getPersistentStopSummary();
}
+ else if (!memcmp(FName, "IOBSDNameMatching", 17) ||
+ !memcmp(FName, "IOServiceMatching", 17)) {
+ // Part of <rdar://problem/6961230>. (IOKit)
+ // This should be addressed using a API table.
+ S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true),
+ DoNothing, DoNothing);
+ }
break;
-
+
+ case 21:
+ if (!memcmp(FName, "IOServiceNameMatching", 21)) {
+ // Part of <rdar://problem/6961230>. (IOKit)
+ // This should be addressed using a API table.
+ S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true),
+ DoNothing, DoNothing);
+ }
+ break;
+
+ case 24:
+ if (!memcmp(FName, "IOServiceAddNotification", 24)) {
+ // Part of <rdar://problem/6961230>. (IOKit)
+ // This should be addressed using a API table.
+ ScratchArgs = AF.Add(ScratchArgs, 2, DecRef);
+ S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
+ }
+ break;
+
+ case 25:
+ if (!memcmp(FName, "IORegistryEntryIDMatching", 25)) {
+ // Part of <rdar://problem/6961230>. (IOKit)
+ // This should be addressed using a API table.
+ S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true),
+ DoNothing, DoNothing);
+ }
+ break;
+
+ case 26:
+ if (!memcmp(FName, "IOOpenFirmwarePathMatching", 26)) {
+ // Part of <rdar://problem/6961230>. (IOKit)
+ // This should be addressed using a API table.
+ S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true),
+ DoNothing, DoNothing);
+ }
+ break;
+
case 27:
if (!memcmp(FName, "IOServiceGetMatchingService", 27)) {
// Part of <rdar://problem/6961230>.
// This should be addressed using a API table.
- assert (ScratchArgs.isEmpty());
ScratchArgs = AF.Add(ScratchArgs, 1, DecRef);
S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
}
@@ -997,11 +1043,19 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
// FIXES: <rdar://problem/6326900>
// This should be addressed using a API table. This strcmp is also
// a little gross, but there is no need to super optimize here.
- assert (ScratchArgs.isEmpty());
ScratchArgs = AF.Add(ScratchArgs, 1, DecRef);
S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
}
break;
+
+ case 32:
+ if (!memcmp(FName, "IOServiceAddMatchingNotification", 32)) {
+ // Part of <rdar://problem/6961230>.
+ // This should be addressed using a API table.
+ ScratchArgs = AF.Add(ScratchArgs, 2, DecRef);
+ S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
+ }
+ break;
}
// Did we get a summary?
@@ -1195,15 +1249,15 @@ RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ,
// Determine if there is a special return effect for this method.
if (isTrackedObjCObjectType(RetTy)) {
- if (FD->getAttr<NSReturnsRetainedAttr>()) {
+ if (FD->getAttr<NSReturnsRetainedAttr>(Ctx)) {
Summ.setRetEffect(ObjCAllocRetE);
}
- else if (FD->getAttr<CFReturnsRetainedAttr>()) {
+ else if (FD->getAttr<CFReturnsRetainedAttr>(Ctx)) {
Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true));
}
}
else if (RetTy->getAsPointerType()) {
- if (FD->getAttr<CFReturnsRetainedAttr>()) {
+ if (FD->getAttr<CFReturnsRetainedAttr>(Ctx)) {
Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true));
}
}
@@ -1217,10 +1271,10 @@ RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ,
// Determine if there is a special return effect for this method.
if (isTrackedObjCObjectType(MD->getResultType())) {
- if (MD->getAttr<NSReturnsRetainedAttr>()) {
+ if (MD->getAttr<NSReturnsRetainedAttr>(Ctx)) {
Summ.setRetEffect(ObjCAllocRetE);
}
- else if (MD->getAttr<CFReturnsRetainedAttr>()) {
+ else if (MD->getAttr<CFReturnsRetainedAttr>(Ctx)) {
Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true));
}
}
@@ -1485,11 +1539,14 @@ void RetainSummaryManager::InitializeMethodSummaries() {
addInstMethSummary("QCView", AllocSumm,
"createSnapshotImageOfType", NULL);
- // Create summaries for CIContext, 'createCGImage'.
+ // Create summaries for CIContext, 'createCGImage' and
+ // 'createCGLayerWithSize'.
addInstMethSummary("CIContext", AllocSumm,
"createCGImage", "fromRect", NULL);
addInstMethSummary("CIContext", AllocSumm,
- "createCGImage", "fromRect", "format", "colorSpace", NULL);
+ "createCGImage", "fromRect", "format", "colorSpace", NULL);
+ addInstMethSummary("CIContext", AllocSumm, "createCGLayerWithSize",
+ "info", NULL);
}
//===----------------------------------------------------------------------===//
@@ -1747,11 +1804,11 @@ static SymbolRef GetCurrentAutoreleasePool(const GRState* state) {
return stack.isEmpty() ? SymbolRef() : stack.getHead();
}
-static GRStateRef SendAutorelease(GRStateRef state, ARCounts::Factory &F,
- SymbolRef sym) {
+static const GRState * SendAutorelease(const GRState *state,
+ ARCounts::Factory &F, SymbolRef sym) {
SymbolRef pool = GetCurrentAutoreleasePool(state);
- const ARCounts *cnts = state.get<AutoreleasePoolContents>(pool);
+ const ARCounts *cnts = state->get<AutoreleasePoolContents>(pool);
ARCounts newCnts(0);
if (cnts) {
@@ -1761,7 +1818,7 @@ static GRStateRef SendAutorelease(GRStateRef state, ARCounts::Factory &F,
else
newCnts = F.Add(F.GetEmptyMap(), sym, 1);
- return state.set<AutoreleasePoolContents>(pool, newCnts);
+ return state->set<AutoreleasePoolContents>(pool, newCnts);
}
//===----------------------------------------------------------------------===//
@@ -1794,7 +1851,7 @@ private:
BugType *returnNotOwnedForOwned;
BugReporter *BR;
- GRStateRef Update(GRStateRef state, SymbolRef sym, RefVal V, ArgEffect E,
+ const GRState * Update(const GRState * state, SymbolRef sym, RefVal V, ArgEffect E,
RefVal::Kind& hasErr);
void ProcessNonLeakError(ExplodedNodeSet<GRState>& Dst,
@@ -1804,10 +1861,10 @@ private:
const GRState* St,
RefVal::Kind hasErr, SymbolRef Sym);
- GRStateRef HandleSymbolDeath(GRStateRef state, SymbolRef sid, RefVal V,
+ const GRState * HandleSymbolDeath(const GRState * state, SymbolRef sid, RefVal V,
llvm::SmallVectorImpl<SymbolRef> &Leaked);
- ExplodedNode<GRState>* ProcessLeaks(GRStateRef state,
+ ExplodedNode<GRState>* ProcessLeaks(const GRState * state,
llvm::SmallVectorImpl<SymbolRef> &Leaked,
GenericNodeBuilder &Builder,
GRExprEngine &Eng,
@@ -1882,8 +1939,8 @@ public:
Stmt* S, const GRState* state,
SymbolReaper& SymReaper);
- std::pair<ExplodedNode<GRState>*, GRStateRef>
- HandleAutoreleaseCounts(GRStateRef state, GenericNodeBuilder Bd,
+ std::pair<ExplodedNode<GRState>*, const GRState *>
+ HandleAutoreleaseCounts(const GRState * state, GenericNodeBuilder Bd,
ExplodedNode<GRState>* Pred, GRExprEngine &Eng,
SymbolRef Sym, RefVal V, bool &stop);
// Return statements.
@@ -1896,9 +1953,8 @@ public:
// Assumptions.
- virtual const GRState* EvalAssume(GRStateManager& VMgr,
- const GRState* St, SVal Cond,
- bool Assumption, bool& isFeasible);
+ virtual const GRState *EvalAssume(const GRState* state, SVal condition,
+ bool assumption);
};
} // end anonymous namespace
@@ -2226,15 +2282,14 @@ PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode<GRState>* N,
return NULL;
// Check if the type state has changed.
- GRStateManager &StMgr = BRC.getStateManager();
- GRStateRef PrevSt(PrevN->getState(), StMgr);
- GRStateRef CurrSt(N->getState(), StMgr);
+ const GRState *PrevSt = PrevN->getState();
+ const GRState *CurrSt = N->getState();
- const RefVal* CurrT = CurrSt.get<RefBindings>(Sym);
+ const RefVal* CurrT = CurrSt->get<RefBindings>(Sym);
if (!CurrT) return NULL;
- const RefVal& CurrV = *CurrT;
- const RefVal* PrevT = PrevSt.get<RefBindings>(Sym);
+ const RefVal &CurrV = *CurrT;
+ const RefVal *PrevT = PrevSt->get<RefBindings>(Sym);
// Create a string buffer to constain all the useful things we want
// to tell the user.
@@ -2248,7 +2303,7 @@ PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode<GRState>* N,
if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
// Get the name of the callee (if it is available).
- SVal X = CurrSt.GetSValAsScalarOrLoc(CE->getCallee());
+ SVal X = CurrSt->getSValAsScalarOrLoc(CE->getCallee());
if (const FunctionDecl* FD = X.getAsFunctionDecl())
os << "Call to function '" << FD->getNameAsString() <<'\'';
else
@@ -2305,7 +2360,7 @@ PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode<GRState>* N,
// Retrieve the value of the argument. Is it the symbol
// we are interested in?
- if (CurrSt.GetSValAsScalarOrLoc(*AI).getAsLocSymbol() != Sym)
+ if (CurrSt->getSValAsScalarOrLoc(*AI).getAsLocSymbol() != Sym)
continue;
// We have an argument. Get the effect!
@@ -2314,7 +2369,7 @@ PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode<GRState>* N,
}
else if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S)) {
if (Expr *receiver = ME->getReceiver())
- if (CurrSt.GetSValAsScalarOrLoc(receiver).getAsLocSymbol() == Sym) {
+ if (CurrSt->getSValAsScalarOrLoc(receiver).getAsLocSymbol() == Sym) {
// The symbol we are tracking is the receiver.
AEffects.push_back(Summ->getReceiverEffect());
}
@@ -2342,7 +2397,7 @@ PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode<GRState>* N,
if (contains(AEffects, MakeCollectable)) {
// Get the name of the function.
Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
- SVal X = CurrSt.GetSValAsScalarOrLoc(cast<CallExpr>(S)->getCallee());
+ SVal X = CurrSt->getSValAsScalarOrLoc(cast<CallExpr>(S)->getCallee());
const FunctionDecl* FD = X.getAsFunctionDecl();
const std::string& FName = FD->getNameAsString();
@@ -2453,7 +2508,7 @@ PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode<GRState>* N,
// to Sym.
for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
if (Expr* Exp = dyn_cast_or_null<Expr>(*I))
- if (CurrSt.GetSValAsScalarOrLoc(Exp).getAsLocSymbol() == Sym) {
+ if (CurrSt->getSValAsScalarOrLoc(Exp).getAsLocSymbol() == Sym) {
P->addRange(Exp->getSourceRange());
break;
}
@@ -2705,7 +2760,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
// Get the state.
GRStateManager& StateMgr = Eng.getStateManager();
- GRStateRef state(Builder.GetState(Pred), StateMgr);
+ const GRState *state = Builder.GetState(Pred);
ASTContext& Ctx = StateMgr.getContext();
ValueManager &ValMgr = Eng.getValueManager();
@@ -2716,11 +2771,11 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
SymbolRef ErrorSym = 0;
for (ExprIterator I = arg_beg; I != arg_end; ++I, ++idx) {
- SVal V = state.GetSValAsScalarOrLoc(*I);
+ SVal V = state->getSValAsScalarOrLoc(*I);
SymbolRef Sym = V.getAsLocSymbol();
if (Sym)
- if (RefBindings::data_type* T = state.get<RefBindings>(Sym)) {
+ if (RefBindings::data_type* T = state->get<RefBindings>(Sym)) {
state = Update(state, Sym, *T, Summ.getArg(idx), hasErr);
if (hasErr) {
ErrorExpr = *I;
@@ -2775,10 +2830,10 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
}
// Is the invalidated variable something that we were tracking?
- SymbolRef Sym = state.GetSValAsScalarOrLoc(R).getAsLocSymbol();
+ SymbolRef Sym = state->getSValAsScalarOrLoc(R).getAsLocSymbol();
// Remove any existing reference-count binding.
- if (Sym) state = state.remove<RefBindings>(Sym);
+ if (Sym) state = state->remove<RefBindings>(Sym);
if (R->isBoundable(Ctx)) {
// Set the value of the variable to be a conjured symbol.
@@ -2788,7 +2843,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
if (Loc::IsLocType(T) || (T->isIntegerType() && T->isScalarType())){
ValueManager &ValMgr = Eng.getValueManager();
SVal V = ValMgr.getConjuredSymbolVal(*I, T, Count);
- state = state.BindLoc(Loc::MakeVal(R), V);
+ state = state->bindLoc(Loc::MakeVal(R), V);
}
else if (const RecordType *RT = T->getAsStructureType()) {
// Handle structs in a not so awesome way. Here we just
@@ -2802,7 +2857,8 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
if (!RD)
continue;
- MemRegionManager &MRMgr = state.getManager().getRegionManager();
+ MemRegionManager &MRMgr =
+ state->getStateManager().getRegionManager();
// Iterate through the fields and construct new symbols.
for (RecordDecl::field_iterator FI=RD->field_begin(Ctx),
@@ -2817,7 +2873,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
const FieldRegion* FR = MRMgr.getFieldRegion(FD, R);
SVal V = ValMgr.getConjuredSymbolVal(*I, FT, Count);
- state = state.BindLoc(Loc::MakeVal(FR), V);
+ state = state->bindLoc(Loc::MakeVal(FR), V);
}
}
} else if (const ArrayType *AT = Ctx.getAsArrayType(T)) {
@@ -2825,31 +2881,30 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
StoreManager& StoreMgr = Eng.getStateManager().getStoreManager();
SVal V = ValMgr.getConjuredSymbolVal(*I, AT->getElementType(),
Count);
- state = GRStateRef(StoreMgr.setDefaultValue(state, R, V),
- StateMgr);
+ state = StoreMgr.setDefaultValue(state, R, V);
} else {
// Just blast away other values.
- state = state.BindLoc(*MR, UnknownVal());
+ state = state->bindLoc(*MR, UnknownVal());
}
}
}
else
- state = state.BindLoc(*MR, UnknownVal());
+ state = state->bindLoc(*MR, UnknownVal());
}
else {
// Nuke all other arguments passed by reference.
- state = state.Unbind(cast<Loc>(V));
+ state = state->unbindLoc(cast<Loc>(V));
}
}
else if (isa<nonloc::LocAsInteger>(V))
- state = state.Unbind(cast<nonloc::LocAsInteger>(V).getLoc());
+ state = state->unbindLoc(cast<nonloc::LocAsInteger>(V).getLoc());
}
// Evaluate the effect on the message receiver.
if (!ErrorExpr && Receiver) {
- SymbolRef Sym = state.GetSValAsScalarOrLoc(Receiver).getAsLocSymbol();
+ SymbolRef Sym = state->getSValAsScalarOrLoc(Receiver).getAsLocSymbol();
if (Sym) {
- if (const RefVal* T = state.get<RefBindings>(Sym)) {
+ if (const RefVal* T = state->get<RefBindings>(Sym)) {
state = Update(state, Sym, *T, Summ.getReceiverEffect(), hasErr);
if (hasErr) {
ErrorExpr = Receiver;
@@ -2871,10 +2926,10 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
if (RE.getKind() == RetEffect::OwnedWhenTrackedReceiver) {
assert(Receiver);
- SVal V = state.GetSValAsScalarOrLoc(Receiver);
+ SVal V = state->getSValAsScalarOrLoc(Receiver);
bool found = false;
if (SymbolRef Sym = V.getAsLocSymbol())
- if (state.get<RefBindings>(Sym)) {
+ if (state->get<RefBindings>(Sym)) {
found = true;
RE = Summaries.getObjAllocRetEffect();
}
@@ -2902,7 +2957,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
unsigned Count = Builder.getCurrentBlockCount();
ValueManager &ValMgr = Eng.getValueManager();
SVal X = ValMgr.getConjuredSymbolVal(Ex, T, Count);
- state = state.BindExpr(Ex, X, false);
+ state = state->bindExpr(Ex, X, false);
}
break;
@@ -2912,15 +2967,15 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
unsigned idx = RE.getIndex();
assert (arg_end >= arg_beg);
assert (idx < (unsigned) (arg_end - arg_beg));
- SVal V = state.GetSValAsScalarOrLoc(*(arg_beg+idx));
- state = state.BindExpr(Ex, V, false);
+ SVal V = state->getSValAsScalarOrLoc(*(arg_beg+idx));
+ state = state->bindExpr(Ex, V, false);
break;
}
case RetEffect::ReceiverAlias: {
assert (Receiver);
- SVal V = state.GetSValAsScalarOrLoc(Receiver);
- state = state.BindExpr(Ex, V, false);
+ SVal V = state->getSValAsScalarOrLoc(Receiver);
+ state = state->bindExpr(Ex, V, false);
break;
}
@@ -2930,9 +2985,9 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
ValueManager &ValMgr = Eng.getValueManager();
SymbolRef Sym = ValMgr.getConjuredSymbol(Ex, Count);
QualType RetT = GetReturnType(Ex, ValMgr.getContext());
- state = state.set<RefBindings>(Sym, RefVal::makeOwned(RE.getObjKind(),
+ state = state->set<RefBindings>(Sym, RefVal::makeOwned(RE.getObjKind(),
RetT));
- state = state.BindExpr(Ex, ValMgr.makeRegionVal(Sym), false);
+ state = state->bindExpr(Ex, ValMgr.makeRegionVal(Sym), false);
// FIXME: Add a flag to the checker where allocations are assumed to
// *not fail.
@@ -2953,9 +3008,9 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
ValueManager &ValMgr = Eng.getValueManager();
SymbolRef Sym = ValMgr.getConjuredSymbol(Ex, Count);
QualType RetT = GetReturnType(Ex, ValMgr.getContext());
- state = state.set<RefBindings>(Sym, RefVal::makeNotOwned(RE.getObjKind(),
+ state = state->set<RefBindings>(Sym, RefVal::makeNotOwned(RE.getObjKind(),
RetT));
- state = state.BindExpr(Ex, ValMgr.makeRegionVal(Sym), false);
+ state = state->bindExpr(Ex, ValMgr.makeRegionVal(Sym), false);
break;
}
}
@@ -3001,7 +3056,7 @@ void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<GRState>& Dst,
// FIXME: Is this really working as expected? There are cases where
// we just use the 'ID' from the message expression.
const GRState* St = Builder.GetState(Pred);
- SVal V = Eng.getStateManager().GetSValAsScalarOrLoc(St, Receiver);
+ SVal V = St->getSValAsScalarOrLoc(Receiver);
SymbolRef Sym = V.getAsLocSymbol();
if (Sym) {
@@ -3034,7 +3089,7 @@ void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<GRState>& Dst,
// This is a hack. When we have full-IP this should be removed.
if (isa<ObjCMethodDecl>(&Eng.getGraph().getCodeDecl())) {
if (Expr* Receiver = ME->getReceiver()) {
- SVal X = Eng.getStateManager().GetSValAsScalarOrLoc(St, Receiver);
+ SVal X = St->getSValAsScalarOrLoc(Receiver);
if (loc::MemRegionVal* L = dyn_cast<loc::MemRegionVal>(&X))
if (L->getRegion() == Eng.getStateManager().getSelfRegion(St)) {
// Update the summary to make the default argument effect
@@ -3057,17 +3112,15 @@ void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<GRState>& Dst,
namespace {
class VISIBILITY_HIDDEN StopTrackingCallback : public SymbolVisitor {
- GRStateRef state;
+ const GRState *state;
public:
- StopTrackingCallback(GRStateRef st) : state(st) {}
- GRStateRef getState() { return state; }
+ StopTrackingCallback(const GRState *st) : state(st) {}
+ const GRState *getState() const { return state; }
bool VisitSymbol(SymbolRef sym) {
- state = state.remove<RefBindings>(sym);
+ state = state->remove<RefBindings>(sym);
return true;
}
-
- const GRState* getState() const { return state.getState(); }
};
} // end anonymous namespace
@@ -3082,7 +3135,7 @@ void CFRefCount::EvalBind(GRStmtNodeBuilderRef& B, SVal location, SVal val) {
// (2) we are binding to a memregion that does not have stack storage
// (3) we are binding to a memregion with stack storage that the store
// does not understand.
- GRStateRef state = B.getState();
+ const GRState *state = B.getState();
if (!isa<loc::MemRegionVal>(location))
escapes = true;
@@ -3094,7 +3147,7 @@ void CFRefCount::EvalBind(GRStmtNodeBuilderRef& B, SVal location, SVal val) {
// To test (3), generate a new state with the binding removed. If it is
// the same state, then it escapes (since the store cannot represent
// the binding).
- escapes = (state == (state.BindLoc(cast<Loc>(location), UnknownVal())));
+ escapes = (state == (state->bindLoc(cast<Loc>(location), UnknownVal())));
}
}
@@ -3106,10 +3159,9 @@ void CFRefCount::EvalBind(GRStmtNodeBuilderRef& B, SVal location, SVal val) {
// Otherwise, find all symbols referenced by 'val' that we are tracking
// and stop tracking them.
- B.MakeNode(state.scanReachableSymbols<StopTrackingCallback>(val).getState());
+ B.MakeNode(state->scanReachableSymbols<StopTrackingCallback>(val).getState());
}
-
// Return statements.
void CFRefCount::EvalReturn(ExplodedNodeSet<GRState>& Dst,
@@ -3122,14 +3174,14 @@ void CFRefCount::EvalReturn(ExplodedNodeSet<GRState>& Dst,
if (!RetE)
return;
- GRStateRef state(Builder.GetState(Pred), Eng.getStateManager());
- SymbolRef Sym = state.GetSValAsScalarOrLoc(RetE).getAsLocSymbol();
+ const GRState *state = Builder.GetState(Pred);
+ SymbolRef Sym = state->getSValAsScalarOrLoc(RetE).getAsLocSymbol();
if (!Sym)
return;
// Get the reference count binding (if any).
- const RefVal* T = state.get<RefBindings>(Sym);
+ const RefVal* T = state->get<RefBindings>(Sym);
if (!T)
return;
@@ -3163,7 +3215,7 @@ void CFRefCount::EvalReturn(ExplodedNodeSet<GRState>& Dst,
}
// Update the binding.
- state = state.set<RefBindings>(Sym, X);
+ state = state->set<RefBindings>(Sym, X);
Pred = Builder.MakeNode(Dst, S, Pred, state);
// Did we cache out?
@@ -3182,7 +3234,7 @@ void CFRefCount::EvalReturn(ExplodedNodeSet<GRState>& Dst,
return;
// Get the updated binding.
- T = state.get<RefBindings>(Sym);
+ T = state->get<RefBindings>(Sym);
assert(T);
X = *T;
@@ -3217,7 +3269,7 @@ void CFRefCount::EvalReturn(ExplodedNodeSet<GRState>& Dst,
if (hasError) {
// Generate an error node.
static int ReturnOwnLeakTag = 0;
- state = state.set<RefBindings>(Sym, X);
+ state = state->set<RefBindings>(Sym, X);
ExplodedNode<GRState> *N =
Builder.generateNode(PostStmt(S, &ReturnOwnLeakTag), state, Pred);
if (N) {
@@ -3238,7 +3290,7 @@ void CFRefCount::EvalReturn(ExplodedNodeSet<GRState>& Dst,
// owned object.
static int ReturnNotOwnedForOwnedTag = 0;
- state = state.set<RefBindings>(Sym, X ^ RefVal::ErrorReturnedNotOwned);
+ state = state->set<RefBindings>(Sym, X ^ RefVal::ErrorReturnedNotOwned);
if (ExplodedNode<GRState> *N =
Builder.generateNode(PostStmt(S, &ReturnNotOwnedForOwnedTag),
state, Pred)) {
@@ -3254,10 +3306,8 @@ void CFRefCount::EvalReturn(ExplodedNodeSet<GRState>& Dst,
// Assumptions.
-const GRState* CFRefCount::EvalAssume(GRStateManager& VMgr,
- const GRState* St,
- SVal Cond, bool Assumption,
- bool& isFeasible) {
+const GRState* CFRefCount::EvalAssume(const GRState *state,
+ SVal Cond, bool Assumption) {
// FIXME: We may add to the interface of EvalAssume the list of symbols
// whose assumptions have changed. For now we just iterate through the
@@ -3265,32 +3315,30 @@ const GRState* CFRefCount::EvalAssume(GRStateManager& VMgr,
// too bad since the number of symbols we will track in practice are
// probably small and EvalAssume is only called at branches and a few
// other places.
- RefBindings B = St->get<RefBindings>();
+ RefBindings B = state->get<RefBindings>();
if (B.isEmpty())
- return St;
+ return state;
- bool changed = false;
-
- GRStateRef state(St, VMgr);
- RefBindings::Factory& RefBFactory = state.get_context<RefBindings>();
+ bool changed = false;
+ RefBindings::Factory& RefBFactory = state->get_context<RefBindings>();
for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
// Check if the symbol is null (or equal to any constant).
// If this is the case, stop tracking the symbol.
- if (VMgr.getSymVal(St, I.getKey())) {
+ if (state->getSymVal(I.getKey())) {
changed = true;
B = RefBFactory.Remove(B, I.getKey());
}
}
if (changed)
- state = state.set<RefBindings>(B);
+ state = state->set<RefBindings>(B);
return state;
}
-GRStateRef CFRefCount::Update(GRStateRef state, SymbolRef sym,
+const GRState * CFRefCount::Update(const GRState * state, SymbolRef sym,
RefVal V, ArgEffect E,
RefVal::Kind& hasErr) {
@@ -3308,7 +3356,7 @@ GRStateRef CFRefCount::Update(GRStateRef state, SymbolRef sym,
if (!isGCEnabled() && V.getKind() == RefVal::Released) {
V = V ^ RefVal::ErrorUseAfterRelease;
hasErr = V.getKind();
- return state.set<RefBindings>(sym, V);
+ return state->set<RefBindings>(sym, V);
}
switch (E) {
@@ -3330,7 +3378,7 @@ GRStateRef CFRefCount::Update(GRStateRef state, SymbolRef sym,
// The object immediately transitions to the released state.
V = V ^ RefVal::Released;
V.clearCounts();
- return state.set<RefBindings>(sym, V);
+ return state->set<RefBindings>(sym, V);
case RefVal::NotOwned:
V = V ^ RefVal::ErrorDeallocNotOwned;
hasErr = V.getKind();
@@ -3340,7 +3388,7 @@ GRStateRef CFRefCount::Update(GRStateRef state, SymbolRef sym,
case NewAutoreleasePool:
assert(!isGCEnabled());
- return state.add<AutoreleaseStack>(sym);
+ return state->add<AutoreleaseStack>(sym);
case MayEscape:
if (V.getKind() == RefVal::Owned) {
@@ -3364,7 +3412,7 @@ GRStateRef CFRefCount::Update(GRStateRef state, SymbolRef sym,
break;
case StopTracking:
- return state.remove<RefBindings>(sym);
+ return state->remove<RefBindings>(sym);
case IncRef:
switch (V.getKind()) {
@@ -3416,15 +3464,15 @@ GRStateRef CFRefCount::Update(GRStateRef state, SymbolRef sym,
}
break;
}
- return state.set<RefBindings>(sym, V);
+ return state->set<RefBindings>(sym, V);
}
//===----------------------------------------------------------------------===//
// Handle dead symbols and end-of-path.
//===----------------------------------------------------------------------===//
-std::pair<ExplodedNode<GRState>*, GRStateRef>
-CFRefCount::HandleAutoreleaseCounts(GRStateRef state, GenericNodeBuilder Bd,
+std::pair<ExplodedNode<GRState>*, const GRState *>
+CFRefCount::HandleAutoreleaseCounts(const GRState * state, GenericNodeBuilder Bd,
ExplodedNode<GRState>* Pred,
GRExprEngine &Eng,
SymbolRef Sym, RefVal V, bool &stop) {
@@ -3456,7 +3504,7 @@ CFRefCount::HandleAutoreleaseCounts(GRStateRef state, GenericNodeBuilder Bd,
V.setCount(Cnt - ACnt);
V.setAutoreleaseCount(0);
}
- state = state.set<RefBindings>(Sym, V);
+ state = state->set<RefBindings>(Sym, V);
ExplodedNode<GRState> *N = Bd.MakeNode(state, Pred);
stop = (N == 0);
return std::make_pair(N, state);
@@ -3466,7 +3514,7 @@ CFRefCount::HandleAutoreleaseCounts(GRStateRef state, GenericNodeBuilder Bd,
// Emit hard error.
stop = true;
V = V ^ RefVal::ErrorOverAutorelease;
- state = state.set<RefBindings>(Sym, V);
+ state = state->set<RefBindings>(Sym, V);
if (ExplodedNode<GRState> *N = Bd.MakeNode(state, Pred)) {
N->markAsSink();
@@ -3492,22 +3540,22 @@ CFRefCount::HandleAutoreleaseCounts(GRStateRef state, GenericNodeBuilder Bd,
return std::make_pair((ExplodedNode<GRState>*)0, state);
}
-GRStateRef
-CFRefCount::HandleSymbolDeath(GRStateRef state, SymbolRef sid, RefVal V,
+const GRState *
+CFRefCount::HandleSymbolDeath(const GRState * state, SymbolRef sid, RefVal V,
llvm::SmallVectorImpl<SymbolRef> &Leaked) {
bool hasLeak = V.isOwned() ||
((V.isNotOwned() || V.isReturnedOwned()) && V.getCount() > 0);
if (!hasLeak)
- return state.remove<RefBindings>(sid);
+ return state->remove<RefBindings>(sid);
Leaked.push_back(sid);
- return state.set<RefBindings>(sid, V ^ RefVal::ErrorLeak);
+ return state->set<RefBindings>(sid, V ^ RefVal::ErrorLeak);
}
ExplodedNode<GRState>*
-CFRefCount::ProcessLeaks(GRStateRef state,
+CFRefCount::ProcessLeaks(const GRState * state,
llvm::SmallVectorImpl<SymbolRef> &Leaked,
GenericNodeBuilder &Builder,
GRExprEngine& Eng,
@@ -3537,9 +3585,9 @@ CFRefCount::ProcessLeaks(GRStateRef state,
void CFRefCount::EvalEndPath(GRExprEngine& Eng,
GREndPathNodeBuilder<GRState>& Builder) {
- GRStateRef state(Builder.getState(), Eng.getStateManager());
+ const GRState *state = Builder.getState();
GenericNodeBuilder Bd(Builder);
- RefBindings B = state.get<RefBindings>();
+ RefBindings B = state->get<RefBindings>();
ExplodedNode<GRState> *Pred = 0;
for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
@@ -3552,7 +3600,7 @@ void CFRefCount::EvalEndPath(GRExprEngine& Eng,
return;
}
- B = state.get<RefBindings>();
+ B = state->get<RefBindings>();
llvm::SmallVector<SymbolRef, 10> Leaked;
for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I)
@@ -3566,11 +3614,10 @@ void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<GRState>& Dst,
GRStmtNodeBuilder<GRState>& Builder,
ExplodedNode<GRState>* Pred,
Stmt* S,
- const GRState* St,
+ const GRState* state,
SymbolReaper& SymReaper) {
- GRStateRef state(St, Eng.getStateManager());
- RefBindings B = state.get<RefBindings>();
+ RefBindings B = state->get<RefBindings>();
// Update counts from autorelease pools
for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
@@ -3588,7 +3635,7 @@ void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<GRState>& Dst,
}
}
- B = state.get<RefBindings>();
+ B = state->get<RefBindings>();
llvm::SmallVector<SymbolRef, 10> Leaked;
for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
@@ -3608,12 +3655,12 @@ void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<GRState>& Dst,
return;
// Now generate a new node that nukes the old bindings.
- RefBindings::Factory& F = state.get_context<RefBindings>();
+ RefBindings::Factory& F = state->get_context<RefBindings>();
for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
E = SymReaper.dead_end(); I!=E; ++I) B = F.Remove(B, *I);
- state = state.set<RefBindings>(B);
+ state = state->set<RefBindings>(B);
Builder.MakeNode(Dst, S, Pred, state);
}
diff --git a/lib/Analysis/CheckDeadStores.cpp b/lib/Analysis/CheckDeadStores.cpp
index 69433d6396a5..0f61a5ee916a 100644
--- a/lib/Analysis/CheckDeadStores.cpp
+++ b/lib/Analysis/CheckDeadStores.cpp
@@ -85,7 +85,7 @@ public:
const LiveVariables::AnalysisDataTy& AD,
const LiveVariables::ValTy& Live) {
- if (VD->hasLocalStorage() && !Live(VD, AD) && !VD->getAttr<UnusedAttr>())
+ if (VD->hasLocalStorage() && !Live(VD, AD) && !VD->getAttr<UnusedAttr>(Ctx))
Report(VD, dsk, Ex->getSourceRange().getBegin(),
Val->getSourceRange());
}
@@ -190,7 +190,7 @@ public:
// A dead initialization is a variable that is dead after it
// is initialized. We don't flag warnings for those variables
// marked 'unused'.
- if (!Live(V, AD) && V->getAttr<UnusedAttr>() == 0) {
+ if (!Live(V, AD) && V->getAttr<UnusedAttr>(Ctx) == 0) {
// Special case: check for initializations with constants.
//
// e.g. : int x = 0;
diff --git a/lib/Analysis/CheckNSError.cpp b/lib/Analysis/CheckNSError.cpp
index ff9da0f659c3..c91442b5e829 100644
--- a/lib/Analysis/CheckNSError.cpp
+++ b/lib/Analysis/CheckNSError.cpp
@@ -41,7 +41,7 @@ class VISIBILITY_HIDDEN NSErrorCheck : public BugType {
bool CheckNSErrorArgument(QualType ArgTy);
bool CheckCFErrorArgument(QualType ArgTy);
- void CheckParamDeref(VarDecl* V, GRStateRef state, BugReporter& BR);
+ void CheckParamDeref(VarDecl* V, const GRState *state, BugReporter& BR);
void EmitRetTyWarning(BugReporter& BR, Decl& CodeDecl);
@@ -94,8 +94,7 @@ void NSErrorCheck::FlushReports(BugReporter& BR) {
// Scan the parameters for an implicit null dereference.
for (llvm::SmallVectorImpl<VarDecl*>::iterator I=ErrorParams.begin(),
E=ErrorParams.end(); I!=E; ++I)
- CheckParamDeref(*I, GRStateRef((*RI)->getState(),Eng.getStateManager()),
- BR);
+ CheckParamDeref(*I, (*RI)->getState(), BR);
}
}
@@ -186,13 +185,13 @@ bool NSErrorCheck::CheckCFErrorArgument(QualType ArgTy) {
return TT->getDecl()->getIdentifier() == II;
}
-void NSErrorCheck::CheckParamDeref(VarDecl* Param, GRStateRef rootState,
+void NSErrorCheck::CheckParamDeref(VarDecl* Param, const GRState *rootState,
BugReporter& BR) {
- SVal ParamL = rootState.GetLValue(Param);
+ SVal ParamL = rootState->getLValue(Param);
const MemRegion* ParamR = cast<loc::MemRegionVal>(ParamL).getRegionAs<VarRegion>();
assert (ParamR && "Parameters always have VarRegions.");
- SVal ParamSVal = rootState.GetSVal(ParamR);
+ SVal ParamSVal = rootState->getSVal(ParamR);
// FIXME: For now assume that ParamSVal is symbolic. We need to generalize
// this later.
@@ -204,8 +203,8 @@ void NSErrorCheck::CheckParamDeref(VarDecl* Param, GRStateRef rootState,
for (GRExprEngine::null_deref_iterator I=Eng.implicit_null_derefs_begin(),
E=Eng.implicit_null_derefs_end(); I!=E; ++I) {
- GRStateRef state = GRStateRef((*I)->getState(), Eng.getStateManager());
- const SVal* X = state.get<GRState::NullDerefTag>();
+ const GRState *state = (*I)->getState();
+ const SVal* X = state->get<GRState::NullDerefTag>();
if (!X || X->getAsSymbol() != ParamSym)
continue;
diff --git a/lib/Analysis/CheckObjCDealloc.cpp b/lib/Analysis/CheckObjCDealloc.cpp
index f50d7a19c420..2ba7d868e90b 100644
--- a/lib/Analysis/CheckObjCDealloc.cpp
+++ b/lib/Analysis/CheckObjCDealloc.cpp
@@ -109,7 +109,7 @@ void clang::CheckObjCDealloc(ObjCImplementationDecl* D,
QualType T = ID->getType();
if (!Ctx.isObjCObjectPointerType(T) ||
- ID->getAttr<IBOutletAttr>()) // Skip IBOutlets.
+ ID->getAttr<IBOutletAttr>(Ctx)) // Skip IBOutlets.
continue;
containsPointerIvar = true;
diff --git a/lib/Analysis/CheckObjCUnusedIVars.cpp b/lib/Analysis/CheckObjCUnusedIVars.cpp
index 7979f9c942e6..92c50e2a9185 100644
--- a/lib/Analysis/CheckObjCUnusedIVars.cpp
+++ b/lib/Analysis/CheckObjCUnusedIVars.cpp
@@ -74,7 +74,7 @@ void clang::CheckObjCUnusedIvar(ObjCImplementationDecl* D, BugReporter& BR) {
continue;
// Skip IB Outlets.
- if (ID->getAttr<IBOutletAttr>())
+ if (ID->getAttr<IBOutletAttr>(Ctx))
continue;
M[ID] = Unused;
diff --git a/lib/Analysis/Environment.cpp b/lib/Analysis/Environment.cpp
index 2bc071a265ed..7ada6d809bd4 100644
--- a/lib/Analysis/Environment.cpp
+++ b/lib/Analysis/Environment.cpp
@@ -18,7 +18,7 @@
using namespace clang;
-SVal Environment::GetSVal(Stmt* E, BasicValueFactory& BasicVals) const {
+SVal Environment::GetSVal(const Stmt *E, BasicValueFactory& BasicVals) const {
for (;;) {
@@ -34,7 +34,7 @@ SVal Environment::GetSVal(Stmt* E, BasicValueFactory& BasicVals) const {
continue;
case Stmt::CharacterLiteralClass: {
- CharacterLiteral* C = cast<CharacterLiteral>(E);
+ const CharacterLiteral* C = cast<CharacterLiteral>(E);
return NonLoc::MakeVal(BasicVals, C->getValue(), C->getType());
}
@@ -48,7 +48,7 @@ SVal Environment::GetSVal(Stmt* E, BasicValueFactory& BasicVals) const {
case Stmt::ImplicitCastExprClass:
case Stmt::CStyleCastExprClass: {
- CastExpr* C = cast<CastExpr>(E);
+ const CastExpr* C = cast<CastExpr>(E);
QualType CT = C->getType();
if (CT->isVoidType())
@@ -69,7 +69,8 @@ SVal Environment::GetSVal(Stmt* E, BasicValueFactory& BasicVals) const {
return LookupExpr(E);
}
-SVal Environment::GetBlkExprSVal(Stmt* E, BasicValueFactory& BasicVals) const {
+SVal Environment::GetBlkExprSVal(const Stmt *E,
+ BasicValueFactory& BasicVals) const {
while (1) {
switch (E->getStmtClass()) {
@@ -78,7 +79,7 @@ SVal Environment::GetBlkExprSVal(Stmt* E, BasicValueFactory& BasicVals) const {
continue;
case Stmt::CharacterLiteralClass: {
- CharacterLiteral* C = cast<CharacterLiteral>(E);
+ const CharacterLiteral* C = cast<CharacterLiteral>(E);
return NonLoc::MakeVal(BasicVals, C->getValue(), C->getType());
}
@@ -92,8 +93,9 @@ SVal Environment::GetBlkExprSVal(Stmt* E, BasicValueFactory& BasicVals) const {
}
}
-Environment EnvironmentManager::BindExpr(const Environment& Env, Stmt* E,SVal V,
- bool isBlkExpr, bool Invalidate) {
+Environment EnvironmentManager::BindExpr(const Environment& Env, const Stmt* E,
+ SVal V, bool isBlkExpr,
+ bool Invalidate) {
assert (E);
if (V.isUnknown()) {
@@ -136,7 +138,7 @@ EnvironmentManager::RemoveDeadBindings(Environment Env, Stmt* Loc,
// Iterate over the block-expr bindings.
for (Environment::beb_iterator I = Env.beb_begin(), E = Env.beb_end();
I != E; ++I) {
- Stmt* BlkExpr = I.getKey();
+ const Stmt *BlkExpr = I.getKey();
if (SymReaper.isLive(Loc, BlkExpr)) {
SVal X = I.getData();
@@ -147,7 +149,7 @@ EnvironmentManager::RemoveDeadBindings(Environment Env, Stmt* Loc,
// Mark all symbols in the block expr's value live.
MarkLiveCallback cb(SymReaper);
- StateMgr.scanReachableSymbols(X, state, cb);
+ state->scanReachableSymbols(X, cb);
} else {
// The block expr is dead.
SVal X = I.getData();
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index 7a8fef58bb21..87432d4815a8 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -177,14 +177,13 @@ const GRState* GRExprEngine::getInitialState() {
QualType T = PD->getType();
if (T->isIntegerType())
if (const MemRegion *R = StateMgr.getRegion(PD)) {
- SVal V = GetSVal(state, loc::MemRegionVal(R));
+ SVal V = state->getSVal(loc::MemRegionVal(R));
SVal Constraint = EvalBinOp(state, BinaryOperator::GT, V,
ValMgr.makeZeroVal(T),
getContext().IntTy);
- bool isFeasible = false;
- const GRState *newState = Assume(state, Constraint, true,
- isFeasible);
- if (newState) state = newState;
+
+ if (const GRState *newState = state->assume(Constraint, true))
+ state = newState;
}
}
@@ -310,7 +309,7 @@ void GRExprEngine::Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst) {
}
else if (B->getOpcode() == BinaryOperator::Comma) {
const GRState* state = GetState(Pred);
- MakeNode(Dst, B, Pred, BindExpr(state, B, GetSVal(state, B->getRHS())));
+ MakeNode(Dst, B, Pred, state->bindExpr(B, state->getSVal(B->getRHS())));
break;
}
@@ -426,7 +425,7 @@ void GRExprEngine::Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst) {
if (Expr* LastExpr = dyn_cast<Expr>(*SE->getSubStmt()->body_rbegin())) {
const GRState* state = GetState(Pred);
- MakeNode(Dst, SE, Pred, BindExpr(state, SE, GetSVal(state, LastExpr)));
+ MakeNode(Dst, SE, Pred, state->bindExpr(SE, state->getSVal(LastExpr)));
}
else
Dst.Add(Pred);
@@ -506,8 +505,8 @@ void GRExprEngine::VisitLValue(Expr* Ex, NodeTy* Pred, NodeSet& Dst) {
case Stmt::StringLiteralClass: {
const GRState* state = GetState(Pred);
- SVal V = StateMgr.GetLValue(state, cast<StringLiteral>(Ex));
- MakeNode(Dst, Ex, Pred, BindExpr(state, Ex, V));
+ SVal V = state->getLValue(cast<StringLiteral>(Ex));
+ MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V));
return;
}
@@ -579,7 +578,7 @@ const GRState* GRExprEngine::MarkBranch(const GRState* state,
(Op == BinaryOperator::LOr && !branchTaken)
? B->getRHS() : B->getLHS();
- return BindBlkExpr(state, B, UndefinedVal(Ex));
+ return state->bindBlkExpr(B, UndefinedVal(Ex));
}
case Stmt::ConditionalOperatorClass: { // ?:
@@ -596,7 +595,7 @@ const GRState* GRExprEngine::MarkBranch(const GRState* state,
else
Ex = C->getRHS();
- return BindBlkExpr(state, C, UndefinedVal(Ex));
+ return state->bindBlkExpr(C, UndefinedVal(Ex));
}
case Stmt::ChooseExprClass: { // ?:
@@ -604,7 +603,7 @@ const GRState* GRExprEngine::MarkBranch(const GRState* state,
ChooseExpr* C = cast<ChooseExpr>(Terminator);
Expr* Ex = branchTaken ? C->getLHS() : C->getRHS();
- return BindBlkExpr(state, C, UndefinedVal(Ex));
+ return state->bindBlkExpr(C, UndefinedVal(Ex));
}
}
}
@@ -645,7 +644,7 @@ static SVal RecoverCastedSymbol(GRStateManager& StateMgr, const GRState* state,
if (!bitsInit || !T->isIntegerType() || Ctx.getTypeSize(T) > bits)
return UnknownVal();
- return StateMgr.GetSVal(state, Ex);
+ return state->getSVal(Ex);
}
void GRExprEngine::ProcessBranch(Stmt* Condition, Stmt* Term,
@@ -665,7 +664,7 @@ void GRExprEngine::ProcessBranch(Stmt* Condition, Stmt* Term,
Condition->getLocStart(),
"Error evaluating branch");
- SVal V = GetSVal(PrevState, Condition);
+ SVal V = PrevState->getSVal(Condition);
switch (V.getBaseKind()) {
default:
@@ -708,21 +707,13 @@ void GRExprEngine::ProcessBranch(Stmt* Condition, Stmt* Term,
}
// Process the true branch.
-
- bool isFeasible = false;
- const GRState* state = Assume(PrevState, V, true, isFeasible);
-
- if (isFeasible)
+ if (const GRState *state = PrevState->assume(V, true))
builder.generateNode(MarkBranch(state, Term, true), true);
else
builder.markInfeasible(true);
// Process the false branch.
-
- isFeasible = false;
- state = Assume(PrevState, V, false, isFeasible);
-
- if (isFeasible)
+ if (const GRState *state = PrevState->assume(V, false))
builder.generateNode(MarkBranch(state, Term, false), false);
else
builder.markInfeasible(false);
@@ -732,8 +723,8 @@ void GRExprEngine::ProcessBranch(Stmt* Condition, Stmt* Term,
/// nodes by processing the 'effects' of a computed goto jump.
void GRExprEngine::ProcessIndirectGoto(IndirectGotoNodeBuilder& builder) {
- const GRState* state = builder.getState();
- SVal V = GetSVal(state, builder.getTarget());
+ const GRState *state = builder.getState();
+ SVal V = state->getSVal(builder.getTarget());
// Three possibilities:
//
@@ -779,18 +770,16 @@ void GRExprEngine::VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R,
assert (Ex == CurrentStmt && getCFG().isBlkExpr(Ex));
const GRState* state = GetState(Pred);
- SVal X = GetBlkExprSVal(state, Ex);
+ SVal X = state->getBlkExprSVal(Ex);
assert (X.isUndef());
- Expr* SE = (Expr*) cast<UndefinedVal>(X).getData();
-
- assert (SE);
-
- X = GetBlkExprSVal(state, SE);
+ Expr *SE = (Expr*) cast<UndefinedVal>(X).getData();
+ assert(SE);
+ X = state->getBlkExprSVal(SE);
// Make sure that we invalidate the previous binding.
- MakeNode(Dst, Ex, Pred, StateMgr.BindExpr(state, Ex, X, true, true));
+ MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, X, true, true));
}
/// ProcessSwitch - Called by GRCoreEngine. Used to generate successor
@@ -799,7 +788,7 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) {
typedef SwitchNodeBuilder::iterator iterator;
const GRState* state = builder.getState();
Expr* CondE = builder.getCondition();
- SVal CondV = GetSVal(state, CondE);
+ SVal CondV = state->getSVal(CondE);
if (CondV.isUndef()) {
NodeTy* N = builder.generateDefaultCaseNode(state, true);
@@ -808,7 +797,7 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) {
}
const GRState* DefaultSt = state;
- bool DefaultFeasible = false;
+ bool defaultIsFeasible = false;
for (iterator I = builder.begin(), EI = builder.end(); I != EI; ++I) {
CaseStmt* Case = cast<CaseStmt>(I.getCase());
@@ -846,11 +835,8 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) {
getContext().IntTy);
// Now "assume" that the case matches.
- bool isFeasible = false;
- const GRState* StNew = Assume(state, Res, true, isFeasible);
-
- if (isFeasible) {
- builder.generateCaseStmtNode(I, StNew);
+ if (const GRState* stateNew = state->assume(Res, true)) {
+ builder.generateCaseStmtNode(I, stateNew);
// If CondV evaluates to a constant, then we know that this
// is the *only* case that we can take, so stop evaluating the
@@ -861,13 +847,9 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) {
// Now "assume" that the case doesn't match. Add this state
// to the default state (if it is feasible).
-
- isFeasible = false;
- StNew = Assume(DefaultSt, Res, false, isFeasible);
-
- if (isFeasible) {
- DefaultFeasible = true;
- DefaultSt = StNew;
+ if (const GRState *stateNew = DefaultSt->assume(Res, false)) {
+ defaultIsFeasible = true;
+ DefaultSt = stateNew;
}
// Concretize the next value in the range.
@@ -882,7 +864,7 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) {
// If we reach here, than we know that the default branch is
// possible.
- if (DefaultFeasible) builder.generateDefaultCaseNode(DefaultSt);
+ if (defaultIsFeasible) builder.generateDefaultCaseNode(DefaultSt);
}
//===----------------------------------------------------------------------===//
@@ -892,28 +874,27 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) {
void GRExprEngine::VisitLogicalExpr(BinaryOperator* B, NodeTy* Pred,
NodeSet& Dst) {
- assert (B->getOpcode() == BinaryOperator::LAnd ||
- B->getOpcode() == BinaryOperator::LOr);
+ assert(B->getOpcode() == BinaryOperator::LAnd ||
+ B->getOpcode() == BinaryOperator::LOr);
- assert (B == CurrentStmt && getCFG().isBlkExpr(B));
+ assert(B == CurrentStmt && getCFG().isBlkExpr(B));
const GRState* state = GetState(Pred);
- SVal X = GetBlkExprSVal(state, B);
-
- assert (X.isUndef());
+ SVal X = state->getBlkExprSVal(B);
+ assert(X.isUndef());
Expr* Ex = (Expr*) cast<UndefinedVal>(X).getData();
- assert (Ex);
+ assert(Ex);
if (Ex == B->getRHS()) {
- X = GetBlkExprSVal(state, Ex);
+ X = state->getBlkExprSVal(Ex);
// Handle undefined values.
if (X.isUndef()) {
- MakeNode(Dst, B, Pred, BindBlkExpr(state, B, X));
+ MakeNode(Dst, B, Pred, state->bindBlkExpr(B, X));
return;
}
@@ -922,29 +903,19 @@ void GRExprEngine::VisitLogicalExpr(BinaryOperator* B, NodeTy* Pred,
// or 1. Alternatively, we could take a lazy approach, and calculate this
// value later when necessary. We don't have the machinery in place for
// this right now, and since most logical expressions are used for branches,
- // the payoff is not likely to be large. Instead, we do eager evaluation.
-
- bool isFeasible = false;
- const GRState* NewState = Assume(state, X, true, isFeasible);
-
- if (isFeasible)
- MakeNode(Dst, B, Pred,
- BindBlkExpr(NewState, B, MakeConstantVal(1U, B)));
+ // the payoff is not likely to be large. Instead, we do eager evaluation.
+ if (const GRState *newState = state->assume(X, true))
+ MakeNode(Dst, B, Pred, newState->bindBlkExpr(B, MakeConstantVal(1U, B)));
- isFeasible = false;
- NewState = Assume(state, X, false, isFeasible);
-
- if (isFeasible)
- MakeNode(Dst, B, Pred,
- BindBlkExpr(NewState, B, MakeConstantVal(0U, B)));
+ if (const GRState *newState = state->assume(X, false))
+ MakeNode(Dst, B, Pred, newState->bindBlkExpr(B, MakeConstantVal(0U, B)));
}
else {
// We took the LHS expression. Depending on whether we are '&&' or
// '||' we know what the value of the expression is via properties of
// the short-circuiting.
-
X = MakeConstantVal( B->getOpcode() == BinaryOperator::LAnd ? 0U : 1U, B);
- MakeNode(Dst, B, Pred, BindBlkExpr(state, B, X));
+ MakeNode(Dst, B, Pred, state->bindBlkExpr(B, X));
}
}
@@ -961,10 +932,10 @@ void GRExprEngine::VisitDeclRefExpr(DeclRefExpr* Ex, NodeTy* Pred, NodeSet& Dst,
if (const VarDecl* VD = dyn_cast<VarDecl>(D)) {
- SVal V = StateMgr.GetLValue(state, VD);
+ SVal V = state->getLValue(VD);
if (asLValue)
- MakeNode(Dst, Ex, Pred, BindExpr(state, Ex, V),
+ MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V),
ProgramPoint::PostLValueKind);
else
EvalLoad(Dst, Ex, Pred, state, V);
@@ -975,13 +946,13 @@ void GRExprEngine::VisitDeclRefExpr(DeclRefExpr* Ex, NodeTy* Pred, NodeSet& Dst,
BasicValueFactory& BasicVals = StateMgr.getBasicVals();
SVal V = nonloc::ConcreteInt(BasicVals.getValue(ED->getInitVal()));
- MakeNode(Dst, Ex, Pred, BindExpr(state, Ex, V));
+ MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V));
return;
} else if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(D)) {
assert(asLValue);
SVal V = ValMgr.getFunctionPointer(FD);
- MakeNode(Dst, Ex, Pred, BindExpr(state, Ex, V),
+ MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V),
ProgramPoint::PostLValueKind);
return;
}
@@ -1014,12 +985,11 @@ void GRExprEngine::VisitArraySubscriptExpr(ArraySubscriptExpr* A, NodeTy* Pred,
for (NodeSet::iterator I2=Tmp2.begin(), E2=Tmp2.end(); I2!=E2; ++I2) {
const GRState* state = GetState(*I2);
- SVal V = StateMgr.GetLValue(state, A->getType(),
- GetSVal(state, Base),
- GetSVal(state, Idx));
+ SVal V = state->getLValue(A->getType(), state->getSVal(Base),
+ state->getSVal(Idx));
if (asLValue)
- MakeNode(Dst, A, *I2, BindExpr(state, A, V),
+ MakeNode(Dst, A, *I2, state->bindExpr(A, V),
ProgramPoint::PostLValueKind);
else
EvalLoad(Dst, A, *I2, state, V);
@@ -1048,10 +1018,10 @@ void GRExprEngine::VisitMemberExpr(MemberExpr* M, NodeTy* Pred,
// FIXME: Should we insert some assumption logic in here to determine
// if "Base" is a valid piece of memory? Before we put this assumption
// later when using FieldOffset lvals (which we no longer have).
- SVal L = StateMgr.GetLValue(state, GetSVal(state, Base), Field);
+ SVal L = state->getLValue(state->getSVal(Base), Field);
if (asLValue)
- MakeNode(Dst, M, *I, BindExpr(state, M, L),
+ MakeNode(Dst, M, *I, state->bindExpr(M, L),
ProgramPoint::PostLValueKind);
else
EvalLoad(Dst, M, *I, state, L);
@@ -1135,11 +1105,11 @@ void GRExprEngine::EvalLoad(NodeSet& Dst, Expr* Ex, NodeTy* Pred,
if (location.isUnknown()) {
// This is important. We must nuke the old binding.
- MakeNode(Dst, Ex, Pred, BindExpr(state, Ex, UnknownVal()), K, tag);
+ MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, UnknownVal()), K, tag);
}
else {
- SVal V = GetSVal(state, cast<Loc>(location), Ex->getType());
- MakeNode(Dst, Ex, Pred, BindExpr(state, Ex, V), K, tag);
+ SVal V = state->getSVal(cast<Loc>(location), Ex->getType());
+ MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V), K, tag);
}
}
@@ -1189,19 +1159,15 @@ GRExprEngine::NodeTy* GRExprEngine::EvalLocation(Stmt* Ex, NodeTy* Pred,
Loc LV = cast<Loc>(location);
// "Assume" that the pointer is not NULL.
- bool isFeasibleNotNull = false;
- const GRState* StNotNull = Assume(state, LV, true, isFeasibleNotNull);
+ const GRState *StNotNull = state->assume(LV, true);
// "Assume" that the pointer is NULL.
- bool isFeasibleNull = false;
- GRStateRef StNull = GRStateRef(Assume(state, LV, false, isFeasibleNull),
- getStateManager());
+ const GRState *StNull = state->assume(LV, false);
- if (isFeasibleNull) {
-
+ if (StNull) {
// Use the Generic Data Map to mark in the state what lval was null.
const SVal* PersistentLV = getBasicVals().getPersistentSVal(LV);
- StNull = StNull.set<GRState::NullDerefTag>(PersistentLV);
+ StNull = StNull->set<GRState::NullDerefTag>(PersistentLV);
// We don't use "MakeNode" here because the node will be a sink
// and we have no intention of processing it later.
@@ -1209,17 +1175,15 @@ GRExprEngine::NodeTy* GRExprEngine::EvalLocation(Stmt* Ex, NodeTy* Pred,
Builder->generateNode(Ex, StNull, Pred,
ProgramPoint::PostNullCheckFailedKind);
- if (NullNode) {
-
- NullNode->markAsSink();
-
- if (isFeasibleNotNull) ImplicitNullDeref.insert(NullNode);
+ if (NullNode) {
+ NullNode->markAsSink();
+ if (StNotNull) ImplicitNullDeref.insert(NullNode);
else ExplicitNullDeref.insert(NullNode);
}
}
- if (!isFeasibleNotNull)
- return 0;
+ if (!StNotNull)
+ return NULL;
// Check for out-of-bound array access.
if (isa<loc::MemRegionVal>(LV)) {
@@ -1231,15 +1195,12 @@ GRExprEngine::NodeTy* GRExprEngine::EvalLocation(Stmt* Ex, NodeTy* Pred,
SVal NumElements = getStoreManager().getSizeInElements(StNotNull,
ER->getSuperRegion());
- bool isFeasibleInBound = false;
- const GRState* StInBound = AssumeInBound(StNotNull, Idx, NumElements,
- true, isFeasibleInBound);
-
- bool isFeasibleOutBound = false;
- const GRState* StOutBound = AssumeInBound(StNotNull, Idx, NumElements,
- false, isFeasibleOutBound);
+ const GRState * StInBound = StNotNull->assumeInBound(Idx, NumElements,
+ true);
+ const GRState* StOutBound = StNotNull->assumeInBound(Idx, NumElements,
+ false);
- if (isFeasibleOutBound) {
+ if (StOutBound) {
// Report warning. Make sink node manually.
NodeTy* OOBNode =
Builder->generateNode(Ex, StOutBound, Pred,
@@ -1248,16 +1209,16 @@ GRExprEngine::NodeTy* GRExprEngine::EvalLocation(Stmt* Ex, NodeTy* Pred,
if (OOBNode) {
OOBNode->markAsSink();
- if (isFeasibleInBound)
+ if (StInBound)
ImplicitOOBMemAccesses.insert(OOBNode);
else
ExplicitOOBMemAccesses.insert(OOBNode);
}
}
- if (!isFeasibleInBound)
- return 0;
-
+ if (!StInBound)
+ return NULL;
+
StNotNull = StInBound;
}
}
@@ -1319,10 +1280,9 @@ static bool EvalOSAtomicCompareAndSwap(ExplodedNodeSet<GRState>& Dst,
const void *OSAtomicStoreTag = &magic_store;
// Load 'theValue'.
- GRStateManager &StateMgr = Engine.getStateManager();
const GRState *state = Pred->getState();
ExplodedNodeSet<GRState> Tmp;
- SVal location = StateMgr.GetSVal(state, theValueExpr);
+ SVal location = state->getSVal(theValueExpr);
Engine.EvalLoad(Tmp, theValueExpr, Pred, state, location, OSAtomicLoadTag);
for (ExplodedNodeSet<GRState>::iterator I = Tmp.begin(), E = Tmp.end();
@@ -1330,24 +1290,22 @@ static bool EvalOSAtomicCompareAndSwap(ExplodedNodeSet<GRState>& Dst,
ExplodedNode<GRState> *N = *I;
const GRState *stateLoad = N->getState();
- SVal theValueVal = StateMgr.GetSVal(stateLoad, theValueExpr);
- SVal oldValueVal = StateMgr.GetSVal(stateLoad, oldValueExpr);
+ SVal theValueVal = stateLoad->getSVal(theValueExpr);
+ SVal oldValueVal = stateLoad->getSVal(oldValueExpr);
// Perform the comparison.
SVal Cmp = Engine.EvalBinOp(stateLoad,
BinaryOperator::EQ, theValueVal, oldValueVal,
Engine.getContext().IntTy);
- bool isFeasible = false;
- const GRState *stateEqual = StateMgr.Assume(stateLoad, Cmp, true,
- isFeasible);
+
+ const GRState *stateEqual = stateLoad->assume(Cmp, true);
// Were they equal?
- if (isFeasible) {
+ if (stateEqual) {
// Perform the store.
ExplodedNodeSet<GRState> TmpStore;
Engine.EvalStore(TmpStore, theValueExpr, N, stateEqual, location,
- StateMgr.GetSVal(stateEqual, newValueExpr),
- OSAtomicStoreTag);
+ stateEqual->getSVal(newValueExpr), OSAtomicStoreTag);
// Now bind the result of the comparison.
for (ExplodedNodeSet<GRState>::iterator I2 = TmpStore.begin(),
@@ -1355,18 +1313,14 @@ static bool EvalOSAtomicCompareAndSwap(ExplodedNodeSet<GRState>& Dst,
ExplodedNode<GRState> *predNew = *I2;
const GRState *stateNew = predNew->getState();
SVal Res = Engine.getValueManager().makeTruthVal(true, CE->getType());
- Engine.MakeNode(Dst, CE, predNew, Engine.BindExpr(stateNew, CE, Res));
+ Engine.MakeNode(Dst, CE, predNew, stateNew->bindExpr(CE, Res));
}
}
// Were they not equal?
- isFeasible = false;
- const GRState *stateNotEqual = StateMgr.Assume(stateLoad, Cmp, false,
- isFeasible);
-
- if (isFeasible) {
+ if (const GRState *stateNotEqual = stateLoad->assume(Cmp, false)) {
SVal Res = Engine.getValueManager().makeTruthVal(false, CE->getType());
- Engine.MakeNode(Dst, CE, N, Engine.BindExpr(stateNotEqual, CE, Res));
+ Engine.MakeNode(Dst, CE, N, stateNotEqual->bindExpr(CE, Res));
}
}
@@ -1460,7 +1414,7 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, NodeTy* Pred,
for (NodeSet::iterator DI = DstTmp.begin(), DE = DstTmp.end(); DI!=DE; ++DI) {
const GRState* state = GetState(*DI);
- SVal L = GetSVal(state, Callee);
+ SVal L = state->getSVal(Callee);
// FIXME: Add support for symbolic function calls (calls involving
// function pointer values that are symbolic).
@@ -1483,7 +1437,8 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, NodeTy* Pred,
SaveAndRestore<bool> OldSink(Builder->BuildSinks);
const FunctionDecl* FD = L.getAsFunctionDecl();
if (FD) {
- if (FD->getAttr<NoReturnAttr>() || FD->getAttr<AnalyzerNoReturnAttr>())
+ if (FD->getAttr<NoReturnAttr>(getContext()) ||
+ FD->getAttr<AnalyzerNoReturnAttr>(getContext()))
Builder->BuildSinks = true;
else {
// HACK: Some functions are not marked noreturn, and don't return.
@@ -1504,7 +1459,7 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, NodeTy* Pred,
if (!memcmp(s, "panic", 5)) Builder->BuildSinks = true;
else if (!memcmp(s, "error", 5)) {
if (CE->getNumArgs() > 0) {
- SVal X = GetSVal(state, *CE->arg_begin());
+ SVal X = state->getSVal(*CE->arg_begin());
// FIXME: use Assume to inspect the possible symbolic value of
// X. Also check the specific signature of error().
nonloc::ConcreteInt* CI = dyn_cast<nonloc::ConcreteInt>(&X);
@@ -1571,8 +1526,8 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, NodeTy* Pred,
case Builtin::BI__builtin_expect: {
// For __builtin_expect, just return the value of the subexpression.
assert (CE->arg_begin() != CE->arg_end());
- SVal X = GetSVal(state, *(CE->arg_begin()));
- MakeNode(Dst, CE, *DI, BindExpr(state, CE, X));
+ SVal X = state->getSVal(*(CE->arg_begin()));
+ MakeNode(Dst, CE, *DI, state->bindExpr(CE, X));
continue;
}
@@ -1585,10 +1540,10 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, NodeTy* Pred,
// Set the extent of the region in bytes. This enables us to use the
// SVal of the argument directly. If we save the extent in bits, we
// cannot represent values like symbol*8.
- SVal Extent = GetSVal(state, *(CE->arg_begin()));
+ SVal Extent = state->getSVal(*(CE->arg_begin()));
state = getStoreManager().setExtent(state, R, Extent);
- MakeNode(Dst, CE, *DI, BindExpr(state, CE, loc::MemRegionVal(R)));
+ MakeNode(Dst, CE, *DI, state->bindExpr(CE, loc::MemRegionVal(R)));
continue;
}
@@ -1604,7 +1559,7 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, NodeTy* Pred,
for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end();
I != E; ++I) {
- if (GetSVal(GetState(*DI), *I).isUndef()) {
+ if (GetState(*DI)->getSVal(*I).isUndef()) {
NodeTy* N = Builder->generateNode(CE, GetState(*DI), *DI);
if (N) {
@@ -1656,22 +1611,18 @@ void GRExprEngine::EvalEagerlyAssume(NodeSet &Dst, NodeSet &Src, Expr *Ex) {
}
const GRState* state = Pred->getState();
- SVal V = GetSVal(state, Ex);
+ SVal V = state->getSVal(Ex);
if (isa<nonloc::SymExprVal>(V)) {
// First assume that the condition is true.
- bool isFeasible = false;
- const GRState *stateTrue = Assume(state, V, true, isFeasible);
- if (isFeasible) {
- stateTrue = BindExpr(stateTrue, Ex, MakeConstantVal(1U, Ex));
+ if (const GRState *stateTrue = state->assume(V, true)) {
+ stateTrue = stateTrue->bindExpr(Ex, MakeConstantVal(1U, Ex));
Dst.Add(Builder->generateNode(PostStmtCustom(Ex, &EagerlyAssumeTag),
stateTrue, Pred));
}
// Next, assume that the condition is false.
- isFeasible = false;
- const GRState *stateFalse = Assume(state, V, false, isFeasible);
- if (isFeasible) {
- stateFalse = BindExpr(stateFalse, Ex, MakeConstantVal(0U, Ex));
+ if (const GRState *stateFalse = state->assume(V, false)) {
+ stateFalse = stateFalse->bindExpr(Ex, MakeConstantVal(0U, Ex));
Dst.Add(Builder->generateNode(PostStmtCustom(Ex, &EagerlyAssumeTag),
stateFalse, Pred));
}
@@ -1695,11 +1646,11 @@ void GRExprEngine::VisitObjCIvarRefExpr(ObjCIvarRefExpr* Ex,
for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
const GRState* state = GetState(*I);
- SVal BaseVal = GetSVal(state, Base);
- SVal location = StateMgr.GetLValue(state, Ex->getDecl(), BaseVal);
+ SVal BaseVal = state->getSVal(Base);
+ SVal location = state->getLValue(Ex->getDecl(), BaseVal);
if (asLValue)
- MakeNode(Dst, Ex, *I, BindExpr(state, Ex, location));
+ MakeNode(Dst, Ex, *I, state->bindExpr(Ex, location));
else
EvalLoad(Dst, Ex, *I, state, location);
}
@@ -1743,7 +1694,7 @@ void GRExprEngine::VisitObjCForCollectionStmt(ObjCForCollectionStmt* S,
if (DeclStmt* DS = dyn_cast<DeclStmt>(elem)) {
VarDecl* ElemD = cast<VarDecl>(DS->getSingleDecl());
assert (ElemD->getInit() == 0);
- ElementV = getStateManager().GetLValue(GetState(Pred), ElemD);
+ ElementV = GetState(Pred)->getLValue(ElemD);
VisitObjCForCollectionStmtAux(S, Pred, Dst, ElementV);
return;
}
@@ -1753,7 +1704,7 @@ void GRExprEngine::VisitObjCForCollectionStmt(ObjCForCollectionStmt* S,
for (NodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I!=E; ++I) {
const GRState* state = GetState(*I);
- VisitObjCForCollectionStmtAux(S, *I, Dst, GetSVal(state, elem));
+ VisitObjCForCollectionStmtAux(S, *I, Dst, state->getSVal(elem));
}
}
@@ -1771,16 +1722,16 @@ void GRExprEngine::VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S,
if (!Pred)
return;
- GRStateRef state = GRStateRef(GetState(Pred), getStateManager());
+ const GRState *state = GetState(Pred);
// Handle the case where the container still has elements.
QualType IntTy = getContext().IntTy;
SVal TrueV = NonLoc::MakeVal(getBasicVals(), 1, IntTy);
- GRStateRef hasElems = state.BindExpr(S, TrueV);
+ const GRState *hasElems = state->bindExpr(S, TrueV);
// Handle the case where the container has no elements.
SVal FalseV = NonLoc::MakeVal(getBasicVals(), 0, IntTy);
- GRStateRef noElems = state.BindExpr(S, FalseV);
+ const GRState *noElems = state->bindExpr(S, FalseV);
if (loc::MemRegionVal* MV = dyn_cast<loc::MemRegionVal>(&ElementV))
if (const TypedRegion* R = dyn_cast<TypedRegion>(MV->getRegion())) {
@@ -1792,11 +1743,11 @@ void GRExprEngine::VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S,
unsigned Count = Builder->getCurrentBlockCount();
SymbolRef Sym = SymMgr.getConjuredSymbol(elem, T, Count);
SVal V = Loc::MakeVal(getStoreManager().getRegionManager().getSymbolicRegion(Sym));
- hasElems = hasElems.BindLoc(ElementV, V);
+ hasElems = hasElems->bindLoc(ElementV, V);
// Bind the location to 'nil' on the false branch.
SVal nilV = loc::ConcreteInt(getBasicVals().getValue(0, T));
- noElems = noElems.BindLoc(ElementV, nilV);
+ noElems = noElems->bindLoc(ElementV, nilV);
}
// Create the new nodes.
@@ -1858,7 +1809,7 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME,
if (Expr* Receiver = ME->getReceiver()) {
- SVal L = GetSVal(state, Receiver);
+ SVal L = state->getSVal(Receiver);
// Check for undefined control-flow.
if (L.isUndef()) {
@@ -1873,14 +1824,12 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME,
}
// "Assume" that the receiver is not NULL.
- bool isFeasibleNotNull = false;
- const GRState *StNotNull = Assume(state, L, true, isFeasibleNotNull);
+ const GRState *StNotNull = state->assume(L, true);
// "Assume" that the receiver is NULL.
- bool isFeasibleNull = false;
- const GRState *StNull = Assume(state, L, false, isFeasibleNull);
+ const GRState *StNull = state->assume(L, false);
- if (isFeasibleNull) {
+ if (StNull) {
QualType RetTy = ME->getType();
// Check if the receiver was nil and the return value a struct.
@@ -1894,7 +1843,7 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME,
// garbage.
if (NodeTy* N = Builder->generateNode(ME, StNull, Pred)) {
N->markAsSink();
- if (isFeasibleNotNull)
+ if (StNotNull)
NilReceiverStructRetImplicit.insert(N);
else
NilReceiverStructRetExplicit.insert(N);
@@ -1913,13 +1862,13 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME,
if(voidPtrSize < returnTypeSize) {
if (NodeTy* N = Builder->generateNode(ME, StNull, Pred)) {
N->markAsSink();
- if(isFeasibleNotNull)
+ if(StNotNull)
NilReceiverLargerThanVoidPtrRetImplicit.insert(N);
else
NilReceiverLargerThanVoidPtrRetExplicit.insert(N);
}
}
- else if (!isFeasibleNotNull) {
+ else if (!StNotNull) {
// Handle the safe cases where the return value is 0 if the
// receiver is nil.
//
@@ -1934,7 +1883,7 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME,
// of this case unless we have *a lot* more knowledge.
//
SVal V = ValMgr.makeZeroVal(ME->getType());
- MakeNode(Dst, ME, Pred, BindExpr(StNull, ME, V));
+ MakeNode(Dst, ME, Pred, StNull->bindExpr(ME, V));
return;
}
}
@@ -2004,7 +1953,7 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME,
for (ObjCMessageExpr::arg_iterator I = ME->arg_begin(), E = ME->arg_end();
I != E; ++I) {
- if (GetSVal(state, *I).isUndef()) {
+ if (state->getSVal(*I).isUndef()) {
// Generate an error node for passing an uninitialized/undefined value
// as an argument to a message expression. This node is a sink.
@@ -2053,11 +2002,11 @@ void GRExprEngine::VisitCastPointerToInteger(SVal V, const GRState* state,
// FIXME: Determine if the number of bits of the target type is
// equal or exceeds the number of bits to store the pointer value.
// If not, flag an error.
- MakeNode(Dst, CastE, Pred, BindExpr(state, CastE, EvalCast(cast<Loc>(V),
+ MakeNode(Dst, CastE, Pred, state->bindExpr(CastE, EvalCast(cast<Loc>(V),
CastE->getType())));
}
else
- MakeNode(Dst, CastE, Pred, BindExpr(state, CastE, V));
+ MakeNode(Dst, CastE, Pred, state->bindExpr(CastE, V));
}
@@ -2089,7 +2038,7 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){
for (NodeSet::iterator I1 = S1.begin(), E1 = S1.end(); I1 != E1; ++I1) {
NodeTy* N = *I1;
const GRState* state = GetState(N);
- SVal V = GetSVal(state, Ex);
+ SVal V = state->getSVal(Ex);
ASTContext& C = getContext();
// Unknown?
@@ -2118,7 +2067,7 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){
if (nonloc::LocAsInteger *LV = dyn_cast<nonloc::LocAsInteger>(&V)) {
// Just unpackage the lval and return it.
V = LV->getLoc();
- MakeNode(Dst, CastE, N, BindExpr(state, CastE, V));
+ MakeNode(Dst, CastE, N, state->bindExpr(CastE, V));
continue;
}
@@ -2190,18 +2139,18 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){
if (R) { V = loc::MemRegionVal(R); } else { V = UnknownVal(); }
// Generate the new node in the ExplodedGraph.
- MakeNode(Dst, CastE, N, BindExpr(Res.getState(), CastE, V));
+ MakeNode(Dst, CastE, N, Res.getState()->bindExpr(CastE, V));
continue;
}
// All other cases.
DispatchCast: {
- MakeNode(Dst, CastE, N, BindExpr(state, CastE,
- EvalCast(V, CastE->getType())));
+ MakeNode(Dst, CastE, N, state->bindExpr(CastE,
+ EvalCast(V, CastE->getType())));
continue;
}
PassThrough: {
- MakeNode(Dst, CastE, N, BindExpr(state, CastE, V));
+ MakeNode(Dst, CastE, N, state->bindExpr(CastE, V));
}
}
}
@@ -2215,13 +2164,13 @@ void GRExprEngine::VisitCompoundLiteralExpr(CompoundLiteralExpr* CL,
for (NodeSet::iterator I = Tmp.begin(), EI = Tmp.end(); I!=EI; ++I) {
const GRState* state = GetState(*I);
- SVal ILV = GetSVal(state, ILE);
- state = StateMgr.BindCompoundLiteral(state, CL, ILV);
+ SVal ILV = state->getSVal(ILE);
+ state = state->bindCompoundLiteral(CL, ILV);
if (asLValue)
- MakeNode(Dst, CL, *I, BindExpr(state, CL, StateMgr.GetLValue(state, CL)));
+ MakeNode(Dst, CL, *I, state->bindExpr(CL, state->getLValue(CL)));
else
- MakeNode(Dst, CL, *I, BindExpr(state, CL, ILV));
+ MakeNode(Dst, CL, *I, state->bindExpr(CL, ILV));
}
}
@@ -2256,7 +2205,7 @@ void GRExprEngine::VisitDeclStmt(DeclStmt* DS, NodeTy* Pred, NodeSet& Dst) {
// FIXME: Handle multi-dimensional VLAs.
Expr* SE = VLA->getSizeExpr();
- SVal Size = GetSVal(state, SE);
+ SVal Size = state->getSVal(SE);
if (Size.isUndef()) {
if (NodeTy* N = Builder->generateNode(DS, state, Pred)) {
@@ -2266,27 +2215,26 @@ void GRExprEngine::VisitDeclStmt(DeclStmt* DS, NodeTy* Pred, NodeSet& Dst) {
continue;
}
- bool isFeasibleZero = false;
- const GRState* ZeroSt = Assume(state, Size, false, isFeasibleZero);
+ const GRState* zeroState = state->assume(Size, false);
+ state = state->assume(Size, true);
- bool isFeasibleNotZero = false;
- state = Assume(state, Size, true, isFeasibleNotZero);
-
- if (isFeasibleZero) {
- if (NodeTy* N = Builder->generateNode(DS, ZeroSt, Pred)) {
+ if (zeroState) {
+ if (NodeTy* N = Builder->generateNode(DS, zeroState, Pred)) {
N->markAsSink();
- if (isFeasibleNotZero) ImplicitBadSizedVLA.insert(N);
- else ExplicitBadSizedVLA.insert(N);
+ if (state)
+ ImplicitBadSizedVLA.insert(N);
+ else
+ ExplicitBadSizedVLA.insert(N);
}
}
- if (!isFeasibleNotZero)
+ if (!state)
continue;
}
// Decls without InitExpr are not initialized explicitly.
if (InitEx) {
- SVal InitVal = GetSVal(state, InitEx);
+ SVal InitVal = state->getSVal(InitEx);
QualType T = VD->getType();
// Recover some path-sensitivity if a scalar value evaluated to
@@ -2343,7 +2291,7 @@ void GRExprEngine::VisitInitListExpr(InitListExpr* E, NodeTy* Pred,
// e.g: static int* myArray[] = {};
if (NumInitElements == 0) {
SVal V = NonLoc::MakeCompoundVal(T, StartVals, getBasicVals());
- MakeNode(Dst, E, Pred, BindExpr(state, E, V));
+ MakeNode(Dst, E, Pred, state->bindExpr(E, V));
return;
}
@@ -2366,7 +2314,7 @@ void GRExprEngine::VisitInitListExpr(InitListExpr* E, NodeTy* Pred,
for (NodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI) {
// Get the last initializer value.
state = GetState(*NI);
- SVal InitV = GetSVal(state, cast<Expr>(*X.Itr));
+ SVal InitV = state->getSVal(cast<Expr>(*X.Itr));
// Construct the new list of values by prepending the new value to
// the already constructed list.
@@ -2378,7 +2326,7 @@ void GRExprEngine::VisitInitListExpr(InitListExpr* E, NodeTy* Pred,
SVal V = NonLoc::MakeCompoundVal(T, NewVals, getBasicVals());
// Make final state and node.
- MakeNode(Dst, E, *NI, BindExpr(state, E, V));
+ MakeNode(Dst, E, *NI, state->bindExpr(E, V));
}
else {
// Still some initializer values to go. Push them onto the worklist.
@@ -2404,7 +2352,7 @@ void GRExprEngine::VisitInitListExpr(InitListExpr* E, NodeTy* Pred,
Visit(Init, Pred, Tmp);
for (NodeSet::iterator I = Tmp.begin(), EI = Tmp.end(); I != EI; ++I) {
state = GetState(*I);
- MakeNode(Dst, E, *I, BindExpr(state, E, GetSVal(state, Init)));
+ MakeNode(Dst, E, *I, state->bindExpr(E, state->getSVal(Init)));
}
return;
}
@@ -2445,8 +2393,8 @@ void GRExprEngine::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr* Ex,
amt = getContext().getTypeAlign(T) / 8;
MakeNode(Dst, Ex, Pred,
- BindExpr(GetState(Pred), Ex,
- NonLoc::MakeVal(getBasicVals(), amt, Ex->getType())));
+ GetState(Pred)->bindExpr(Ex, NonLoc::MakeVal(getBasicVals(), amt,
+ Ex->getType())));
}
@@ -2467,10 +2415,10 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
const GRState* state = GetState(*I);
- SVal location = GetSVal(state, Ex);
+ SVal location = state->getSVal(Ex);
if (asLValue)
- MakeNode(Dst, U, *I, BindExpr(state, U, location),
+ MakeNode(Dst, U, *I, state->bindExpr(U, location),
ProgramPoint::PostLValueKind);
else
EvalLoad(Dst, U, *I, state, location);
@@ -2497,7 +2445,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
// For all other types, UnaryOperator::Real is an identity operation.
assert (U->getType() == Ex->getType());
const GRState* state = GetState(*I);
- MakeNode(Dst, U, *I, BindExpr(state, U, GetSVal(state, Ex)));
+ MakeNode(Dst, U, *I, state->bindExpr(U, state->getSVal(Ex)));
}
return;
@@ -2521,7 +2469,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
assert (Ex->getType()->isIntegerType());
const GRState* state = GetState(*I);
SVal X = NonLoc::MakeVal(getBasicVals(), 0, Ex->getType());
- MakeNode(Dst, U, *I, BindExpr(state, U, X));
+ MakeNode(Dst, U, *I, state->bindExpr(U, X));
}
return;
@@ -2546,7 +2494,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
const GRState* state = GetState(*I);
- MakeNode(Dst, U, *I, BindExpr(state, U, GetSVal(state, Ex)));
+ MakeNode(Dst, U, *I, state->bindExpr(U, state->getSVal(Ex)));
}
return;
@@ -2561,8 +2509,8 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
const GRState* state = GetState(*I);
- SVal V = GetSVal(state, Ex);
- state = BindExpr(state, U, V);
+ SVal V = state->getSVal(Ex);
+ state = state->bindExpr(U, V);
MakeNode(Dst, U, *I, state);
}
@@ -2582,10 +2530,10 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
const GRState* state = GetState(*I);
// Get the value of the subexpression.
- SVal V = GetSVal(state, Ex);
+ SVal V = state->getSVal(Ex);
if (V.isUnknownOrUndef()) {
- MakeNode(Dst, U, *I, BindExpr(state, U, V));
+ MakeNode(Dst, U, *I, state->bindExpr(U, V));
continue;
}
@@ -2607,12 +2555,12 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
case UnaryOperator::Not:
// FIXME: Do we need to handle promotions?
- state = BindExpr(state, U, EvalComplement(cast<NonLoc>(V)));
+ state = state->bindExpr(U, EvalComplement(cast<NonLoc>(V)));
break;
case UnaryOperator::Minus:
// FIXME: Do we need to handle promotions?
- state = BindExpr(state, U, EvalMinus(U, cast<NonLoc>(V)));
+ state = state->bindExpr(U, EvalMinus(U, cast<NonLoc>(V)));
break;
case UnaryOperator::LNot:
@@ -2626,7 +2574,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
Loc X = Loc::MakeNull(getBasicVals());
SVal Result = EvalBinOp(state,BinaryOperator::EQ, cast<Loc>(V), X,
U->getType());
- state = BindExpr(state, U, Result);
+ state = state->bindExpr(U, Result);
}
else {
nonloc::ConcreteInt X(getBasicVals().getValue(0, Ex->getType()));
@@ -2660,7 +2608,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
for (NodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I!=E; ++I) {
const GRState* state = GetState(*I);
- SVal V1 = GetSVal(state, Ex);
+ SVal V1 = state->getSVal(Ex);
// Perform a load.
NodeSet Tmp2;
@@ -2669,11 +2617,11 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
for (NodeSet::iterator I2 = Tmp2.begin(), E2 = Tmp2.end(); I2!=E2; ++I2) {
state = GetState(*I2);
- SVal V2 = GetSVal(state, Ex);
+ SVal V2 = state->getSVal(Ex);
// Propagate unknown and undefined values.
if (V2.isUnknownOrUndef()) {
- MakeNode(Dst, U, *I2, BindExpr(state, U, V2));
+ MakeNode(Dst, U, *I2, state->bindExpr(U, V2));
continue;
}
@@ -2697,23 +2645,20 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
ValMgr.makeZeroVal(U->getType()),
getContext().IntTy);
- bool isFeasible = false;
- Assume(state, Constraint, true, isFeasible);
- if (!isFeasible) {
+ if (!state->assume(Constraint, true)) {
// It isn't feasible for the original value to be null.
// Propagate this constraint.
Constraint = EvalBinOp(state, BinaryOperator::EQ, Result,
ValMgr.makeZeroVal(U->getType()),
getContext().IntTy);
- bool isFeasible = false;
- state = Assume(state, Constraint, false, isFeasible);
- assert(isFeasible && state);
+ state = state->assume(Constraint, false);
+ assert(state);
}
}
}
- state = BindExpr(state, U, U->isPostfix() ? V2 : Result);
+ state = state->bindExpr(U, U->isPostfix() ? V2 : Result);
// Perform the store.
EvalStore(Dst, U, *I2, state, V1, Result);
@@ -2761,11 +2706,11 @@ void GRExprEngine::VisitAsmStmtHelperInputs(AsmStmt* A,
for (AsmStmt::outputs_iterator OI = A->begin_outputs(),
OE = A->end_outputs(); OI != OE; ++OI) {
- SVal X = GetSVal(state, *OI);
+ SVal X = state->getSVal(*OI);
assert (!isa<NonLoc>(X)); // Should be an Lval, or unknown, undef.
if (isa<Loc>(X))
- state = BindLoc(state, cast<Loc>(X), UnknownVal());
+ state = state->bindLoc(cast<Loc>(X), UnknownVal());
}
MakeNode(Dst, A, Pred, state);
@@ -2810,7 +2755,7 @@ void GRExprEngine::VisitReturnStmt(ReturnStmt* S, NodeTy* Pred, NodeSet& Dst) {
Visit(R, Pred, Tmp);
for (NodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I != E; ++I) {
- SVal X = GetSVal((*I)->getState(), R);
+ SVal X = (*I)->getState()->getSVal(R);
// Check if we return the address of a stack variable.
if (isa<loc::MemRegionVal>(X)) {
@@ -2861,29 +2806,24 @@ const GRState* GRExprEngine::CheckDivideZero(Expr* Ex, const GRState* state,
// Check for divide/remainder-by-zero.
// First, "assume" that the denominator is 0 or undefined.
-
- bool isFeasibleZero = false;
- const GRState* ZeroSt = Assume(state, Denom, false, isFeasibleZero);
+ const GRState* zeroState = state->assume(Denom, false);
// Second, "assume" that the denominator cannot be 0.
+ state = state->assume(Denom, true);
- bool isFeasibleNotZero = false;
- state = Assume(state, Denom, true, isFeasibleNotZero);
-
- // Create the node for the divide-by-zero (if it occurred).
-
- if (isFeasibleZero)
- if (NodeTy* DivZeroNode = Builder->generateNode(Ex, ZeroSt, Pred)) {
+ // Create the node for the divide-by-zero (if it occurred).
+ if (zeroState)
+ if (NodeTy* DivZeroNode = Builder->generateNode(Ex, zeroState, Pred)) {
DivZeroNode->markAsSink();
- if (isFeasibleNotZero)
+ if (state)
ImplicitBadDivides.insert(DivZeroNode);
else
ExplicitBadDivides.insert(DivZeroNode);
}
- return isFeasibleNotZero ? state : 0;
+ return state;
}
void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
@@ -2907,7 +2847,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
for (NodeSet::iterator I1=Tmp1.begin(), E1=Tmp1.end(); I1 != E1; ++I1) {
- SVal LeftV = GetSVal((*I1)->getState(), LHS);
+ SVal LeftV = (*I1)->getState()->getSVal(LHS);
// Process the RHS.
@@ -2921,7 +2861,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
const GRState* state = GetState(*I2);
const GRState* OldSt = state;
- SVal RightV = GetSVal(state, RHS);
+ SVal RightV = state->getSVal(RHS);
BinaryOperator::Opcode Op = B->getOpcode();
switch (Op) {
@@ -2942,7 +2882,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
// Simulate the effects of a "store": bind the value of the RHS
// to the L-Value represented by the LHS.
- EvalStore(Dst, B, LHS, *I2, BindExpr(state, B, RightV), LeftV,
+ EvalStore(Dst, B, LHS, *I2, state->bindExpr(B, RightV), LeftV,
RightV);
continue;
}
@@ -2996,7 +2936,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
// Otherwise, create a new node.
- MakeNode(Dst, B, *I2, BindExpr(state, B, Result));
+ MakeNode(Dst, B, *I2, state->bindExpr(B, Result));
continue;
}
}
@@ -3021,13 +2961,13 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
// Perform a load (the LHS). This performs the checks for
// null dereferences, and so on.
NodeSet Tmp3;
- SVal location = GetSVal(state, LHS);
+ SVal location = state->getSVal(LHS);
EvalLoad(Tmp3, LHS, *I2, state, location);
for (NodeSet::iterator I3=Tmp3.begin(), E3=Tmp3.end(); I3!=E3; ++I3) {
state = GetState(*I3);
- SVal V = GetSVal(state, LHS);
+ SVal V = state->getSVal(LHS);
// Check for divide-by-zero.
if ((Op == BinaryOperator::Div || Op == BinaryOperator::Rem)
@@ -3044,13 +2984,13 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
// Propagate undefined values (left-side).
if (V.isUndef()) {
- EvalStore(Dst, B, LHS, *I3, BindExpr(state, B, V), location, V);
+ EvalStore(Dst, B, LHS, *I3, state->bindExpr(B, V), location, V);
continue;
}
// Propagate unknown values (left and right-side).
if (RightV.isUnknown() || V.isUnknown()) {
- EvalStore(Dst, B, LHS, *I3, BindExpr(state, B, UnknownVal()),
+ EvalStore(Dst, B, LHS, *I3, state->bindExpr(B, UnknownVal()),
location, UnknownVal());
continue;
}
@@ -3076,7 +3016,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
// Evaluate operands and promote to result type.
if (RightV.isUndef()) {
// Propagate undefined values (right-side).
- EvalStore(Dst, B, LHS, *I3, BindExpr(state, B, RightV), location,
+ EvalStore(Dst, B, LHS, *I3, state->bindExpr(B, RightV), location,
RightV);
continue;
}
@@ -3120,7 +3060,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
LHSVal = (LTy == CTy) ? Result : EvalCast(Result,LTy);
}
- EvalStore(Dst, B, LHS, *I3, BindExpr(state, B, Result), location,
+ EvalStore(Dst, B, LHS, *I3, state->bindExpr(B, Result), location,
LHSVal);
}
}
@@ -3353,8 +3293,8 @@ struct VISIBILITY_HIDDEN DOTGraphTraits<GRExprEngine::NodeTy*> :
Out << "\\|StateID: " << (void*) N->getState() << "\\|";
- GRStateRef state(N->getState(), GraphPrintCheckerState->getStateManager());
- state.printDOT(Out);
+ const GRState *state = N->getState();
+ state->printDOT(Out);
Out << "\\l";
return Out.str();
diff --git a/lib/Analysis/GRExprEngineInternalChecks.cpp b/lib/Analysis/GRExprEngineInternalChecks.cpp
index 9aea12447dd5..7f7270d40d64 100644
--- a/lib/Analysis/GRExprEngineInternalChecks.cpp
+++ b/lib/Analysis/GRExprEngineInternalChecks.cpp
@@ -347,9 +347,7 @@ public:
assert (E && "Return expression cannot be NULL");
// Get the value associated with E.
- loc::MemRegionVal V =
- cast<loc::MemRegionVal>(Eng.getStateManager().GetSVal(N->getState(),
- E));
+ loc::MemRegionVal V = cast<loc::MemRegionVal>(N->getState()->getSVal(E));
// Generate a report for this bug.
std::string buf;
@@ -427,7 +425,7 @@ class VISIBILITY_HIDDEN UndefBranch : public BuiltinBug {
return Ex;
}
- bool MatchesCriteria(Expr* Ex) { return VM.GetSVal(St, Ex).isUndef(); }
+ bool MatchesCriteria(Expr* Ex) { return St->getSVal(Ex).isUndef(); }
};
public:
@@ -519,8 +517,7 @@ public:
"variable-length array (VLA) '"
<< VD->getNameAsString() << "' evaluates to ";
- bool isUndefined = Eng.getStateManager().GetSVal(N->getState(),
- SizeExpr).isUndef();
+ bool isUndefined = N->getState()->getSVal(SizeExpr).isUndef();
if (isUndefined)
os << "an undefined or garbage value.";
@@ -563,13 +560,13 @@ public:
CallExpr* CE = cast<CallExpr>(cast<PostStmt>(N->getLocation()).getStmt());
const GRState* state = N->getState();
- SVal X = VMgr.GetSVal(state, CE->getCallee());
+ SVal X = state->getSVal(CE->getCallee());
const FunctionDecl* FD = X.getAsFunctionDecl();
if (!FD)
return false;
- const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
+ const NonNullAttr* Att = FD->getAttr<NonNullAttr>(BR.getContext());
if (!Att)
return false;
@@ -819,24 +816,15 @@ public:
// Check if in the previous state it was feasible for this constraint
// to *not* be true.
-
- GRStateManager &StateMgr = BRC.getStateManager();
- bool isFeasible = false;
- if (StateMgr.Assume(PrevN->getState(), Constraint, !Assumption,
- isFeasible)) {
- assert(isFeasible); // Eventually we don't need 'isFeasible'.
+ if (PrevN->getState()->assume(Constraint, !Assumption)) {
isSatisfied = true;
// As a sanity check, make sure that the negation of the constraint
// was infeasible in the current state. If it is feasible, we somehow
// missed the transition point.
- isFeasible = false;
- if (StateMgr.Assume(N->getState(), Constraint, !Assumption,
- isFeasible)) {
- assert(isFeasible);
+ if (N->getState()->assume(Constraint, !Assumption))
return NULL;
- }
// We found the transition point for the constraint. We now need to
// pretty-print the constraint. (work-in-progress)
@@ -897,7 +885,7 @@ static void registerTrackNullOrUndefValue(BugReporterContext& BRC,
StateMgr.getRegionManager().getVarRegion(VD);
// What did we load?
- SVal V = StateMgr.GetSVal(state, S);
+ SVal V = state->getSVal(S);
if (isa<loc::ConcreteInt>(V) || isa<nonloc::ConcreteInt>(V)
|| V.isUndef()) {
@@ -906,7 +894,7 @@ static void registerTrackNullOrUndefValue(BugReporterContext& BRC,
}
}
- SVal V = StateMgr.GetSValAsScalarOrLoc(state, S);
+ SVal V = state->getSValAsScalarOrLoc(S);
// Uncomment this to find cases where we aren't properly getting the
// base value that was dereferenced.
diff --git a/lib/Analysis/GRSimpleVals.cpp b/lib/Analysis/GRSimpleVals.cpp
index e1c4848f4559..7e54f1ad6866 100644
--- a/lib/Analysis/GRSimpleVals.cpp
+++ b/lib/Analysis/GRSimpleVals.cpp
@@ -363,11 +363,13 @@ void GRSimpleVals::EvalCall(ExplodedNodeSet<GRState>& Dst,
for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end();
I != E; ++I) {
- SVal V = StateMgr.GetSVal(St, *I);
+ SVal V = St->getSVal(*I);
- if (isa<loc::MemRegionVal>(V))
- St = StateMgr.BindLoc(St, cast<Loc>(V), UnknownVal());
- else if (isa<nonloc::LocAsInteger>(V))
+ if (isa<loc::MemRegionVal>(V)) {
+ const MemRegion *R = cast<loc::MemRegionVal>(V).getRegion();
+ if (R->isBoundable(Eng.getContext()))
+ St = StateMgr.BindLoc(St, cast<Loc>(V), UnknownVal());
+ } else if (isa<nonloc::LocAsInteger>(V))
St = StateMgr.BindLoc(St, cast<nonloc::LocAsInteger>(V).getLoc(),
UnknownVal());
@@ -380,7 +382,7 @@ void GRSimpleVals::EvalCall(ExplodedNodeSet<GRState>& Dst,
if (Loc::IsLocType(T) || (T->isIntegerType() && T->isScalarType())) {
unsigned Count = Builder.getCurrentBlockCount();
SVal X = Eng.getValueManager().getConjuredSymbolVal(CE, Count);
- St = StateMgr.BindExpr(St, CE, X, Eng.getCFG().isBlkExpr(CE), false);
+ St = St->bindExpr(CE, X, Eng.getCFG().isBlkExpr(CE), false);
}
Builder.MakeNode(Dst, CE, Pred, St);
@@ -398,18 +400,16 @@ void GRSimpleVals::EvalObjCMessageExpr(ExplodedNodeSet<GRState>& Dst,
// The basic transfer function logic for message expressions does nothing.
- // We just invalidate all arguments passed in by references.
-
- GRStateManager& StateMgr = Eng.getStateManager();
- const GRState* St = Builder.GetState(Pred);
+ // We just invalidate all arguments passed in by references.
+ const GRState *St = Builder.GetState(Pred);
for (ObjCMessageExpr::arg_iterator I = ME->arg_begin(), E = ME->arg_end();
I != E; ++I) {
- SVal V = StateMgr.GetSVal(St, *I);
+ SVal V = St->getSVal(*I);
if (isa<Loc>(V))
- St = StateMgr.BindLoc(St, cast<Loc>(V), UnknownVal());
+ St = St->bindLoc(cast<Loc>(V), UnknownVal());
}
Builder.MakeNode(Dst, ME, Pred, St);
diff --git a/lib/Analysis/GRState.cpp b/lib/Analysis/GRState.cpp
index e0e478c30717..aeb1c04cafba 100644
--- a/lib/Analysis/GRState.cpp
+++ b/lib/Analysis/GRState.cpp
@@ -69,8 +69,7 @@ const GRState* GRStateManager::Unbind(const GRState* St, Loc LV) {
}
const GRState* GRStateManager::getInitialState() {
-
- GRState StateImpl(EnvMgr.getInitialEnvironment(),
+ GRState StateImpl(this, EnvMgr.getInitialEnvironment(),
StoreMgr->getInitialStore(),
GDMFactory.GetEmptyMap());
@@ -92,25 +91,19 @@ const GRState* GRStateManager::getPersistentState(GRState& State) {
return I;
}
-const GRState* GRStateManager::MakeStateWithStore(const GRState* St,
- Store store) {
- GRState NewSt = *St;
+const GRState* GRState::makeWithStore(Store store) const {
+ GRState NewSt = *this;
NewSt.St = store;
- return getPersistentState(NewSt);
+ return Mgr->getPersistentState(NewSt);
}
-
//===----------------------------------------------------------------------===//
// State pretty-printing.
//===----------------------------------------------------------------------===//
-void GRState::print(std::ostream& Out, StoreManager& StoreMgr,
- ConstraintManager& ConstraintMgr,
- Printer** Beg, Printer** End,
- const char* nl, const char* sep) const {
-
+void GRState::print(std::ostream& Out, const char* nl, const char* sep) const {
// Print the store.
- StoreMgr.print(getStore(), Out, nl, sep);
+ Mgr->getStoreManager().print(getStore(), Out, nl, sep);
// Print Subexpression bindings.
bool isFirst = true;
@@ -150,24 +143,21 @@ void GRState::print(std::ostream& Out, StoreManager& StoreMgr,
I.getData().print(Out);
}
- ConstraintMgr.print(this, Out, nl, sep);
+ Mgr->getConstraintManager().print(this, Out, nl, sep);
- // Print checker-specific data.
- for ( ; Beg != End ; ++Beg) (*Beg)->Print(Out, this, nl, sep);
+ // Print checker-specific data.
+ for (std::vector<Printer*>::iterator I = Mgr->Printers.begin(),
+ E = Mgr->Printers.end(); I != E; ++I) {
+ (*I)->Print(Out, this, nl, sep);
+ }
}
-void GRStateRef::printDOT(std::ostream& Out) const {
+void GRState::printDOT(std::ostream& Out) const {
print(Out, "\\l", "\\|");
}
-void GRStateRef::printStdErr() const {
+void GRState::printStdErr() const {
print(*llvm::cerr);
-}
-
-void GRStateRef::print(std::ostream& Out, const char* nl, const char* sep)const{
- GRState::Printer **beg = Mgr->Printers.empty() ? 0 : &Mgr->Printers[0];
- GRState::Printer **end = !beg ? 0 : beg + Mgr->Printers.size();
- St->print(Out, *Mgr->StoreMgr, *Mgr->ConstraintMgr, beg, end, nl, sep);
}
//===----------------------------------------------------------------------===//
@@ -213,13 +203,13 @@ class VISIBILITY_HIDDEN ScanReachableSymbols : public SubRegionMap::Visitor {
typedef llvm::DenseSet<const MemRegion*> VisitedRegionsTy;
VisitedRegionsTy visited;
- GRStateRef state;
+ const GRState *state;
SymbolVisitor &visitor;
llvm::OwningPtr<SubRegionMap> SRM;
public:
- ScanReachableSymbols(GRStateManager* sm, const GRState *st, SymbolVisitor& v)
- : state(st, *sm), visitor(v) {}
+ ScanReachableSymbols(const GRState *st, SymbolVisitor& v)
+ : state(st), visitor(v) {}
bool scan(nonloc::CompoundVal val);
bool scan(SVal val);
@@ -270,19 +260,18 @@ bool ScanReachableSymbols::scan(const MemRegion *R) {
return false;
// Now look at the binding to this region (if any).
- if (!scan(state.GetSValAsScalarOrLoc(R)))
+ if (!scan(state->getSValAsScalarOrLoc(R)))
return false;
// Now look at the subregions.
if (!SRM.get())
- SRM.reset(state.getManager().getStoreManager().getSubRegionMap(state));
+ SRM.reset(state->getStateManager().getStoreManager().getSubRegionMap(state));
return SRM->iterSubRegions(R, *this);
}
-bool GRStateManager::scanReachableSymbols(SVal val, const GRState* state,
- SymbolVisitor& visitor) {
- ScanReachableSymbols S(this, state, visitor);
+bool GRState::scanReachableSymbols(SVal val, SymbolVisitor& visitor) const {
+ ScanReachableSymbols S(this, visitor);
return S.scan(val);
}
diff --git a/lib/Analysis/GRTransferFuncs.cpp b/lib/Analysis/GRTransferFuncs.cpp
index 69c09d9a2ec5..3c14ee9ab5c2 100644
--- a/lib/Analysis/GRTransferFuncs.cpp
+++ b/lib/Analysis/GRTransferFuncs.cpp
@@ -23,6 +23,5 @@ void GRTransferFuncs::EvalBinOpNN(GRStateSet& OStates,
BinaryOperator::Opcode Op,
NonLoc L, NonLoc R, QualType T) {
- OStates.Add(Eng.getStateManager().BindExpr(St, Ex,
- DetermEvalBinOpNN(Eng, Op, L, R, T)));
+ OStates.Add(St->bindExpr(Ex, DetermEvalBinOpNN(Eng, Op, L, R, T)));
}
diff --git a/lib/Analysis/MemRegion.cpp b/lib/Analysis/MemRegion.cpp
index 9f066f44692f..9e11a263536d 100644
--- a/lib/Analysis/MemRegion.cpp
+++ b/lib/Analysis/MemRegion.cpp
@@ -296,10 +296,12 @@ MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr* CL) {
ElementRegion*
MemRegionManager::getElementRegion(QualType elementType, SVal Idx,
- const MemRegion* superRegion){
+ const MemRegion* superRegion, ASTContext& Ctx){
+
+ QualType T = Ctx.getCanonicalType(elementType);
llvm::FoldingSetNodeID ID;
- ElementRegion::ProfileRegion(ID, elementType, Idx, superRegion);
+ ElementRegion::ProfileRegion(ID, T, Idx, superRegion);
void* InsertPos;
MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
@@ -307,7 +309,7 @@ MemRegionManager::getElementRegion(QualType elementType, SVal Idx,
if (!R) {
R = (ElementRegion*) A.Allocate<ElementRegion>();
- new (R) ElementRegion(elementType, Idx, superRegion);
+ new (R) ElementRegion(T, Idx, superRegion);
Regions.InsertNode(R, InsertPos);
}
diff --git a/lib/Analysis/RangeConstraintManager.cpp b/lib/Analysis/RangeConstraintManager.cpp
index f6ac2b9748c4..73c68bcaea03 100644
--- a/lib/Analysis/RangeConstraintManager.cpp
+++ b/lib/Analysis/RangeConstraintManager.cpp
@@ -233,28 +233,27 @@ struct GRStateTrait<ConstraintRange>
namespace {
class VISIBILITY_HIDDEN RangeConstraintManager : public SimpleConstraintManager{
- RangeSet GetRange(GRStateRef state, SymbolRef sym);
+ RangeSet GetRange(const GRState *state, SymbolRef sym);
public:
- RangeConstraintManager(GRStateManager& statemgr)
- : SimpleConstraintManager(statemgr) {}
+ RangeConstraintManager() {}
const GRState* AssumeSymNE(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible);
+ const llvm::APSInt& V);
const GRState* AssumeSymEQ(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible);
+ const llvm::APSInt& V);
const GRState* AssumeSymLT(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible);
+ const llvm::APSInt& V);
const GRState* AssumeSymGT(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible);
+ const llvm::APSInt& V);
const GRState* AssumeSymGE(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible);
+ const llvm::APSInt& V);
const GRState* AssumeSymLE(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V, bool& isFeasible);
+ const llvm::APSInt& V);
const llvm::APSInt* getSymVal(const GRState* St, SymbolRef sym) const;
@@ -275,9 +274,8 @@ private:
} // end anonymous namespace
-ConstraintManager* clang::CreateRangeConstraintManager(GRStateManager& StateMgr)
-{
- return new RangeConstraintManager(StateMgr);
+ConstraintManager* clang::CreateRangeConstraintManager(GRStateManager&) {
+ return new RangeConstraintManager();
}
const llvm::APSInt* RangeConstraintManager::getSymVal(const GRState* St,
@@ -289,12 +287,11 @@ const llvm::APSInt* RangeConstraintManager::getSymVal(const GRState* St,
/// Scan all symbols referenced by the constraints. If the symbol is not alive
/// as marked in LSymbols, mark it as dead in DSymbols.
const GRState*
-RangeConstraintManager::RemoveDeadBindings(const GRState* St,
+RangeConstraintManager::RemoveDeadBindings(const GRState* state,
SymbolReaper& SymReaper) {
- GRStateRef state(St, StateMgr);
- ConstraintRangeTy CR = state.get<ConstraintRange>();
- ConstraintRangeTy::Factory& CRFactory = state.get_context<ConstraintRange>();
+ ConstraintRangeTy CR = state->get<ConstraintRange>();
+ ConstraintRangeTy::Factory& CRFactory = state->get_context<ConstraintRange>();
for (ConstraintRangeTy::iterator I = CR.begin(), E = CR.end(); I != E; ++I) {
SymbolRef sym = I.getKey();
@@ -302,7 +299,7 @@ RangeConstraintManager::RemoveDeadBindings(const GRState* St,
CR = CRFactory.Remove(CR, sym);
}
- return state.set<ConstraintRange>(CR);
+ return state->set<ConstraintRange>(CR);
}
//===------------------------------------------------------------------------===
@@ -310,14 +307,14 @@ RangeConstraintManager::RemoveDeadBindings(const GRState* St,
//===------------------------------------------------------------------------===/
RangeSet
-RangeConstraintManager::GetRange(GRStateRef state, SymbolRef sym) {
- if (ConstraintRangeTy::data_type* V = state.get<ConstraintRange>(sym))
+RangeConstraintManager::GetRange(const GRState *state, SymbolRef sym) {
+ if (ConstraintRangeTy::data_type* V = state->get<ConstraintRange>(sym))
return *V;
// Lazily generate a new RangeSet representing all possible values for the
// given symbol type.
- QualType T = state.getSymbolManager().getType(sym);
- BasicValueFactory& BV = state.getBasicVals();
+ QualType T = state->getSymbolManager().getType(sym);
+ BasicValueFactory& BV = state->getBasicVals();
return RangeSet(F, BV.getMinValue(T), BV.getMaxValue(T));
}
@@ -327,12 +324,10 @@ RangeConstraintManager::GetRange(GRStateRef state, SymbolRef sym) {
#define AssumeX(OP)\
const GRState*\
-RangeConstraintManager::AssumeSym ## OP(const GRState* St, SymbolRef sym,\
- const llvm::APSInt& V, bool& isFeasible){\
- GRStateRef state(St, StateMgr);\
- const RangeSet& R = GetRange(state, sym).Add##OP(state.getBasicVals(), F, V);\
- isFeasible = !R.isEmpty();\
- return isFeasible ? state.set<ConstraintRange>(sym, R).getState() : 0;\
+RangeConstraintManager::AssumeSym ## OP(const GRState* state, SymbolRef sym,\
+ const llvm::APSInt& V){\
+ const RangeSet& R = GetRange(state, sym).Add##OP(state->getBasicVals(), F, V);\
+ return !R.isEmpty() ? state->set<ConstraintRange>(sym, R) : NULL;\
}
AssumeX(EQ)
diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp
index eae3aefe218f..5f2b8f809de3 100644
--- a/lib/Analysis/RegionStore.cpp
+++ b/lib/Analysis/RegionStore.cpp
@@ -31,6 +31,32 @@ using namespace clang;
typedef llvm::ImmutableMap<const MemRegion*, SVal> RegionBindingsTy;
//===----------------------------------------------------------------------===//
+// Fine-grained control of RegionStoreManager.
+//===----------------------------------------------------------------------===//
+
+namespace {
+struct VISIBILITY_HIDDEN minimal_features_tag {};
+struct VISIBILITY_HIDDEN maximal_features_tag {};
+
+class VISIBILITY_HIDDEN RegionStoreFeatures {
+ bool SupportsFields;
+ bool SupportsRemaining;
+
+public:
+ RegionStoreFeatures(minimal_features_tag) :
+ SupportsFields(false), SupportsRemaining(false) {}
+
+ RegionStoreFeatures(maximal_features_tag) :
+ SupportsFields(true), SupportsRemaining(false) {}
+
+ void enableFields(bool t) { SupportsFields = t; }
+
+ bool supportsFields() const { return SupportsFields; }
+ bool supportsRemaining() const { return SupportsRemaining; }
+};
+}
+
+//===----------------------------------------------------------------------===//
// Region "Views"
//===----------------------------------------------------------------------===//
//
@@ -151,6 +177,7 @@ public:
};
class VISIBILITY_HIDDEN RegionStoreManager : public StoreManager {
+ const RegionStoreFeatures Features;
RegionBindingsTy::Factory RBFactory;
RegionViews::Factory RVFactory;
@@ -158,8 +185,9 @@ class VISIBILITY_HIDDEN RegionStoreManager : public StoreManager {
const ImplicitParamDecl *SelfDecl;
public:
- RegionStoreManager(GRStateManager& mgr)
+ RegionStoreManager(GRStateManager& mgr, const RegionStoreFeatures &f)
: StoreManager(mgr),
+ Features(f),
RBFactory(mgr.getAllocator()),
RVFactory(mgr.getAllocator()),
SelfRegion(0), SelfDecl(0) {
@@ -172,36 +200,32 @@ public:
SubRegionMap* getSubRegionMap(const GRState *state);
- const GRState* BindCompoundLiteral(const GRState* St,
- const CompoundLiteralExpr* CL, SVal V);
-
/// getLValueString - Returns an SVal representing the lvalue of a
/// StringLiteral. Within RegionStore a StringLiteral has an
/// associated StringRegion, and the lvalue of a StringLiteral is
/// the lvalue of that region.
- SVal getLValueString(const GRState* St, const StringLiteral* S);
+ SVal getLValueString(const GRState *state, const StringLiteral* S);
/// getLValueCompoundLiteral - Returns an SVal representing the
/// lvalue of a compound literal. Within RegionStore a compound
/// literal has an associated region, and the lvalue of the
/// compound literal is the lvalue of that region.
- SVal getLValueCompoundLiteral(const GRState* St, const CompoundLiteralExpr*);
+ SVal getLValueCompoundLiteral(const GRState *state, const CompoundLiteralExpr*);
/// getLValueVar - Returns an SVal that represents the lvalue of a
/// variable. Within RegionStore a variable has an associated
/// VarRegion, and the lvalue of the variable is the lvalue of that region.
- SVal getLValueVar(const GRState* St, const VarDecl* VD);
+ SVal getLValueVar(const GRState *state, const VarDecl* VD);
- SVal getLValueIvar(const GRState* St, const ObjCIvarDecl* D, SVal Base);
+ SVal getLValueIvar(const GRState *state, const ObjCIvarDecl* D, SVal Base);
- SVal getLValueField(const GRState* St, SVal Base, const FieldDecl* D);
+ SVal getLValueField(const GRState *state, SVal Base, const FieldDecl* D);
- SVal getLValueFieldOrIvar(const GRState* St, SVal Base, const Decl* D);
+ SVal getLValueFieldOrIvar(const GRState *state, SVal Base, const Decl* D);
- SVal getLValueElement(const GRState* St, QualType elementType,
+ SVal getLValueElement(const GRState *state, QualType elementType,
SVal Base, SVal Offset);
- SVal getSizeInElements(const GRState* St, const MemRegion* R);
/// ArrayToPointer - Emulates the "decay" of an array to a pointer
/// type. 'Array' represents the lvalue of the array being decayed
@@ -211,27 +235,13 @@ public:
/// casts from arrays to pointers.
SVal ArrayToPointer(Loc Array);
- CastResult CastRegion(const GRState* state, const MemRegion* R,
+ CastResult CastRegion(const GRState *state, const MemRegion* R,
QualType CastToTy);
- SVal EvalBinOp(const GRState *state,BinaryOperator::Opcode Op,Loc L,NonLoc R);
+ SVal EvalBinOp(const GRState *state, BinaryOperator::Opcode Op,Loc L,NonLoc R);
- /// The high level logic for this method is this:
- /// Retrieve (L)
- /// if L has binding
- /// return L's binding
- /// else if L is in killset
- /// return unknown
- /// else
- /// if L is on stack or heap
- /// return undefined
- /// else
- /// return symbolic
- SVal Retrieve(const GRState* state, Loc L, QualType T = QualType());
- const GRState* Bind(const GRState* St, Loc LV, SVal V);
- Store Remove(Store store, Loc LV);
Store getInitialStore() { return RBFactory.GetEmptyMap().getRoot(); }
@@ -251,65 +261,130 @@ public:
return SelfRegion;
}
- /// RemoveDeadBindings - Scans the RegionStore of 'state' for dead values.
- /// It returns a new Store with these values removed, and populates LSymbols
- // and DSymbols with the known set of live and dead symbols respectively.
- Store RemoveDeadBindings(const GRState* state, Stmt* Loc,
- SymbolReaper& SymReaper,
- llvm::SmallVectorImpl<const MemRegion*>& RegionRoots);
- const GRState* BindDecl(const GRState* St, const VarDecl* VD, SVal InitVal);
+
+ //===-------------------------------------------------------------------===//
+ // Binding values to regions.
+ //===-------------------------------------------------------------------===//
- const GRState* BindDeclWithNoInit(const GRState* St, const VarDecl* VD) {
- return St;
- }
+ const GRState *Bind(const GRState *state, Loc LV, SVal V);
- const GRState* setExtent(const GRState* St, const MemRegion* R, SVal Extent);
- const GRState* setCastType(const GRState* St, const MemRegion* R, QualType T);
+ const GRState *BindCompoundLiteral(const GRState *state,
+ const CompoundLiteralExpr* CL, SVal V);
+
+ const GRState *BindDecl(const GRState *state, const VarDecl* VD, SVal InitVal);
- static inline RegionBindingsTy GetRegionBindings(Store store) {
- return RegionBindingsTy(static_cast<const RegionBindingsTy::TreeTy*>(store));
+ const GRState *BindDeclWithNoInit(const GRState *state, const VarDecl* VD) {
+ return state;
}
- void print(Store store, std::ostream& Out, const char* nl, const char *sep);
+ /// BindStruct - Bind a compound value to a structure.
+ const GRState *BindStruct(const GRState *, const TypedRegion* R, SVal V);
+
+ const GRState *BindArray(const GRState *state, const TypedRegion* R, SVal V);
+
+ /// KillStruct - Set the entire struct to unknown.
+ const GRState *KillStruct(const GRState *state, const TypedRegion* R);
- void iterBindings(Store store, BindingsHandler& f) {
- // FIXME: Implement.
- }
- const GRState* setDefaultValue(const GRState* St, const MemRegion* R, SVal V);
-private:
- const GRState* BindArray(const GRState* St, const TypedRegion* R, SVal V);
+ const GRState *setDefaultValue(const GRState *state, const MemRegion* R, SVal V);
+ Store Remove(Store store, Loc LV);
+
+ //===------------------------------------------------------------------===//
+ // Loading values from regions.
+ //===------------------------------------------------------------------===//
+
+ /// The high level logic for this method is this:
+ /// Retrieve (L)
+ /// if L has binding
+ /// return L's binding
+ /// else if L is in killset
+ /// return unknown
+ /// else
+ /// if L is on stack or heap
+ /// return undefined
+ /// else
+ /// return symbolic
+ SVal Retrieve(const GRState *state, Loc L, QualType T = QualType());
+
/// Retrieve the values in a struct and return a CompoundVal, used when doing
/// struct copy:
/// struct s x, y;
/// x = y;
/// y's value is retrieved by this method.
- SVal RetrieveStruct(const GRState* St, const TypedRegion* R);
+ SVal RetrieveStruct(const GRState *St, const TypedRegion* R);
+
+ SVal RetrieveArray(const GRState *St, const TypedRegion* R);
- SVal RetrieveArray(const GRState* St, const TypedRegion* R);
+ //===------------------------------------------------------------------===//
+ // State pruning.
+ //===------------------------------------------------------------------===//
+
+ /// RemoveDeadBindings - Scans the RegionStore of 'state' for dead values.
+ /// It returns a new Store with these values removed.
+ Store RemoveDeadBindings(const GRState *state, Stmt* Loc, SymbolReaper& SymReaper,
+ llvm::SmallVectorImpl<const MemRegion*>& RegionRoots);
- const GRState* BindStruct(const GRState* St, const TypedRegion* R, SVal V);
+ //===------------------------------------------------------------------===//
+ // Region "extents".
+ //===------------------------------------------------------------------===//
+
+ const GRState *setExtent(const GRState *state, const MemRegion* R, SVal Extent);
+ SVal getSizeInElements(const GRState *state, const MemRegion* R);
- /// KillStruct - Set the entire struct to unknown.
- const GRState* KillStruct(const GRState* St, const TypedRegion* R);
+ //===------------------------------------------------------------------===//
+ // Region "views".
+ //===------------------------------------------------------------------===//
+
+ const GRState *AddRegionView(const GRState *state, const MemRegion* View,
+ const MemRegion* Base);
+
+ const GRState *RemoveRegionView(const GRState *state, const MemRegion* View,
+ const MemRegion* Base);
+ //===------------------------------------------------------------------===//
// Utility methods.
- BasicValueFactory& getBasicVals() { return StateMgr.getBasicVals(); }
- ASTContext& getContext() { return StateMgr.getContext(); }
+ //===------------------------------------------------------------------===//
+
+ const GRState *setCastType(const GRState *state, const MemRegion* R, QualType T);
- SymbolManager& getSymbolManager() { return StateMgr.getSymbolManager(); }
+ static inline RegionBindingsTy GetRegionBindings(Store store) {
+ return RegionBindingsTy(static_cast<const RegionBindingsTy::TreeTy*>(store));
+ }
- const GRState* AddRegionView(const GRState* St,
- const MemRegion* View, const MemRegion* Base);
- const GRState* RemoveRegionView(const GRState* St,
- const MemRegion* View, const MemRegion* Base);
+ void print(Store store, std::ostream& Out, const char* nl, const char *sep);
+
+ void iterBindings(Store store, BindingsHandler& f) {
+ // FIXME: Implement.
+ }
+
+ // FIXME: Remove.
+ BasicValueFactory& getBasicVals() {
+ return StateMgr.getBasicVals();
+ }
+
+ // FIXME: Remove.
+ ASTContext& getContext() { return StateMgr.getContext(); }
+
+ // FIXME: Use ValueManager?
+ SymbolManager& getSymbolManager() { return StateMgr.getSymbolManager(); }
};
} // end anonymous namespace
-StoreManager* clang::CreateRegionStoreManager(GRStateManager& StMgr) {
- return new RegionStoreManager(StMgr);
+//===----------------------------------------------------------------------===//
+// RegionStore creation.
+//===----------------------------------------------------------------------===//
+
+StoreManager *clang::CreateRegionStoreManager(GRStateManager& StMgr) {
+ RegionStoreFeatures F = maximal_features_tag();
+ return new RegionStoreManager(StMgr, F);
+}
+
+StoreManager *clang::CreateFieldsOnlyRegionStoreManager(GRStateManager &StMgr) {
+ RegionStoreFeatures F = minimal_features_tag();
+ F.enableFields(true);
+ return new RegionStoreManager(StMgr, F);
}
SubRegionMap* RegionStoreManager::getSubRegionMap(const GRState *state) {
@@ -324,11 +399,15 @@ SubRegionMap* RegionStoreManager::getSubRegionMap(const GRState *state) {
return M;
}
+//===----------------------------------------------------------------------===//
+// getLValueXXX methods.
+//===----------------------------------------------------------------------===//
+
/// getLValueString - Returns an SVal representing the lvalue of a
/// StringLiteral. Within RegionStore a StringLiteral has an
/// associated StringRegion, and the lvalue of a StringLiteral is the
/// lvalue of that region.
-SVal RegionStoreManager::getLValueString(const GRState* St,
+SVal RegionStoreManager::getLValueString(const GRState *St,
const StringLiteral* S) {
return loc::MemRegionVal(MRMgr.getStringRegion(S));
}
@@ -336,7 +415,7 @@ SVal RegionStoreManager::getLValueString(const GRState* St,
/// getLValueVar - Returns an SVal that represents the lvalue of a
/// variable. Within RegionStore a variable has an associated
/// VarRegion, and the lvalue of the variable is the lvalue of that region.
-SVal RegionStoreManager::getLValueVar(const GRState* St, const VarDecl* VD) {
+SVal RegionStoreManager::getLValueVar(const GRState *St, const VarDecl* VD) {
return loc::MemRegionVal(MRMgr.getVarRegion(VD));
}
@@ -345,22 +424,22 @@ SVal RegionStoreManager::getLValueVar(const GRState* St, const VarDecl* VD) {
/// has an associated region, and the lvalue of the compound literal
/// is the lvalue of that region.
SVal
-RegionStoreManager::getLValueCompoundLiteral(const GRState* St,
+RegionStoreManager::getLValueCompoundLiteral(const GRState *St,
const CompoundLiteralExpr* CL) {
return loc::MemRegionVal(MRMgr.getCompoundLiteralRegion(CL));
}
-SVal RegionStoreManager::getLValueIvar(const GRState* St, const ObjCIvarDecl* D,
+SVal RegionStoreManager::getLValueIvar(const GRState *St, const ObjCIvarDecl* D,
SVal Base) {
return getLValueFieldOrIvar(St, Base, D);
}
-SVal RegionStoreManager::getLValueField(const GRState* St, SVal Base,
+SVal RegionStoreManager::getLValueField(const GRState *St, SVal Base,
const FieldDecl* D) {
return getLValueFieldOrIvar(St, Base, D);
}
-SVal RegionStoreManager::getLValueFieldOrIvar(const GRState* St, SVal Base,
+SVal RegionStoreManager::getLValueFieldOrIvar(const GRState *St, SVal Base,
const Decl* D) {
if (Base.isUnknownOrUndef())
return Base;
@@ -397,7 +476,7 @@ SVal RegionStoreManager::getLValueFieldOrIvar(const GRState* St, SVal Base,
return loc::MemRegionVal(MRMgr.getFieldRegion(cast<FieldDecl>(D), BaseR));
}
-SVal RegionStoreManager::getLValueElement(const GRState* St,
+SVal RegionStoreManager::getLValueElement(const GRState *St,
QualType elementType,
SVal Base, SVal Offset) {
@@ -438,7 +517,7 @@ SVal RegionStoreManager::getLValueElement(const GRState* St,
}
}
return loc::MemRegionVal(MRMgr.getElementRegion(elementType, Offset,
- BaseRegion));
+ BaseRegion, getContext()));
}
SVal BaseIdx = ElemR->getIndex();
@@ -473,10 +552,15 @@ SVal RegionStoreManager::getLValueElement(const GRState* St,
else
NewIdx = nonloc::ConcreteInt(getBasicVals().getValue(BaseIdxI + OffI));
- return loc::MemRegionVal(MRMgr.getElementRegion(elementType, NewIdx, ArrayR));
+ return loc::MemRegionVal(MRMgr.getElementRegion(elementType, NewIdx, ArrayR,
+ getContext()));
}
-SVal RegionStoreManager::getSizeInElements(const GRState* St,
+//===----------------------------------------------------------------------===//
+// Extents for regions.
+//===----------------------------------------------------------------------===//
+
+SVal RegionStoreManager::getSizeInElements(const GRState *state,
const MemRegion* R) {
if (const VarRegion* VR = dyn_cast<VarRegion>(R)) {
// Get the type of the variable.
@@ -491,8 +575,7 @@ SVal RegionStoreManager::getSizeInElements(const GRState* St,
return NonLoc::MakeVal(getBasicVals(), CAT->getSize(), false);
}
- GRStateRef state(St, StateMgr);
- const QualType* CastTy = state.get<RegionCasts>(VR);
+ const QualType* CastTy = state->get<RegionCasts>(VR);
// If the VarRegion is cast to other type, compute the size with respect to
// that type.
@@ -501,6 +584,7 @@ SVal RegionStoreManager::getSizeInElements(const GRState* St,
QualType VarTy = VR->getValueType(getContext());
uint64_t EleSize = getContext().getTypeSize(EleTy);
uint64_t VarSize = getContext().getTypeSize(VarTy);
+ assert(VarSize != 0);
return NonLoc::MakeIntVal(getBasicVals(), VarSize / EleSize, false);
}
@@ -538,6 +622,16 @@ SVal RegionStoreManager::getSizeInElements(const GRState* St,
return UnknownVal();
}
+const GRState *RegionStoreManager::setExtent(const GRState *state,
+ const MemRegion *region,
+ SVal extent) {
+ return state->set<RegionExtents>(region, extent);
+}
+
+//===----------------------------------------------------------------------===//
+// Location and region casting.
+//===----------------------------------------------------------------------===//
+
/// ArrayToPointer - Emulates the "decay" of an array to a pointer
/// type. 'Array' represents the lvalue of the array being decayed
/// to a pointer, and the returned SVal represents the decayed
@@ -560,13 +654,13 @@ SVal RegionStoreManager::ArrayToPointer(Loc Array) {
T = AT->getElementType();
nonloc::ConcreteInt Idx(getBasicVals().getZeroWithPtrWidth(false));
- ElementRegion* ER = MRMgr.getElementRegion(T, Idx, ArrayR);
+ ElementRegion* ER = MRMgr.getElementRegion(T, Idx, ArrayR, getContext());
return loc::MemRegionVal(ER);
}
RegionStoreManager::CastResult
-RegionStoreManager::CastRegion(const GRState* state, const MemRegion* R,
+RegionStoreManager::CastRegion(const GRState *state, const MemRegion* R,
QualType CastToTy) {
ASTContext& Ctx = StateMgr.getContext();
@@ -575,7 +669,7 @@ RegionStoreManager::CastRegion(const GRState* state, const MemRegion* R,
QualType ToTy = Ctx.getCanonicalType(CastToTy);
// Check cast to ObjCQualifiedID type.
- if (isa<ObjCQualifiedIdType>(ToTy)) {
+ if (ToTy->isObjCQualifiedIdType()) {
// FIXME: Record the type information aside.
return CastResult(state, R);
}
@@ -617,15 +711,18 @@ RegionStoreManager::CastRegion(const GRState* state, const MemRegion* R,
uint64_t ObjTySize = getContext().getTypeSize(ObjTy);
if ((PointeeTySize > 0 && PointeeTySize < ObjTySize) ||
- (ObjTy->isAggregateType() && PointeeTy->isScalarType())) {
+ (ObjTy->isAggregateType() && PointeeTy->isScalarType()) ||
+ ObjTySize == 0 /* R has 'void*' type. */) {
// Record the cast type of the region.
state = setCastType(state, R, ToTy);
SVal Idx = ValMgr.makeZeroArrayIndex();
- ElementRegion* ER = MRMgr.getElementRegion(PointeeTy, Idx, R);
+ ElementRegion* ER = MRMgr.getElementRegion(PointeeTy, Idx,R,getContext());
return CastResult(state, ER);
- } else
+ } else {
+ state = setCastType(state, R, ToTy);
return CastResult(state, R);
+ }
}
if (isa<ObjCObjectRegion>(R)) {
@@ -636,6 +733,10 @@ RegionStoreManager::CastRegion(const GRState* state, const MemRegion* R,
return 0;
}
+//===----------------------------------------------------------------------===//
+// Pointer arithmetic.
+//===----------------------------------------------------------------------===//
+
SVal RegionStoreManager::EvalBinOp(const GRState *state,
BinaryOperator::Opcode Op, Loc L, NonLoc R) {
// Assume the base location is MemRegionVal.
@@ -648,26 +749,37 @@ SVal RegionStoreManager::EvalBinOp(const GRState *state,
// If the operand is a symbolic or alloca region, create the first element
// region on it.
if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(MR)) {
- // Get symbol's type. It should be a pointer type.
- SymbolRef Sym = SR->getSymbol();
- QualType T = Sym->getType(getContext());
+ QualType T;
+ // If the SymbolicRegion was cast to another type, use that type.
+ if (const QualType *t = state->get<RegionCasts>(SR)) {
+ T = *t;
+ } else {
+ // Otherwise use the symbol's type.
+ SymbolRef Sym = SR->getSymbol();
+ T = Sym->getType(getContext());
+ }
QualType EleTy = T->getAsPointerType()->getPointeeType();
SVal ZeroIdx = ValMgr.makeZeroArrayIndex();
- ER = MRMgr.getElementRegion(EleTy, ZeroIdx, SR);
+ ER = MRMgr.getElementRegion(EleTy, ZeroIdx, SR, getContext());
}
else if (const AllocaRegion *AR = dyn_cast<AllocaRegion>(MR)) {
// Get the alloca region's current cast type.
- GRStateRef StRef(state, StateMgr);
- GRStateTrait<RegionCasts>::lookup_type T = StRef.get<RegionCasts>(AR);
+
+ GRStateTrait<RegionCasts>::lookup_type T = state->get<RegionCasts>(AR);
assert(T && "alloca region has no type.");
QualType EleTy = cast<PointerType>(T->getTypePtr())->getPointeeType();
SVal ZeroIdx = ValMgr.makeZeroArrayIndex();
- ER = MRMgr.getElementRegion(EleTy, ZeroIdx, AR);
+ ER = MRMgr.getElementRegion(EleTy, ZeroIdx, AR, getContext());
}
- else
+ else if (isa<FieldRegion>(MR)) {
+ // Not track pointer arithmetic on struct fields.
+ return UnknownVal();
+ }
+ else {
ER = cast<ElementRegion>(MR);
+ }
SVal Idx = ER->getIndex();
@@ -686,7 +798,8 @@ SVal RegionStoreManager::EvalBinOp(const GRState *state,
Offset->getValue()));
SVal NewIdx = Base->EvalBinOp(getBasicVals(), Op, OffConverted);
const MemRegion* NewER =
- MRMgr.getElementRegion(ER->getElementType(), NewIdx,ER->getSuperRegion());
+ MRMgr.getElementRegion(ER->getElementType(), NewIdx,ER->getSuperRegion(),
+ getContext());
return Loc::MakeVal(NewER);
}
@@ -694,7 +807,12 @@ SVal RegionStoreManager::EvalBinOp(const GRState *state,
return UnknownVal();
}
-SVal RegionStoreManager::Retrieve(const GRState* St, Loc L, QualType T) {
+//===----------------------------------------------------------------------===//
+// Loading values from regions.
+//===----------------------------------------------------------------------===//
+
+SVal RegionStoreManager::Retrieve(const GRState *state, Loc L, QualType T) {
+
assert(!isa<UnknownVal>(L) && "location unknown");
assert(!isa<UndefinedVal>(L) && "location undefined");
@@ -703,7 +821,7 @@ SVal RegionStoreManager::Retrieve(const GRState* St, Loc L, QualType T) {
if (isa<loc::ConcreteInt>(L))
return UndefinedVal();
- const MemRegion* MR = cast<loc::MemRegionVal>(L).getRegion();
+ const MemRegion *MR = cast<loc::MemRegionVal>(L).getRegion();
// FIXME: return symbolic value for these cases.
// Example:
@@ -716,7 +834,7 @@ SVal RegionStoreManager::Retrieve(const GRState* St, Loc L, QualType T) {
// FIXME: Perhaps this method should just take a 'const MemRegion*' argument
// instead of 'Loc', and have the other Loc cases handled at a higher level.
- const TypedRegion* R = cast<TypedRegion>(MR);
+ const TypedRegion *R = cast<TypedRegion>(MR);
assert(R && "bad region");
// FIXME: We should eventually handle funny addressing. e.g.:
@@ -731,26 +849,24 @@ SVal RegionStoreManager::Retrieve(const GRState* St, Loc L, QualType T) {
QualType RTy = R->getValueType(getContext());
if (RTy->isStructureType())
- return RetrieveStruct(St, R);
+ return RetrieveStruct(state, R);
if (RTy->isArrayType())
- return RetrieveArray(St, R);
+ return RetrieveArray(state, R);
// FIXME: handle Vector types.
if (RTy->isVectorType())
return UnknownVal();
- RegionBindingsTy B = GetRegionBindings(St->getStore());
+ RegionBindingsTy B = GetRegionBindings(state->getStore());
RegionBindingsTy::data_type* V = B.lookup(R);
// Check if the region has a binding.
if (V)
return *V;
- GRStateRef state(St, StateMgr);
-
// Check if the region is in killset.
- if (state.contains<RegionKills>(R))
+ if (state->contains<RegionKills>(R))
return UnknownVal();
// Check if the region is an element region of a string literal.
@@ -775,7 +891,7 @@ SVal RegionStoreManager::Retrieve(const GRState* St, Loc L, QualType T) {
if (isa<ElementRegion>(R) || isa<FieldRegion>(R)) {
const MemRegion* SuperR = cast<SubRegion>(R)->getSuperRegion();
GRStateTrait<RegionDefaultValue>::lookup_type D =
- state.get<RegionDefaultValue>(SuperR);
+ state->get<RegionDefaultValue>(SuperR);
if (D) {
// If the default value is symbolic, we need to create a new symbol.
if (D->hasConjuredSymbol())
@@ -829,14 +945,22 @@ SVal RegionStoreManager::Retrieve(const GRState* St, Loc L, QualType T) {
return UndefinedVal();
}
+ // If the region is already cast to another type, use that type to create the
+ // symbol value.
+ if (const QualType *p = state->get<RegionCasts>(R)) {
+ QualType T = *p;
+ RTy = T->getAsPointerType()->getPointeeType();
+ }
+
// All other integer values are symbolic.
if (Loc::IsLocType(RTy) || RTy->isIntegerType())
- return ValMgr.getRegionValueSymbolVal(R);
+ return ValMgr.getRegionValueSymbolVal(R, RTy);
else
return UnknownVal();
}
-SVal RegionStoreManager::RetrieveStruct(const GRState* St,const TypedRegion* R){
+SVal RegionStoreManager::RetrieveStruct(const GRState *state,
+ const TypedRegion* R){
QualType T = R->getValueType(getContext());
assert(T->isStructureType());
@@ -846,6 +970,8 @@ SVal RegionStoreManager::RetrieveStruct(const GRState* St,const TypedRegion* R){
llvm::ImmutableList<SVal> StructVal = getBasicVals().getEmptySValList();
+ // FIXME: We shouldn't use a std::vector. If RecordDecl doesn't have a
+ // reverse iterator, we should implement one.
std::vector<FieldDecl *> Fields(RD->field_begin(getContext()),
RD->field_end(getContext()));
@@ -854,14 +980,16 @@ SVal RegionStoreManager::RetrieveStruct(const GRState* St,const TypedRegion* R){
Field != FieldEnd; ++Field) {
FieldRegion* FR = MRMgr.getFieldRegion(*Field, R);
QualType FTy = (*Field)->getType();
- SVal FieldValue = Retrieve(St, loc::MemRegionVal(FR), FTy);
+ SVal FieldValue = Retrieve(state, loc::MemRegionVal(FR), FTy);
StructVal = getBasicVals().consVals(FieldValue, StructVal);
}
return NonLoc::MakeCompoundVal(T, StructVal, getBasicVals());
}
-SVal RegionStoreManager::RetrieveArray(const GRState* St, const TypedRegion* R){
+SVal RegionStoreManager::RetrieveArray(const GRState *state,
+ const TypedRegion * R) {
+
QualType T = R->getValueType(getContext());
ConstantArrayType* CAT = cast<ConstantArrayType>(T.getTypePtr());
@@ -871,41 +999,19 @@ SVal RegionStoreManager::RetrieveArray(const GRState* St, const TypedRegion* R){
for (; i < Size; ++i) {
SVal Idx = NonLoc::MakeVal(getBasicVals(), i);
- ElementRegion* ER = MRMgr.getElementRegion(CAT->getElementType(), Idx, R);
+ ElementRegion* ER = MRMgr.getElementRegion(CAT->getElementType(), Idx, R,
+ getContext());
QualType ETy = ER->getElementType();
- SVal ElementVal = Retrieve(St, loc::MemRegionVal(ER), ETy);
+ SVal ElementVal = Retrieve(state, loc::MemRegionVal(ER), ETy);
ArrayVal = getBasicVals().consVals(ElementVal, ArrayVal);
}
return NonLoc::MakeCompoundVal(T, ArrayVal, getBasicVals());
}
-const GRState* RegionStoreManager::Bind(const GRState* St, Loc L, SVal V) {
- // If we get here, the location should be a region.
- const MemRegion* R = cast<loc::MemRegionVal>(L).getRegion();
- assert(R);
-
- // Check if the region is a struct region.
- if (const TypedRegion* TR = dyn_cast<TypedRegion>(R))
- if (TR->getValueType(getContext())->isStructureType())
- return BindStruct(St, TR, V);
-
- Store store = St->getStore();
- RegionBindingsTy B = GetRegionBindings(store);
-
- if (V.isUnknown()) {
- // Remove the binding.
- store = RBFactory.Remove(B, R).getRoot();
-
- // Add the region to the killset.
- GRStateRef state(St, StateMgr);
- St = state.add<RegionKills>(R);
- }
- else
- store = RBFactory.Add(B, R, V).getRoot();
-
- return StateMgr.MakeStateWithStore(St, store);
-}
+//===----------------------------------------------------------------------===//
+// Binding values to regions.
+//===----------------------------------------------------------------------===//
Store RegionStoreManager::Remove(Store store, Loc L) {
const MemRegion* R = 0;
@@ -921,34 +1027,235 @@ Store RegionStoreManager::Remove(Store store, Loc L) {
return store;
}
-const GRState* RegionStoreManager::BindDecl(const GRState* St,
+const GRState *RegionStoreManager::Bind(const GRState *state, Loc L, SVal V) {
+ // If we get here, the location should be a region.
+ const MemRegion* R = cast<loc::MemRegionVal>(L).getRegion();
+
+ // Check if the region is a struct region.
+ if (const TypedRegion* TR = dyn_cast<TypedRegion>(R))
+ if (TR->getValueType(getContext())->isStructureType())
+ return BindStruct(state, TR, V);
+
+ RegionBindingsTy B = GetRegionBindings(state->getStore());
+
+ if (V.isUnknown()) {
+ B = RBFactory.Remove(B, R); // Remove the binding.
+ state = state->add<RegionKills>(R); // Add the region to the killset.
+ }
+ else
+ B = RBFactory.Add(B, R, V);
+
+ return state->makeWithStore(B.getRoot());
+}
+
+const GRState *RegionStoreManager::BindDecl(const GRState *state,
const VarDecl* VD, SVal InitVal) {
QualType T = VD->getType();
VarRegion* VR = MRMgr.getVarRegion(VD);
if (T->isArrayType())
- return BindArray(St, VR, InitVal);
+ return BindArray(state, VR, InitVal);
if (T->isStructureType())
- return BindStruct(St, VR, InitVal);
+ return BindStruct(state, VR, InitVal);
- return Bind(St, Loc::MakeVal(VR), InitVal);
+ return Bind(state, Loc::MakeVal(VR), InitVal);
}
// FIXME: this method should be merged into Bind().
-const GRState*
-RegionStoreManager::BindCompoundLiteral(const GRState* St,
- const CompoundLiteralExpr* CL, SVal V) {
+const GRState *
+RegionStoreManager::BindCompoundLiteral(const GRState *state,
+ const CompoundLiteralExpr* CL,
+ SVal V) {
+
CompoundLiteralRegion* R = MRMgr.getCompoundLiteralRegion(CL);
- return Bind(St, loc::MemRegionVal(R), V);
+ return Bind(state, loc::MemRegionVal(R), V);
}
-const GRState* RegionStoreManager::setExtent(const GRState* St,
- const MemRegion* R, SVal Extent) {
- GRStateRef state(St, StateMgr);
- return state.set<RegionExtents>(R, Extent);
+const GRState *RegionStoreManager::BindArray(const GRState *state,
+ const TypedRegion* R,
+ SVal Init) {
+
+ QualType T = R->getValueType(getContext());
+ assert(T->isArrayType());
+
+ // When we are binding the whole array, it always has default value 0.
+ state = state->set<RegionDefaultValue>(R, NonLoc::MakeIntVal(getBasicVals(),
+ 0, false));
+
+ ConstantArrayType* CAT = cast<ConstantArrayType>(T.getTypePtr());
+
+ llvm::APSInt Size(CAT->getSize(), false);
+ llvm::APSInt i = getBasicVals().getValue(0, Size.getBitWidth(),
+ Size.isUnsigned());
+
+ // Check if the init expr is a StringLiteral.
+ if (isa<loc::MemRegionVal>(Init)) {
+ const MemRegion* InitR = cast<loc::MemRegionVal>(Init).getRegion();
+ const StringLiteral* S = cast<StringRegion>(InitR)->getStringLiteral();
+ const char* str = S->getStrData();
+ unsigned len = S->getByteLength();
+ unsigned j = 0;
+
+ // Copy bytes from the string literal into the target array. Trailing bytes
+ // in the array that are not covered by the string literal are initialized
+ // to zero.
+ for (; i < Size; ++i, ++j) {
+ if (j >= len)
+ break;
+
+ SVal Idx = NonLoc::MakeVal(getBasicVals(), i);
+ ElementRegion* ER =
+ MRMgr.getElementRegion(cast<ArrayType>(T)->getElementType(),
+ Idx, R, getContext());
+
+ SVal V = NonLoc::MakeVal(getBasicVals(), str[j], sizeof(char)*8, true);
+ state = Bind(state, loc::MemRegionVal(ER), V);
+ }
+
+ return state;
+ }
+
+ nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(Init);
+ nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
+
+ for (; i < Size; ++i, ++VI) {
+ // The init list might be shorter than the array decl.
+ if (VI == VE)
+ break;
+
+ SVal Idx = NonLoc::MakeVal(getBasicVals(), i);
+ ElementRegion* ER =
+ MRMgr.getElementRegion(cast<ArrayType>(T)->getElementType(),
+ Idx, R, getContext());
+
+ if (CAT->getElementType()->isStructureType())
+ state = BindStruct(state, ER, *VI);
+ else
+ state = Bind(state, Loc::MakeVal(ER), *VI);
+ }
+
+ return state;
}
+const GRState *
+RegionStoreManager::BindStruct(const GRState *state, const TypedRegion* R,
+ SVal V) {
+
+ if (!Features.supportsFields())
+ return state;
+
+ QualType T = R->getValueType(getContext());
+ assert(T->isStructureType());
+
+ const RecordType* RT = T->getAsRecordType();
+ RecordDecl* RD = RT->getDecl();
+
+ if (!RD->isDefinition())
+ return state;
+
+ // We may get non-CompoundVal accidentally due to imprecise cast logic.
+ // Ignore them and kill the field values.
+ if (V.isUnknown() || !isa<nonloc::CompoundVal>(V))
+ return KillStruct(state, R);
+
+ nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(V);
+ nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
+
+ for (RecordDecl::field_iterator FI = RD->field_begin(getContext()),
+ FE = RD->field_end(getContext());
+ FI != FE; ++FI, ++VI) {
+
+ // There may be fewer values than fields only when we are initializing a
+ // struct decl. In this case, mark the region as having default value.
+ if (VI == VE) {
+ const NonLoc& Idx = NonLoc::MakeIntVal(getBasicVals(), 0, false);
+ state = state->set<RegionDefaultValue>(R, Idx);
+ break;
+ }
+
+ QualType FTy = (*FI)->getType();
+ FieldRegion* FR = MRMgr.getFieldRegion(*FI, R);
+
+ if (Loc::IsLocType(FTy) || FTy->isIntegerType())
+ state = Bind(state, Loc::MakeVal(FR), *VI);
+ else if (FTy->isArrayType())
+ state = BindArray(state, FR, *VI);
+ else if (FTy->isStructureType())
+ state = BindStruct(state, FR, *VI);
+ }
+
+ return state;
+}
+
+const GRState *RegionStoreManager::KillStruct(const GRState *state,
+ const TypedRegion* R){
+
+ // (1) Kill the struct region because it is assigned "unknown".
+ // (2) Set the default value of the struct region to "unknown".
+ state = state->add<RegionKills>(R)->set<RegionDefaultValue>(R, UnknownVal());
+ Store store = state->getStore();
+ RegionBindingsTy B = GetRegionBindings(store);
+
+ // Remove all bindings for the subregions of the struct.
+ for (RegionBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
+ const MemRegion* R = I.getKey();
+ if (const SubRegion* subRegion = dyn_cast<SubRegion>(R))
+ if (subRegion->isSubRegionOf(R))
+ store = Remove(store, Loc::MakeVal(subRegion));
+ // FIXME: Maybe we should also remove the bindings for the "views" of the
+ // subregions.
+ }
+
+ return state->makeWithStore(store);
+}
+
+//===----------------------------------------------------------------------===//
+// Region views.
+//===----------------------------------------------------------------------===//
+
+const GRState *RegionStoreManager::AddRegionView(const GRState *state,
+ const MemRegion* View,
+ const MemRegion* Base) {
+
+ // First, retrieve the region view of the base region.
+ const RegionViews* d = state->get<RegionViewMap>(Base);
+ RegionViews L = d ? *d : RVFactory.GetEmptySet();
+
+ // Now add View to the region view.
+ L = RVFactory.Add(L, View);
+
+ // Create a new state with the new region view.
+ return state->set<RegionViewMap>(Base, L);
+}
+
+const GRState *RegionStoreManager::RemoveRegionView(const GRState *state,
+ const MemRegion* View,
+ const MemRegion* Base) {
+ // Retrieve the region view of the base region.
+ const RegionViews* d = state->get<RegionViewMap>(Base);
+
+ // If the base region has no view, return.
+ if (!d)
+ return state;
+
+ // Remove the view.
+ return state->set<RegionViewMap>(Base, RVFactory.Remove(*d, View));
+}
+
+const GRState *RegionStoreManager::setCastType(const GRState *state,
+ const MemRegion* R, QualType T) {
+ return state->set<RegionCasts>(R, T);
+}
+
+const GRState *RegionStoreManager::setDefaultValue(const GRState *state,
+ const MemRegion* R, SVal V) {
+ return state->set<RegionDefaultValue>(R, V);
+}
+
+//===----------------------------------------------------------------------===//
+// State pruning.
+//===----------------------------------------------------------------------===//
static void UpdateLiveSymbols(SVal X, SymbolReaper& SymReaper) {
if (loc::MemRegionVal *XR = dyn_cast<loc::MemRegionVal>(&X)) {
@@ -975,11 +1282,10 @@ static void UpdateLiveSymbols(SVal X, SymbolReaper& SymReaper) {
SymReaper.markLive(*SI);
}
-Store RegionStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc,
+Store RegionStoreManager::RemoveDeadBindings(const GRState *state, Stmt* Loc,
SymbolReaper& SymReaper,
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots)
-{
-
+{
Store store = state->getStore();
RegionBindingsTy B = GetRegionBindings(store);
@@ -1002,18 +1308,17 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc,
// Do a pass over the regions in the store. For VarRegions we check if
// the variable is still live and if so add it to the list of live roots.
- // For other regions we populate our region backmap.
-
+ // For other regions we populate our region backmap.
llvm::SmallVector<const MemRegion*, 10> IntermediateRoots;
-
+
for (RegionBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
IntermediateRoots.push_back(I.getKey());
}
-
+
while (!IntermediateRoots.empty()) {
const MemRegion* R = IntermediateRoots.back();
IntermediateRoots.pop_back();
-
+
if (const VarRegion* VR = dyn_cast<VarRegion>(R)) {
if (SymReaper.isLive(Loc, VR->getDecl()))
RegionRoots.push_back(VR); // This is a live "root".
@@ -1025,14 +1330,14 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc,
else {
// Get the super region for R.
const MemRegion* SuperR = cast<SubRegion>(R)->getSuperRegion();
-
+
// Get the current set of subregions for SuperR.
const SubRegionsTy* SRptr = SubRegMap.lookup(SuperR);
SubRegionsTy SRs = SRptr ? *SRptr : SubRegF.GetEmptySet();
-
+
// Add R to the subregions of SuperR.
SubRegMap = SubRegMapF.Add(SubRegMap, SuperR, SubRegF.Add(SRs, R));
-
+
// Super region may be VarRegion or subregion of another VarRegion. Add it
// to the work list.
if (isa<SubRegion>(SuperR))
@@ -1048,10 +1353,10 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc,
// Dequeue the next region on the worklist.
const MemRegion* R = RegionRoots.back();
RegionRoots.pop_back();
-
+
// Check if we have already processed this region.
if (Marked.count(R)) continue;
-
+
// Mark this region as processed. This is needed for termination in case
// a region is referenced more than once.
Marked.insert(R);
@@ -1060,13 +1365,13 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc,
// should continue to track that symbol.
if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(R))
SymReaper.markLive(SymR->getSymbol());
-
+
// Get the data binding for R (if any).
RegionBindingsTy::data_type* Xptr = B.lookup(R);
if (Xptr) {
SVal X = *Xptr;
UpdateLiveSymbols(X, SymReaper); // Update the set of live symbols.
-
+
// If X is a region, then add it the RegionRoots.
if (loc::MemRegionVal* RegionX = dyn_cast<loc::MemRegionVal>(&X))
RegionRoots.push_back(RegionX->getRegion());
@@ -1094,11 +1399,11 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc,
// Remove this dead region from the store.
store = Remove(store, Loc::MakeVal(R));
-
+
// Mark all non-live symbols that this region references as dead.
if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(R))
SymReaper.maybeDead(SymR->getSymbol());
-
+
SVal X = I.getData();
SVal::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end();
for (; SI != SE; ++SI) SymReaper.maybeDead(*SI);
@@ -1107,203 +1412,18 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc,
return store;
}
+//===----------------------------------------------------------------------===//
+// Utility methods.
+//===----------------------------------------------------------------------===//
+
void RegionStoreManager::print(Store store, std::ostream& Out,
const char* nl, const char *sep) {
llvm::raw_os_ostream OS(Out);
RegionBindingsTy B = GetRegionBindings(store);
OS << "Store:" << nl;
-
+
for (RegionBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
OS << ' '; I.getKey()->print(OS); OS << " : ";
I.getData().print(OS); OS << nl;
}
}
-
-const GRState* RegionStoreManager::BindArray(const GRState* St,
- const TypedRegion* R, SVal Init) {
- QualType T = R->getValueType(getContext());
- assert(T->isArrayType());
-
- // When we are binding the whole array, it always has default value 0.
- GRStateRef state(St, StateMgr);
- St = state.set<RegionDefaultValue>(R, NonLoc::MakeIntVal(getBasicVals(), 0,
- false));
-
- ConstantArrayType* CAT = cast<ConstantArrayType>(T.getTypePtr());
-
- llvm::APSInt Size(CAT->getSize(), false);
- llvm::APSInt i = getBasicVals().getValue(0, Size.getBitWidth(),
- Size.isUnsigned());
-
- // Check if the init expr is a StringLiteral.
- if (isa<loc::MemRegionVal>(Init)) {
- const MemRegion* InitR = cast<loc::MemRegionVal>(Init).getRegion();
- const StringLiteral* S = cast<StringRegion>(InitR)->getStringLiteral();
- const char* str = S->getStrData();
- unsigned len = S->getByteLength();
- unsigned j = 0;
-
- // Copy bytes from the string literal into the target array. Trailing bytes
- // in the array that are not covered by the string literal are initialized
- // to zero.
- for (; i < Size; ++i, ++j) {
- if (j >= len)
- break;
-
- SVal Idx = NonLoc::MakeVal(getBasicVals(), i);
- ElementRegion* ER =
- MRMgr.getElementRegion(cast<ArrayType>(T)->getElementType(),
- Idx, R);
-
- SVal V = NonLoc::MakeVal(getBasicVals(), str[j], sizeof(char)*8, true);
- St = Bind(St, loc::MemRegionVal(ER), V);
- }
-
- return St;
- }
-
- nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(Init);
- nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
-
- for (; i < Size; ++i, ++VI) {
- // The init list might be shorter than the array decl.
- if (VI == VE)
- break;
-
- SVal Idx = NonLoc::MakeVal(getBasicVals(), i);
- ElementRegion* ER =
- MRMgr.getElementRegion(cast<ArrayType>(T)->getElementType(),
- Idx, R);
-
- if (CAT->getElementType()->isStructureType())
- St = BindStruct(St, ER, *VI);
- else
- St = Bind(St, Loc::MakeVal(ER), *VI);
- }
-
- return St;
-}
-
-const GRState*
-RegionStoreManager::BindStruct(const GRState* St, const TypedRegion* R, SVal V){
- QualType T = R->getValueType(getContext());
- assert(T->isStructureType());
-
- const RecordType* RT = T->getAsRecordType();
- RecordDecl* RD = RT->getDecl();
-
- if (!RD->isDefinition())
- return St;
-
- if (V.isUnknown())
- return KillStruct(St, R);
-
- // We may get non-CompoundVal accidentally due to imprecise cast logic. Ignore
- // them and make struct unknown.
- if (!isa<nonloc::CompoundVal>(V))
- return KillStruct(St, R);
-
- nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(V);
- nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
- RecordDecl::field_iterator FI = RD->field_begin(getContext()),
- FE = RD->field_end(getContext());
-
- for (; FI != FE; ++FI, ++VI) {
-
- // There may be fewer values than fields only when we are initializing a
- // struct decl. In this case, mark the region as having default value.
- if (VI == VE) {
- GRStateRef state(St, StateMgr);
- const NonLoc& Idx = NonLoc::MakeIntVal(getBasicVals(), 0, false);
- St = state.set<RegionDefaultValue>(R, Idx);
- break;
- }
-
- QualType FTy = (*FI)->getType();
- FieldRegion* FR = MRMgr.getFieldRegion(*FI, R);
-
- if (Loc::IsLocType(FTy) || FTy->isIntegerType())
- St = Bind(St, Loc::MakeVal(FR), *VI);
-
- else if (FTy->isArrayType())
- St = BindArray(St, FR, *VI);
-
- else if (FTy->isStructureType())
- St = BindStruct(St, FR, *VI);
- }
-
- return St;
-}
-
-const GRState* RegionStoreManager::KillStruct(const GRState* St,
- const TypedRegion* R){
- GRStateRef state(St, StateMgr);
-
- // Kill the struct region because it is assigned "unknown".
- St = state.add<RegionKills>(R);
-
- // Set the default value of the struct region to "unknown".
- St = state.set<RegionDefaultValue>(R, UnknownVal());
-
- Store store = St->getStore();
- RegionBindingsTy B = GetRegionBindings(store);
-
- // Remove all bindings for the subregions of the struct.
- for (RegionBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
- const MemRegion* r = I.getKey();
- if (const SubRegion* sr = dyn_cast<SubRegion>(r))
- if (sr->isSubRegionOf(R))
- store = Remove(store, Loc::MakeVal(sr));
- // FIXME: Maybe we should also remove the bindings for the "views" of the
- // subregions.
- }
-
- return StateMgr.MakeStateWithStore(St, store);
-}
-
-const GRState* RegionStoreManager::AddRegionView(const GRState* St,
- const MemRegion* View,
- const MemRegion* Base) {
- GRStateRef state(St, StateMgr);
-
- // First, retrieve the region view of the base region.
- const RegionViews* d = state.get<RegionViewMap>(Base);
- RegionViews L = d ? *d : RVFactory.GetEmptySet();
-
- // Now add View to the region view.
- L = RVFactory.Add(L, View);
-
- // Create a new state with the new region view.
- return state.set<RegionViewMap>(Base, L);
-}
-
-const GRState* RegionStoreManager::RemoveRegionView(const GRState* St,
- const MemRegion* View,
- const MemRegion* Base) {
- GRStateRef state(St, StateMgr);
-
- // Retrieve the region view of the base region.
- const RegionViews* d = state.get<RegionViewMap>(Base);
-
- // If the base region has no view, return.
- if (!d)
- return St;
-
- // Remove the view.
- RegionViews V = *d;
- V = RVFactory.Remove(V, View);
-
- return state.set<RegionViewMap>(Base, V);
-}
-
-const GRState* RegionStoreManager::setCastType(const GRState* St,
- const MemRegion* R, QualType T) {
- GRStateRef state(St, StateMgr);
- return state.set<RegionCasts>(R, T);
-}
-
-const GRState* RegionStoreManager::setDefaultValue(const GRState* St,
- const MemRegion* R, SVal V) {
- GRStateRef state(St, StateMgr);
- return state.set<RegionDefaultValue>(R, V);
-}
diff --git a/lib/Analysis/SVals.cpp b/lib/Analysis/SVals.cpp
index e19b16867b39..77c3c8f7722a 100644
--- a/lib/Analysis/SVals.cpp
+++ b/lib/Analysis/SVals.cpp
@@ -294,7 +294,7 @@ NonLoc NonLoc::MakeVal(BasicValueFactory& BasicVals, uint64_t X, QualType T) {
return nonloc::ConcreteInt(BasicVals.getValue(X, T));
}
-NonLoc NonLoc::MakeVal(BasicValueFactory& BasicVals, IntegerLiteral* I) {
+NonLoc NonLoc::MakeVal(BasicValueFactory& BasicVals, const IntegerLiteral* I) {
return nonloc::ConcreteInt(BasicVals.getValue(APSInt(I->getValue(),
I->getType()->isUnsignedIntegerType())));
@@ -322,11 +322,12 @@ NonLoc NonLoc::MakeCompoundVal(QualType T, llvm::ImmutableList<SVal> Vals,
return nonloc::CompoundVal(BasicVals.getCompoundValData(T, Vals));
}
-SVal ValueManager::getRegionValueSymbolVal(const MemRegion* R) {
- SymbolRef sym = SymMgr.getRegionValueSymbol(R);
+SVal ValueManager::getRegionValueSymbolVal(const MemRegion* R, QualType T) {
+ SymbolRef sym = SymMgr.getRegionValueSymbol(R, T);
if (const TypedRegion* TR = dyn_cast<TypedRegion>(R)) {
- QualType T = TR->getValueType(SymMgr.getContext());
+ if (T.isNull())
+ T = TR->getValueType(SymMgr.getContext());
// If T is of function pointer type, create a CodeTextRegion wrapping a
// symbol.
@@ -401,7 +402,9 @@ nonloc::LocAsInteger nonloc::LocAsInteger::Make(BasicValueFactory& Vals, Loc V,
Loc Loc::MakeVal(const MemRegion* R) { return loc::MemRegionVal(R); }
-Loc Loc::MakeVal(AddrLabelExpr* E) { return loc::GotoLabel(E->getLabel()); }
+Loc Loc::MakeVal(const AddrLabelExpr *E) {
+ return loc::GotoLabel(E->getLabel());
+}
Loc Loc::MakeNull(BasicValueFactory &BasicVals) {
return loc::ConcreteInt(BasicVals.getZeroWithPtrWidth());
diff --git a/lib/Analysis/SimpleConstraintManager.cpp b/lib/Analysis/SimpleConstraintManager.cpp
index f79dba0cc5ee..82801eb05d38 100644
--- a/lib/Analysis/SimpleConstraintManager.cpp
+++ b/lib/Analysis/SimpleConstraintManager.cpp
@@ -55,60 +55,55 @@ bool SimpleConstraintManager::canReasonAbout(SVal X) const {
return true;
}
-const GRState*
-SimpleConstraintManager::Assume(const GRState* St, SVal Cond, bool Assumption,
- bool& isFeasible) {
+const GRState *SimpleConstraintManager::Assume(const GRState *state,
+ SVal Cond, bool Assumption) {
if (Cond.isUnknown()) {
- isFeasible = true;
- return St;
+ return state;
}
if (isa<NonLoc>(Cond))
- return Assume(St, cast<NonLoc>(Cond), Assumption, isFeasible);
+ return Assume(state, cast<NonLoc>(Cond), Assumption);
else
- return Assume(St, cast<Loc>(Cond), Assumption, isFeasible);
+ return Assume(state, cast<Loc>(Cond), Assumption);
}
-const GRState*
-SimpleConstraintManager::Assume(const GRState* St, Loc Cond, bool Assumption,
- bool& isFeasible) {
- St = AssumeAux(St, Cond, Assumption, isFeasible);
-
- if (!isFeasible)
- return St;
-
+const GRState *SimpleConstraintManager::Assume(const GRState *state, Loc Cond,
+ bool Assumption) {
+
+ state = AssumeAux(state, Cond, Assumption);
+
// EvalAssume is used to call into the GRTransferFunction object to perform
// any checker-specific update of the state based on this assumption being
- // true or false.
- return StateMgr.getTransferFuncs().EvalAssume(StateMgr, St, Cond, Assumption,
- isFeasible);
+ // true or false.
+ return state ? state->getTransferFuncs().EvalAssume(state, Cond, Assumption)
+ : NULL;
}
-const GRState*
-SimpleConstraintManager::AssumeAux(const GRState* St, Loc Cond, bool Assumption,
- bool& isFeasible) {
- BasicValueFactory& BasicVals = StateMgr.getBasicVals();
+const GRState *SimpleConstraintManager::AssumeAux(const GRState *state,
+ Loc Cond, bool Assumption) {
+
+ BasicValueFactory &BasicVals = state->getBasicVals();
switch (Cond.getSubKind()) {
default:
assert (false && "'Assume' not implemented for this Loc.");
- return St;
+ return state;
case loc::MemRegionKind: {
// FIXME: Should this go into the storemanager?
- const MemRegion* R = cast<loc::MemRegionVal>(Cond).getRegion();
- const SubRegion* SubR = dyn_cast<SubRegion>(R);
+ const MemRegion *R = cast<loc::MemRegionVal>(Cond).getRegion();
+ const SubRegion *SubR = dyn_cast<SubRegion>(R);
while (SubR) {
// FIXME: now we only find the first symbolic region.
- if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(SubR)) {
+ if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(SubR)) {
if (Assumption)
- return AssumeSymNE(St, SymR->getSymbol(),
- BasicVals.getZeroWithPtrWidth(), isFeasible);
+ return AssumeSymNE(state, SymR->getSymbol(),
+ BasicVals.getZeroWithPtrWidth());
else
- return AssumeSymEQ(St, SymR->getSymbol(),
- BasicVals.getZeroWithPtrWidth(), isFeasible);
+ return AssumeSymEQ(state, SymR->getSymbol(),
+ BasicVals.getZeroWithPtrWidth());
}
SubR = dyn_cast<SubRegion>(SubR->getSuperRegion());
}
@@ -117,43 +112,42 @@ SimpleConstraintManager::AssumeAux(const GRState* St, Loc Cond, bool Assumption,
}
case loc::GotoLabelKind:
- isFeasible = Assumption;
- return St;
+ return Assumption ? state : NULL;
case loc::ConcreteIntKind: {
- bool b = cast<loc::ConcreteInt>(Cond).getValue() != 0;
- isFeasible = b ? Assumption : !Assumption;
- return St;
+ bool b = cast<loc::ConcreteInt>(Cond).getValue() != 0;
+ bool isFeasible = b ? Assumption : !Assumption;
+ return isFeasible ? state : NULL;
}
} // end switch
}
-const GRState*
-SimpleConstraintManager::Assume(const GRState* St, NonLoc Cond, bool Assumption,
- bool& isFeasible) {
- St = AssumeAux(St, Cond, Assumption, isFeasible);
-
- if (!isFeasible)
- return St;
-
+const GRState *SimpleConstraintManager::Assume(const GRState *state,
+ NonLoc Cond,
+ bool Assumption) {
+
+ state = AssumeAux(state, Cond, Assumption);
+
// EvalAssume is used to call into the GRTransferFunction object to perform
// any checker-specific update of the state based on this assumption being
- // true or false.
- return StateMgr.getTransferFuncs().EvalAssume(StateMgr, St, Cond, Assumption,
- isFeasible);
+ // true or false.
+ return state ? state->getTransferFuncs().EvalAssume(state, Cond, Assumption)
+ : NULL;
}
-const GRState*
-SimpleConstraintManager::AssumeAux(const GRState* St,NonLoc Cond,
- bool Assumption, bool& isFeasible) {
+const GRState *SimpleConstraintManager::AssumeAux(const GRState *state,
+ NonLoc Cond,
+ bool Assumption) {
+
// We cannot reason about SymIntExpr and SymSymExpr.
if (!canReasonAbout(Cond)) {
- isFeasible = true;
- return St;
+ // Just return the current state indicating that the path is feasible.
+ // This may be an over-approximation of what is possible.
+ return state;
}
- BasicValueFactory& BasicVals = StateMgr.getBasicVals();
- SymbolManager& SymMgr = StateMgr.getSymbolManager();
+ BasicValueFactory &BasicVals = state->getBasicVals();
+ SymbolManager &SymMgr = state->getSymbolManager();
switch (Cond.getSubKind()) {
default:
@@ -162,38 +156,38 @@ SimpleConstraintManager::AssumeAux(const GRState* St,NonLoc Cond,
case nonloc::SymbolValKind: {
nonloc::SymbolVal& SV = cast<nonloc::SymbolVal>(Cond);
SymbolRef sym = SV.getSymbol();
- QualType T = SymMgr.getType(sym);
-
- if (Assumption)
- return AssumeSymNE(St, sym, BasicVals.getValue(0, T), isFeasible);
- else
- return AssumeSymEQ(St, sym, BasicVals.getValue(0, T), isFeasible);
+ QualType T = SymMgr.getType(sym);
+ const llvm::APSInt &zero = BasicVals.getValue(0, T);
+
+ return Assumption ? AssumeSymNE(state, sym, zero)
+ : AssumeSymEQ(state, sym, zero);
}
case nonloc::SymExprValKind: {
nonloc::SymExprVal V = cast<nonloc::SymExprVal>(Cond);
if (const SymIntExpr *SE = dyn_cast<SymIntExpr>(V.getSymbolicExpression()))
- return AssumeSymInt(St, Assumption, SE, isFeasible);
+ return AssumeSymInt(state, Assumption, SE);
- isFeasible = true;
- return St;
+ // For all other symbolic expressions, over-approximate and consider
+ // the constraint feasible.
+ return state;
}
case nonloc::ConcreteIntKind: {
bool b = cast<nonloc::ConcreteInt>(Cond).getValue() != 0;
- isFeasible = b ? Assumption : !Assumption;
- return St;
+ bool isFeasible = b ? Assumption : !Assumption;
+ return isFeasible ? state : NULL;
}
case nonloc::LocAsIntegerKind:
- return AssumeAux(St, cast<nonloc::LocAsInteger>(Cond).getLoc(),
- Assumption, isFeasible);
+ return AssumeAux(state, cast<nonloc::LocAsInteger>(Cond).getLoc(),
+ Assumption);
} // end switch
}
-const GRState*
-SimpleConstraintManager::AssumeSymInt(const GRState* St, bool Assumption,
- const SymIntExpr *SE, bool& isFeasible) {
+const GRState *SimpleConstraintManager::AssumeSymInt(const GRState *state,
+ bool Assumption,
+ const SymIntExpr *SE) {
// Here we assume that LHS is a symbol. This is consistent with the
@@ -203,47 +197,44 @@ SimpleConstraintManager::AssumeSymInt(const GRState* St, bool Assumption,
switch (SE->getOpcode()) {
default:
- // No logic yet for other operators.
- isFeasible = true;
- return St;
+ // No logic yet for other operators. Assume the constraint is feasible.
+ return state;
case BinaryOperator::EQ:
- return Assumption ? AssumeSymEQ(St, Sym, Int, isFeasible)
- : AssumeSymNE(St, Sym, Int, isFeasible);
+ return Assumption ? AssumeSymEQ(state, Sym, Int)
+ : AssumeSymNE(state, Sym, Int);
case BinaryOperator::NE:
- return Assumption ? AssumeSymNE(St, Sym, Int, isFeasible)
- : AssumeSymEQ(St, Sym, Int, isFeasible);
-
+ return Assumption ? AssumeSymNE(state, Sym, Int)
+ : AssumeSymEQ(state, Sym, Int);
case BinaryOperator::GT:
- return Assumption ? AssumeSymGT(St, Sym, Int, isFeasible)
- : AssumeSymLE(St, Sym, Int, isFeasible);
+ return Assumption ? AssumeSymGT(state, Sym, Int)
+ : AssumeSymLE(state, Sym, Int);
case BinaryOperator::GE:
- return Assumption ? AssumeSymGE(St, Sym, Int, isFeasible)
- : AssumeSymLT(St, Sym, Int, isFeasible);
+ return Assumption ? AssumeSymGE(state, Sym, Int)
+ : AssumeSymLT(state, Sym, Int);
case BinaryOperator::LT:
- return Assumption ? AssumeSymLT(St, Sym, Int, isFeasible)
- : AssumeSymGE(St, Sym, Int, isFeasible);
+ return Assumption ? AssumeSymLT(state, Sym, Int)
+ : AssumeSymGE(state, Sym, Int);
case BinaryOperator::LE:
- return Assumption ? AssumeSymLE(St, Sym, Int, isFeasible)
- : AssumeSymGT(St, Sym, Int, isFeasible);
+ return Assumption ? AssumeSymLE(state, Sym, Int)
+ : AssumeSymGT(state, Sym, Int);
} // end switch
}
-const GRState*
-SimpleConstraintManager::AssumeInBound(const GRState* St, SVal Idx,
- SVal UpperBound, bool Assumption,
- bool& isFeasible) {
+const GRState *SimpleConstraintManager::AssumeInBound(const GRState *state,
+ SVal Idx,
+ SVal UpperBound,
+ bool Assumption) {
+
// Only support ConcreteInt for now.
- if (!(isa<nonloc::ConcreteInt>(Idx) && isa<nonloc::ConcreteInt>(UpperBound))){
- isFeasible = true;
- return St;
- }
+ if (!(isa<nonloc::ConcreteInt>(Idx) && isa<nonloc::ConcreteInt>(UpperBound)))
+ return state;
- const llvm::APSInt& Zero = getBasicVals().getZeroWithPtrWidth(false);
+ const llvm::APSInt& Zero = state->getBasicVals().getZeroWithPtrWidth(false);
llvm::APSInt IdxV = cast<nonloc::ConcreteInt>(Idx).getValue();
// IdxV might be too narrow.
if (IdxV.getBitWidth() < Zero.getBitWidth())
@@ -254,10 +245,8 @@ SimpleConstraintManager::AssumeInBound(const GRState* St, SVal Idx,
UBV.extend(Zero.getBitWidth());
bool InBound = (Zero <= IdxV) && (IdxV < UBV);
-
- isFeasible = Assumption ? InBound : !InBound;
-
- return St;
+ bool isFeasible = Assumption ? InBound : !InBound;
+ return isFeasible ? state : NULL;
}
} // end of namespace clang
diff --git a/lib/Analysis/SimpleConstraintManager.h b/lib/Analysis/SimpleConstraintManager.h
index fb41e2f1dab2..1e1a10da030f 100644
--- a/lib/Analysis/SimpleConstraintManager.h
+++ b/lib/Analysis/SimpleConstraintManager.h
@@ -20,63 +20,59 @@
namespace clang {
class SimpleConstraintManager : public ConstraintManager {
-protected:
- GRStateManager& StateMgr;
public:
- SimpleConstraintManager(GRStateManager& statemgr)
- : StateMgr(statemgr) {}
- virtual ~SimpleConstraintManager();
-
- bool canReasonAbout(SVal X) const;
+ SimpleConstraintManager() {}
+ virtual ~SimpleConstraintManager();
- virtual const GRState* Assume(const GRState* St, SVal Cond, bool Assumption,
- bool& isFeasible);
-
- const GRState* Assume(const GRState* St, Loc Cond, bool Assumption,
- bool& isFeasible);
+ //===------------------------------------------------------------------===//
+ // Common implementation for the interface provided by ConstraintManager.
+ //===------------------------------------------------------------------===//
- const GRState* AssumeAux(const GRState* St, Loc Cond,bool Assumption,
- bool& isFeasible);
-
- const GRState* Assume(const GRState* St, NonLoc Cond, bool Assumption,
- bool& isFeasible);
-
- const GRState* AssumeAux(const GRState* St, NonLoc Cond, bool Assumption,
- bool& isFeasible);
+ bool canReasonAbout(SVal X) const;
- const GRState* AssumeSymInt(const GRState* St, bool Assumption,
- const SymIntExpr *SE, bool& isFeasible);
+ const GRState *Assume(const GRState *state, SVal Cond, bool Assumption);
- virtual const GRState* AssumeSymNE(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V,
- bool& isFeasible) = 0;
+ const GRState *Assume(const GRState *state, Loc Cond, bool Assumption);
- virtual const GRState* AssumeSymEQ(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V,
- bool& isFeasible) = 0;
+ const GRState *Assume(const GRState *state, NonLoc Cond, bool Assumption);
- virtual const GRState* AssumeSymLT(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V,
- bool& isFeasible) = 0;
+ const GRState *AssumeSymInt(const GRState *state, bool Assumption,
+ const SymIntExpr *SE);
+
+ const GRState *AssumeInBound(const GRState *state, SVal Idx, SVal UpperBound,
+ bool Assumption);
+
+protected:
+
+ //===------------------------------------------------------------------===//
+ // Interface that subclasses must implement.
+ //===------------------------------------------------------------------===//
+
+ virtual const GRState *AssumeSymNE(const GRState *state, SymbolRef sym,
+ const llvm::APSInt& V) = 0;
- virtual const GRState* AssumeSymGT(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V,
- bool& isFeasible) = 0;
+ virtual const GRState *AssumeSymEQ(const GRState *state, SymbolRef sym,
+ const llvm::APSInt& V) = 0;
- virtual const GRState* AssumeSymLE(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V,
- bool& isFeasible) = 0;
+ virtual const GRState *AssumeSymLT(const GRState *state, SymbolRef sym,
+ const llvm::APSInt& V) = 0;
- virtual const GRState* AssumeSymGE(const GRState* St, SymbolRef sym,
- const llvm::APSInt& V,
- bool& isFeasible) = 0;
+ virtual const GRState *AssumeSymGT(const GRState *state, SymbolRef sym,
+ const llvm::APSInt& V) = 0;
- const GRState* AssumeInBound(const GRState* St, SVal Idx, SVal UpperBound,
- bool Assumption, bool& isFeasible);
+ virtual const GRState *AssumeSymLE(const GRState *state, SymbolRef sym,
+ const llvm::APSInt& V) = 0;
-private:
- BasicValueFactory& getBasicVals() { return StateMgr.getBasicVals(); }
- SymbolManager& getSymbolManager() const { return StateMgr.getSymbolManager(); }
+ virtual const GRState *AssumeSymGE(const GRState *state, SymbolRef sym,
+ const llvm::APSInt& V) = 0;
+
+ //===------------------------------------------------------------------===//
+ // Internal implementation.
+ //===------------------------------------------------------------------===//
+
+ const GRState *AssumeAux(const GRState *state, Loc Cond,bool Assumption);
+
+ const GRState *AssumeAux(const GRState *state, NonLoc Cond, bool Assumption);
};
} // end clang namespace
diff --git a/lib/Analysis/Store.cpp b/lib/Analysis/Store.cpp
index 13326ab31f82..5aa756e14be3 100644
--- a/lib/Analysis/Store.cpp
+++ b/lib/Analysis/Store.cpp
@@ -90,7 +90,8 @@ StoreManager::CastRegion(const GRState* state, const MemRegion* R,
// FIXME: Is this the right thing to do in all cases?
const TypedRegion *Base = isa<ElementRegion>(TR) ?
cast<TypedRegion>(TR->getSuperRegion()) : TR;
- ElementRegion* ER = MRMgr.getElementRegion(Pointee, Idx, Base);
+ ElementRegion* ER = MRMgr.getElementRegion(Pointee, Idx, Base,
+ StateMgr.getContext());
return CastResult(state, ER);
}
}
diff --git a/lib/Analysis/SymbolManager.cpp b/lib/Analysis/SymbolManager.cpp
index 5c885cd6e15a..4e38a3492c79 100644
--- a/lib/Analysis/SymbolManager.cpp
+++ b/lib/Analysis/SymbolManager.cpp
@@ -92,14 +92,14 @@ std::ostream& std::operator<<(std::ostream& os, const SymExpr *SE) {
}
const SymbolRegionValue*
-SymbolManager::getRegionValueSymbol(const MemRegion* R) {
+SymbolManager::getRegionValueSymbol(const MemRegion* R, QualType T) {
llvm::FoldingSetNodeID profile;
- SymbolRegionValue::Profile(profile, R);
+ SymbolRegionValue::Profile(profile, R, T);
void* InsertPos;
SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
if (!SD) {
SD = (SymExpr*) BPAlloc.Allocate<SymbolRegionValue>();
- new (SD) SymbolRegionValue(SymbolCounter, R);
+ new (SD) SymbolRegionValue(SymbolCounter, R, T);
DataSet.InsertNode(SD, InsertPos);
++SymbolCounter;
}
@@ -166,6 +166,9 @@ QualType SymbolConjured::getType(ASTContext&) const {
}
QualType SymbolRegionValue::getType(ASTContext& C) const {
+ if (!T.isNull())
+ return T;
+
if (const TypedRegion* TR = dyn_cast<TypedRegion>(R))
return TR->getValueType(C);
diff --git a/lib/Basic/Builtins.cpp b/lib/Basic/Builtins.cpp
index ebe0514fa008..6cb5dab53df2 100644
--- a/lib/Basic/Builtins.cpp
+++ b/lib/Basic/Builtins.cpp
@@ -30,11 +30,17 @@ const Builtin::Info &Builtin::Context::GetRecord(unsigned ID) const {
return TSRecords[ID - Builtin::FirstTSBuiltin];
}
+Builtin::Context::Context(const TargetInfo &Target) {
+ // Get the target specific builtins from the target.
+ TSRecords = 0;
+ NumTSRecords = 0;
+ Target.getTargetBuiltins(TSRecords, NumTSRecords);
+}
+
/// InitializeBuiltins - Mark the identifiers for all the builtins with their
/// appropriate builtin ID # and mark any non-portable builtin identifiers as
/// such.
void Builtin::Context::InitializeBuiltins(IdentifierTable &Table,
- const TargetInfo &Target,
bool NoBuiltins) {
// Step #1: mark all target-independent builtins with their ID's.
for (unsigned i = Builtin::NotBuiltin+1; i != Builtin::FirstTSBuiltin; ++i)
@@ -42,9 +48,6 @@ void Builtin::Context::InitializeBuiltins(IdentifierTable &Table,
(!NoBuiltins || !strchr(BuiltinInfo[i].Attributes, 'f')))
Table.get(BuiltinInfo[i].Name).setBuiltinID(i);
- // Get the target specific builtins from the target.
- Target.getTargetBuiltins(TSRecords, NumTSRecords);
-
// Step #2: Register target-specific builtins.
for (unsigned i = 0, e = NumTSRecords; i != e; ++i)
if (!TSRecords[i].Suppressed &&
diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp
index 323f7a7d4afd..78b8b0a85597 100644
--- a/lib/Basic/Diagnostic.cpp
+++ b/lib/Basic/Diagnostic.cpp
@@ -118,7 +118,7 @@ const char *Diagnostic::getWarningOptionForDiag(unsigned DiagID) {
bool Diagnostic::isBuiltinSFINAEDiag(unsigned DiagID) {
if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
- return Info->SFINAE && Info->Class != CLASS_NOTE;
+ return Info->SFINAE && Info->Class == CLASS_ERROR;
return false;
}
diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp
index ed5eb46c2847..8dfc5d100e85 100644
--- a/lib/Basic/SourceManager.cpp
+++ b/lib/Basic/SourceManager.cpp
@@ -358,7 +358,10 @@ FileID SourceManager::createFileID(const ContentCache *File,
SLocEntryTable[PreallocatedID]
= SLocEntry::get(Offset, FileInfo::get(IncludePos, File, FileCharacter));
SLocEntryLoaded[PreallocatedID] = true;
- return LastFileIDLookup = FileID::get(PreallocatedID);
+ FileID FID = FileID::get(PreallocatedID);
+ if (File->FirstFID.isInvalid())
+ File->FirstFID = FID;
+ return LastFileIDLookup = FID;
}
SLocEntryTable.push_back(SLocEntry::get(NextOffset,
@@ -914,6 +917,43 @@ PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc) const {
// Other miscellaneous methods.
//===----------------------------------------------------------------------===//
+/// \brief Get the source location for the given file:line:col triplet.
+///
+/// If the source file is included multiple times, the source location will
+/// be based upon the first inclusion.
+SourceLocation SourceManager::getLocation(const FileEntry *SourceFile,
+ unsigned Line, unsigned Col) const {
+ assert(SourceFile && "Null source file!");
+ assert(Line && Col && "Line and column should start from 1!");
+
+ fileinfo_iterator FI = FileInfos.find(SourceFile);
+ if (FI == FileInfos.end())
+ return SourceLocation();
+ ContentCache *Content = FI->second;
+
+ // If this is the first use of line information for this buffer, compute the
+ /// SourceLineCache for it on demand.
+ if (Content->SourceLineCache == 0)
+ ComputeLineNumbers(Content, ContentCacheAlloc);
+
+ if (Line > Content->NumLines)
+ return SourceLocation();
+
+ unsigned FilePos = Content->SourceLineCache[Line - 1];
+ const char *Buf = Content->getBuffer()->getBufferStart();
+ unsigned BufLength = Content->getBuffer()->getBufferEnd() - Buf;
+ unsigned i = 0;
+
+ // Check that the given column is valid.
+ while (i < BufLength-1 && i < Col-1 && Buf[i] != '\n' && Buf[i] != '\r')
+ ++i;
+ if (i < Col-1)
+ return SourceLocation();
+
+ return getLocForStartOfFile(Content->FirstFID).
+ getFileLocWithOffset(FilePos + Col - 1);
+}
+
/// PrintStats - Print statistics to stderr.
///
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index a919dfa2e32c..66b1f17368ea 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -522,7 +522,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BIsqrtf:
case Builtin::BIsqrtl: {
// Rewrite sqrt to intrinsic if allowed.
- if (!FD->hasAttr<ConstAttr>())
+ if (!FD->hasAttr<ConstAttr>(getContext()))
break;
Value *Arg0 = EmitScalarExpr(E->getArg(0));
const llvm::Type *ArgType = Arg0->getType();
@@ -534,7 +534,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BIpowf:
case Builtin::BIpowl: {
// Rewrite sqrt to intrinsic if allowed.
- if (!FD->hasAttr<ConstAttr>())
+ if (!FD->hasAttr<ConstAttr>(getContext()))
break;
Value *Base = EmitScalarExpr(E->getArg(0));
Value *Exponent = EmitScalarExpr(E->getArg(1));
diff --git a/lib/CodeGen/CGCXXTemp.cpp b/lib/CodeGen/CGCXXTemp.cpp
index 141726a649cf..a6e6d11505b6 100644
--- a/lib/CodeGen/CGCXXTemp.cpp
+++ b/lib/CodeGen/CGCXXTemp.cpp
@@ -85,6 +85,11 @@ RValue
CodeGenFunction::EmitCXXExprWithTemporaries(const CXXExprWithTemporaries *E,
llvm::Value *AggLoc,
bool isAggLocVolatile) {
+ // If we shouldn't destroy the temporaries, just emit the
+ // child expression.
+ if (!E->shouldDestroyTemporaries())
+ return EmitAnyExpr(E->getSubExpr(), AggLoc, isAggLocVolatile);
+
// Keep track of the current cleanup stack depth.
size_t CleanupStackDepth = CleanupEntries.size();
(void) CleanupStackDepth;
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index 4037f32ac186..ec6058afd963 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -377,13 +377,13 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
// FIXME: handle sseregparm someday...
if (TargetDecl) {
- if (TargetDecl->hasAttr<NoThrowAttr>())
+ if (TargetDecl->hasAttr<NoThrowAttr>(getContext()))
FuncAttrs |= llvm::Attribute::NoUnwind;
- if (TargetDecl->hasAttr<NoReturnAttr>())
+ if (TargetDecl->hasAttr<NoReturnAttr>(getContext()))
FuncAttrs |= llvm::Attribute::NoReturn;
- if (TargetDecl->hasAttr<ConstAttr>())
+ if (TargetDecl->hasAttr<ConstAttr>(getContext()))
FuncAttrs |= llvm::Attribute::ReadNone;
- else if (TargetDecl->hasAttr<PureAttr>())
+ else if (TargetDecl->hasAttr<PureAttr>(getContext()))
FuncAttrs |= llvm::Attribute::ReadOnly;
}
@@ -432,7 +432,8 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
// register variable.
signed RegParm = 0;
if (TargetDecl)
- if (const RegparmAttr *RegParmAttr = TargetDecl->getAttr<RegparmAttr>())
+ if (const RegparmAttr *RegParmAttr
+ = TargetDecl->getAttr<RegparmAttr>(getContext()))
RegParm = RegParmAttr->getNumParams();
unsigned PointerWidth = getContext().Target.getPointerWidth(0);
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index 049e716c7c1b..a2b8d13e3c99 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -50,6 +50,24 @@ void CGDebugInfo::setLocation(SourceLocation Loc) {
/// getOrCreateCompileUnit - Get the compile unit from the cache or create a new
/// one if necessary. This returns null for invalid source locations.
llvm::DICompileUnit CGDebugInfo::getOrCreateCompileUnit(SourceLocation Loc) {
+
+ // Each input file is encoded as a separate compile unit in LLVM
+ // debugging information output. However, many target specific tool chains
+ // prefer to encode only one compile unit in an object file. In this
+ // situation, the LLVM code generator will include debugging information
+ // entities in the compile unit that is marked as main compile unit. The
+ // code generator accepts maximum one main compile unit per module. If a
+ // module does not contain any main compile unit then the code generator
+ // will emit multiple compile units in the output object file. Create main
+ // compile unit if there is not one available.
+ const LangOptions &LO = M->getLangOptions();
+ if (isMainCompileUnitCreated == false) {
+ if (LO.getMainFileName()) {
+ createCompileUnit(LO.getMainFileName(), true /* isMain */);
+ isMainCompileUnitCreated = true;
+ }
+ }
+
// Get source file information.
const char *FileName = "<unknown>";
SourceManager &SM = M->getContext().getSourceManager();
@@ -72,25 +90,26 @@ llvm::DICompileUnit CGDebugInfo::getOrCreateCompileUnit(SourceLocation Loc) {
AbsFileName = tmp;
}
- // See if thie compile unit is representing main source file. Each source
- // file has corresponding compile unit. There is only one main source
- // file at a time.
- bool isMain = false;
- const LangOptions &LO = M->getLangOptions();
- const char *MainFileName = LO.getMainFileName();
- if (isMainCompileUnitCreated == false) {
- if (MainFileName) {
- if (!strcmp(AbsFileName.getLast().c_str(), MainFileName))
- isMain = true;
- } else {
- if (Loc.isValid() && SM.isFromMainFile(Loc))
- isMain = true;
- }
- if (isMain)
- isMainCompileUnitCreated = true;
+ // There is only one main source file at a time whose compile unit
+ // is already created.
+ Unit = createCompileUnit(FileName, false /* isMain */);
+ return Unit;
+}
+
+/// createCompileUnit - Create a new unit for the given file.
+llvm::DICompileUnit CGDebugInfo::createCompileUnit(const char *FileName,
+ bool isMain) {
+
+ // Get absolute path name.
+ llvm::sys::Path AbsFileName(FileName);
+ if (!AbsFileName.isAbsolute()) {
+ llvm::sys::Path tmp = llvm::sys::Path::GetCurrentDirectory();
+ tmp.appendComponent(FileName);
+ AbsFileName = tmp;
}
unsigned LangTag;
+ const LangOptions &LO = M->getLangOptions();
if (LO.CPlusPlus) {
if (LO.ObjC1)
LangTag = llvm::dwarf::DW_LANG_ObjC_plus_plus;
@@ -114,12 +133,13 @@ llvm::DICompileUnit CGDebugInfo::getOrCreateCompileUnit(SourceLocation Loc) {
RuntimeVers = LO.ObjCNonFragileABI ? 2 : 1;
// Create new compile unit.
- return Unit = DebugFactory.CreateCompileUnit(LangTag, AbsFileName.getLast(),
- AbsFileName.getDirname(),
- Producer, isMain, isOptimized,
- Flags, RuntimeVers);
+ return DebugFactory.CreateCompileUnit(LangTag, AbsFileName.getLast(),
+ AbsFileName.getDirname(),
+ Producer, isMain, isOptimized,
+ Flags, RuntimeVers);
}
+
/// CreateType - Get the Basic type from the cache or create a new
/// one if necessary.
llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT,
@@ -761,7 +781,7 @@ llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty,
case Type::QualifiedName:
// Unsupported types
return llvm::DIType();
- case Type::ObjCQualifiedId: // Encode id<p> in debug info just like id.
+ case Type::ObjCObjectPointer: // Encode id<p> in debug info just like id.
return Slot = getOrCreateType(M->getContext().getObjCIdType(), Unit);
case Type::ObjCQualifiedInterface: // Drop protocols from interface.
diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h
index de655800fa08..8f3368e4ebfc 100644
--- a/lib/CodeGen/CGDebugInfo.h
+++ b/lib/CodeGen/CGDebugInfo.h
@@ -111,7 +111,9 @@ private:
void EmitDeclare(const VarDecl *decl, unsigned Tag, llvm::Value *AI,
CGBuilderTy &Builder);
-
+ /// createCompileUnit - Create a new unit for the given file.
+ llvm::DICompileUnit createCompileUnit(const char *FileName, bool isMain);
+
/// getOrCreateCompileUnit - Get the compile unit from the cache or create a
/// new one if necessary.
llvm::DICompileUnit getOrCreateCompileUnit(SourceLocation Loc);
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index 29eaaad892d7..4e603c34b404 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -60,7 +60,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
/// EmitBlockVarDecl - This method handles emission of any variable declaration
/// inside a function, including static vars etc.
void CodeGenFunction::EmitBlockVarDecl(const VarDecl &D) {
- if (D.hasAttr<AsmLabelAttr>())
+ if (D.hasAttr<AsmLabelAttr>(getContext()))
CGM.ErrorUnsupported(&D, "__asm__");
switch (D.getStorageClass()) {
@@ -171,7 +171,7 @@ void CodeGenFunction::EmitStaticBlockVarDecl(const VarDecl &D) {
}
// FIXME: Merge attribute handling.
- if (const AnnotateAttr *AA = D.getAttr<AnnotateAttr>()) {
+ if (const AnnotateAttr *AA = D.getAttr<AnnotateAttr>(getContext())) {
SourceManager &SM = CGM.getContext().getSourceManager();
llvm::Constant *Ann =
CGM.EmitAnnotateAttr(GV, AA,
@@ -179,10 +179,10 @@ void CodeGenFunction::EmitStaticBlockVarDecl(const VarDecl &D) {
CGM.AddAnnotation(Ann);
}
- if (const SectionAttr *SA = D.getAttr<SectionAttr>())
+ if (const SectionAttr *SA = D.getAttr<SectionAttr>(getContext()))
GV->setSection(SA->getName());
- if (D.hasAttr<UsedAttr>())
+ if (D.hasAttr<UsedAttr>(getContext()))
CGM.AddUsedGlobal(GV);
// We may have to cast the constant because of the initializer
@@ -244,7 +244,7 @@ const llvm::Type *CodeGenFunction::BuildByRefType(QualType Ty,
/// These turn into simple stack objects, or GlobalValues depending on target.
void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
QualType Ty = D.getType();
- bool isByRef = D.hasAttr<BlocksAttr>();
+ bool isByRef = D.hasAttr<BlocksAttr>(getContext());
bool needsDispose = false;
unsigned Align = 0;
@@ -414,7 +414,7 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
}
// Handle the cleanup attribute
- if (const CleanupAttr *CA = D.getAttr<CleanupAttr>()) {
+ if (const CleanupAttr *CA = D.getAttr<CleanupAttr>(getContext())) {
const FunctionDecl *FD = CA->getFunctionDecl();
llvm::Constant* F = CGM.GetAddrOfFunction(GlobalDecl(FD));
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index eb0db611159b..51c5b3d7dde1 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -668,7 +668,8 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
if (VD && (VD->isBlockVarDecl() || isa<ParmVarDecl>(VD) ||
isa<ImplicitParamDecl>(VD))) {
LValue LV;
- bool NonGCable = VD->hasLocalStorage() && !VD->hasAttr<BlocksAttr>();
+ bool NonGCable = VD->hasLocalStorage() &&
+ !VD->hasAttr<BlocksAttr>(getContext());
if (VD->hasExternalStorage()) {
llvm::Value *V = CGM.GetAddrOfGlobalVar(VD);
if (VD->getType()->isReferenceType())
@@ -684,7 +685,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
// local static?
if (!NonGCable)
attr = getContext().getObjCGCAttrKind(E->getType());
- if (VD->hasAttr<BlocksAttr>()) {
+ if (VD->hasAttr<BlocksAttr>(getContext())) {
bool needsCopyDispose = BlockRequiresCopying(VD->getType());
const llvm::Type *PtrStructTy = V->getType();
const llvm::Type *Ty = PtrStructTy;
diff --git a/lib/CodeGen/CGExprComplex.cpp b/lib/CodeGen/CGExprComplex.cpp
index e1332ff29080..3555c8c9b691 100644
--- a/lib/CodeGen/CGExprComplex.cpp
+++ b/lib/CodeGen/CGExprComplex.cpp
@@ -365,23 +365,28 @@ ComplexPairTy ComplexExprEmitter::EmitCast(Expr *Op, QualType DestTy) {
ComplexPairTy ComplexExprEmitter::VisitPrePostIncDec(const UnaryOperator *E,
bool isInc, bool isPre) {
LValue LV = CGF.EmitLValue(E->getSubExpr());
- ComplexPairTy InVal = EmitLoadOfComplex(LV.getAddress(), LV.isVolatileQualified());
+ ComplexPairTy InVal = EmitLoadOfComplex(LV.getAddress(),
+ LV.isVolatileQualified());
llvm::Value *NextVal;
if (isa<llvm::IntegerType>(InVal.first->getType())) {
uint64_t AmountVal = isInc ? 1 : -1;
NextVal = llvm::ConstantInt::get(InVal.first->getType(), AmountVal, true);
+
+ // Add the inc/dec to the real part.
+ NextVal = Builder.CreateAdd(InVal.first, NextVal, isInc ? "inc" : "dec");
+
} else {
QualType ElemTy = E->getType()->getAsComplexType()->getElementType();
llvm::APFloat FVal(CGF.getContext().getFloatTypeSemantics(ElemTy), 1);
if (!isInc)
FVal.changeSign();
NextVal = llvm::ConstantFP::get(FVal);
+
+ // Add the inc/dec to the real part.
+ NextVal = Builder.CreateFAdd(InVal.first, NextVal, isInc ? "inc" : "dec");
}
- // Add the inc/dec to the real part.
- NextVal = Builder.CreateAdd(InVal.first, NextVal, isInc ? "inc" : "dec");
-
ComplexPairTy IncVal(NextVal, InVal.second);
// Store the updated result through the lvalue.
@@ -398,8 +403,15 @@ ComplexPairTy ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *E) {
TestAndClearIgnoreRealAssign();
TestAndClearIgnoreImagAssign();
ComplexPairTy Op = Visit(E->getSubExpr());
- llvm::Value *ResR = Builder.CreateNeg(Op.first, "neg.r");
- llvm::Value *ResI = Builder.CreateNeg(Op.second, "neg.i");
+
+ llvm::Value *ResR, *ResI;
+ if (Op.first->getType()->isFloatingPoint()) {
+ ResR = Builder.CreateFNeg(Op.first, "neg.r");
+ ResI = Builder.CreateFNeg(Op.second, "neg.i");
+ } else {
+ ResR = Builder.CreateNeg(Op.first, "neg.r");
+ ResI = Builder.CreateNeg(Op.second, "neg.i");
+ }
return ComplexPairTy(ResR, ResI);
}
@@ -410,31 +422,62 @@ ComplexPairTy ComplexExprEmitter::VisitUnaryNot(const UnaryOperator *E) {
TestAndClearIgnoreImagAssign();
// ~(a+ib) = a + i*-b
ComplexPairTy Op = Visit(E->getSubExpr());
- llvm::Value *ResI = Builder.CreateNeg(Op.second, "conj.i");
+ llvm::Value *ResI;
+ if (Op.second->getType()->isFloatingPoint())
+ ResI = Builder.CreateFNeg(Op.second, "conj.i");
+ else
+ ResI = Builder.CreateNeg(Op.second, "conj.i");
+
return ComplexPairTy(Op.first, ResI);
}
ComplexPairTy ComplexExprEmitter::EmitBinAdd(const BinOpInfo &Op) {
- llvm::Value *ResR = Builder.CreateAdd(Op.LHS.first, Op.RHS.first, "add.r");
- llvm::Value *ResI = Builder.CreateAdd(Op.LHS.second, Op.RHS.second, "add.i");
+ llvm::Value *ResR, *ResI;
+
+ if (Op.LHS.first->getType()->isFloatingPoint()) {
+ ResR = Builder.CreateFAdd(Op.LHS.first, Op.RHS.first, "add.r");
+ ResI = Builder.CreateFAdd(Op.LHS.second, Op.RHS.second, "add.i");
+ } else {
+ ResR = Builder.CreateAdd(Op.LHS.first, Op.RHS.first, "add.r");
+ ResI = Builder.CreateAdd(Op.LHS.second, Op.RHS.second, "add.i");
+ }
return ComplexPairTy(ResR, ResI);
}
ComplexPairTy ComplexExprEmitter::EmitBinSub(const BinOpInfo &Op) {
- llvm::Value *ResR = Builder.CreateSub(Op.LHS.first, Op.RHS.first, "sub.r");
- llvm::Value *ResI = Builder.CreateSub(Op.LHS.second, Op.RHS.second, "sub.i");
+ llvm::Value *ResR, *ResI;
+ if (Op.LHS.first->getType()->isFloatingPoint()) {
+ ResR = Builder.CreateFSub(Op.LHS.first, Op.RHS.first, "sub.r");
+ ResI = Builder.CreateFSub(Op.LHS.second, Op.RHS.second, "sub.i");
+ } else {
+ ResR = Builder.CreateSub(Op.LHS.first, Op.RHS.first, "sub.r");
+ ResI = Builder.CreateSub(Op.LHS.second, Op.RHS.second, "sub.i");
+ }
return ComplexPairTy(ResR, ResI);
}
ComplexPairTy ComplexExprEmitter::EmitBinMul(const BinOpInfo &Op) {
- llvm::Value *ResRl = Builder.CreateMul(Op.LHS.first, Op.RHS.first, "mul.rl");
- llvm::Value *ResRr = Builder.CreateMul(Op.LHS.second, Op.RHS.second,"mul.rr");
- llvm::Value *ResR = Builder.CreateSub(ResRl, ResRr, "mul.r");
+ using llvm::Value;
+ Value *ResR, *ResI;
- llvm::Value *ResIl = Builder.CreateMul(Op.LHS.second, Op.RHS.first, "mul.il");
- llvm::Value *ResIr = Builder.CreateMul(Op.LHS.first, Op.RHS.second, "mul.ir");
- llvm::Value *ResI = Builder.CreateAdd(ResIl, ResIr, "mul.i");
+ if (Op.LHS.first->getType()->isFloatingPoint()) {
+ Value *ResRl = Builder.CreateFMul(Op.LHS.first, Op.RHS.first, "mul.rl");
+ Value *ResRr = Builder.CreateFMul(Op.LHS.second, Op.RHS.second,"mul.rr");
+ ResR = Builder.CreateFSub(ResRl, ResRr, "mul.r");
+
+ Value *ResIl = Builder.CreateFMul(Op.LHS.second, Op.RHS.first, "mul.il");
+ Value *ResIr = Builder.CreateFMul(Op.LHS.first, Op.RHS.second, "mul.ir");
+ ResI = Builder.CreateFAdd(ResIl, ResIr, "mul.i");
+ } else {
+ Value *ResRl = Builder.CreateMul(Op.LHS.first, Op.RHS.first, "mul.rl");
+ Value *ResRr = Builder.CreateMul(Op.LHS.second, Op.RHS.second,"mul.rr");
+ ResR = Builder.CreateSub(ResRl, ResRr, "mul.r");
+
+ Value *ResIl = Builder.CreateMul(Op.LHS.second, Op.RHS.first, "mul.il");
+ Value *ResIr = Builder.CreateMul(Op.LHS.first, Op.RHS.second, "mul.ir");
+ ResI = Builder.CreateAdd(ResIl, ResIr, "mul.i");
+ }
return ComplexPairTy(ResR, ResI);
}
@@ -442,24 +485,38 @@ ComplexPairTy ComplexExprEmitter::EmitBinDiv(const BinOpInfo &Op) {
llvm::Value *LHSr = Op.LHS.first, *LHSi = Op.LHS.second;
llvm::Value *RHSr = Op.RHS.first, *RHSi = Op.RHS.second;
- // (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd))
- llvm::Value *Tmp1 = Builder.CreateMul(LHSr, RHSr, "tmp"); // a*c
- llvm::Value *Tmp2 = Builder.CreateMul(LHSi, RHSi, "tmp"); // b*d
- llvm::Value *Tmp3 = Builder.CreateAdd(Tmp1, Tmp2, "tmp"); // ac+bd
-
- llvm::Value *Tmp4 = Builder.CreateMul(RHSr, RHSr, "tmp"); // c*c
- llvm::Value *Tmp5 = Builder.CreateMul(RHSi, RHSi, "tmp"); // d*d
- llvm::Value *Tmp6 = Builder.CreateAdd(Tmp4, Tmp5, "tmp"); // cc+dd
-
- llvm::Value *Tmp7 = Builder.CreateMul(LHSi, RHSr, "tmp"); // b*c
- llvm::Value *Tmp8 = Builder.CreateMul(LHSr, RHSi, "tmp"); // a*d
- llvm::Value *Tmp9 = Builder.CreateSub(Tmp7, Tmp8, "tmp"); // bc-ad
llvm::Value *DSTr, *DSTi;
- if (Tmp3->getType()->isFloatingPoint()) {
+ if (Op.LHS.first->getType()->isFloatingPoint()) {
+ // (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd))
+ llvm::Value *Tmp1 = Builder.CreateFMul(LHSr, RHSr, "tmp"); // a*c
+ llvm::Value *Tmp2 = Builder.CreateFMul(LHSi, RHSi, "tmp"); // b*d
+ llvm::Value *Tmp3 = Builder.CreateFAdd(Tmp1, Tmp2, "tmp"); // ac+bd
+
+ llvm::Value *Tmp4 = Builder.CreateFMul(RHSr, RHSr, "tmp"); // c*c
+ llvm::Value *Tmp5 = Builder.CreateFMul(RHSi, RHSi, "tmp"); // d*d
+ llvm::Value *Tmp6 = Builder.CreateFAdd(Tmp4, Tmp5, "tmp"); // cc+dd
+
+ llvm::Value *Tmp7 = Builder.CreateFMul(LHSi, RHSr, "tmp"); // b*c
+ llvm::Value *Tmp8 = Builder.CreateFMul(LHSr, RHSi, "tmp"); // a*d
+ llvm::Value *Tmp9 = Builder.CreateFSub(Tmp7, Tmp8, "tmp"); // bc-ad
+
DSTr = Builder.CreateFDiv(Tmp3, Tmp6, "tmp");
DSTi = Builder.CreateFDiv(Tmp9, Tmp6, "tmp");
} else {
+ // (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd))
+ llvm::Value *Tmp1 = Builder.CreateMul(LHSr, RHSr, "tmp"); // a*c
+ llvm::Value *Tmp2 = Builder.CreateMul(LHSi, RHSi, "tmp"); // b*d
+ llvm::Value *Tmp3 = Builder.CreateAdd(Tmp1, Tmp2, "tmp"); // ac+bd
+
+ llvm::Value *Tmp4 = Builder.CreateMul(RHSr, RHSr, "tmp"); // c*c
+ llvm::Value *Tmp5 = Builder.CreateMul(RHSi, RHSi, "tmp"); // d*d
+ llvm::Value *Tmp6 = Builder.CreateAdd(Tmp4, Tmp5, "tmp"); // cc+dd
+
+ llvm::Value *Tmp7 = Builder.CreateMul(LHSi, RHSr, "tmp"); // b*c
+ llvm::Value *Tmp8 = Builder.CreateMul(LHSr, RHSi, "tmp"); // a*d
+ llvm::Value *Tmp9 = Builder.CreateSub(Tmp7, Tmp8, "tmp"); // bc-ad
+
if (Op.Ty->getAsComplexType()->getElementType()->isUnsignedIntegerType()) {
DSTr = Builder.CreateUDiv(Tmp3, Tmp6, "tmp");
DSTi = Builder.CreateUDiv(Tmp9, Tmp6, "tmp");
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp
index 0e21a00f30fe..0b109f9bee42 100644
--- a/lib/CodeGen/CGExprConstant.cpp
+++ b/lib/CodeGen/CGExprConstant.cpp
@@ -198,16 +198,13 @@ public:
// Copy initializer elements. Skip padding fields.
unsigned EltNo = 0; // Element no in ILE
- int FieldNo = 0; // Field no in RecordDecl
bool RewriteType = false;
for (RecordDecl::field_iterator Field = RD->field_begin(CGM.getContext()),
FieldEnd = RD->field_end(CGM.getContext());
EltNo < ILE->getNumInits() && Field != FieldEnd; ++Field) {
- FieldNo++;
- if (!Field->getIdentifier())
- continue;
-
if (Field->isBitField()) {
+ if (!Field->getIdentifier())
+ continue;
InsertBitfieldIntoStruct(Elts, *Field, ILE->getInit(EltNo));
} else {
unsigned FieldNo = CGM.getTypes().getLLVMFieldNo(*Field);
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index ed18d3247ac6..2af0639f5ce3 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -294,6 +294,8 @@ public:
if (CGF.getContext().getLangOptions().OverflowChecking
&& Ops.Ty->isSignedIntegerType())
return EmitOverflowCheckedBinOp(Ops);
+ if (Ops.LHS->getType()->isFPOrFPVector())
+ return Builder.CreateFMul(Ops.LHS, Ops.RHS, "mul");
return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul");
}
/// Create a binary op that checks for overflow.
@@ -699,11 +701,12 @@ Value *ScalarExprEmitter::VisitPrePostIncDec(const UnaryOperator *E,
// An interesting aspect of this is that increment is always true.
// Decrement does not have this property.
NextVal = llvm::ConstantInt::getTrue();
+ } else if (isa<llvm::IntegerType>(InVal->getType())) {
+ NextVal = llvm::ConstantInt::get(InVal->getType(), AmountVal);
+ NextVal = Builder.CreateAdd(InVal, NextVal, isInc ? "inc" : "dec");
} else {
// Add the inc/dec to the real part.
- if (isa<llvm::IntegerType>(InVal->getType()))
- NextVal = llvm::ConstantInt::get(InVal->getType(), AmountVal);
- else if (InVal->getType() == llvm::Type::FloatTy)
+ if (InVal->getType() == llvm::Type::FloatTy)
NextVal =
llvm::ConstantFP::get(llvm::APFloat(static_cast<float>(AmountVal)));
else if (InVal->getType() == llvm::Type::DoubleTy)
@@ -716,7 +719,7 @@ Value *ScalarExprEmitter::VisitPrePostIncDec(const UnaryOperator *E,
&ignored);
NextVal = llvm::ConstantFP::get(F);
}
- NextVal = Builder.CreateAdd(InVal, NextVal, isInc ? "inc" : "dec");
+ NextVal = Builder.CreateFAdd(InVal, NextVal, isInc ? "inc" : "dec");
}
// Store the updated result through the lvalue.
@@ -735,6 +738,8 @@ Value *ScalarExprEmitter::VisitPrePostIncDec(const UnaryOperator *E,
Value *ScalarExprEmitter::VisitUnaryMinus(const UnaryOperator *E) {
TestAndClearIgnoreResultAssign();
Value *Op = Visit(E->getSubExpr());
+ if (Op->getType()->isFPOrFPVector())
+ return Builder.CreateFNeg(Op, "neg");
return Builder.CreateNeg(Op, "neg");
}
@@ -982,9 +987,13 @@ Value *ScalarExprEmitter::EmitOverflowCheckedBinOp(const BinOpInfo &Ops) {
Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &Ops) {
if (!Ops.Ty->isPointerType()) {
- if (CGF.getContext().getLangOptions().OverflowChecking
- && Ops.Ty->isSignedIntegerType())
+ if (CGF.getContext().getLangOptions().OverflowChecking &&
+ Ops.Ty->isSignedIntegerType())
return EmitOverflowCheckedBinOp(Ops);
+
+ if (Ops.LHS->getType()->isFPOrFPVector())
+ return Builder.CreateFAdd(Ops.LHS, Ops.RHS, "add");
+
return Builder.CreateAdd(Ops.LHS, Ops.RHS, "add");
}
@@ -1050,6 +1059,9 @@ Value *ScalarExprEmitter::EmitSub(const BinOpInfo &Ops) {
if (CGF.getContext().getLangOptions().OverflowChecking
&& Ops.Ty->isSignedIntegerType())
return EmitOverflowCheckedBinOp(Ops);
+
+ if (Ops.LHS->getType()->isFPOrFPVector())
+ return Builder.CreateFSub(Ops.LHS, Ops.RHS, "sub");
return Builder.CreateSub(Ops.LHS, Ops.RHS, "sub");
}
diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp
index 51f9a7657928..e7cf8e6e653a 100644
--- a/lib/CodeGen/CGObjC.cpp
+++ b/lib/CodeGen/CGObjC.cpp
@@ -126,7 +126,7 @@ void CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD,
/// its pointer, name, and types registered in the class struture.
void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) {
// Check if we should generate debug info for this method.
- if (CGM.getDebugInfo() && !OMD->hasAttr<NodebugAttr>())
+ if (CGM.getDebugInfo() && !OMD->hasAttr<NodebugAttr>(getContext()))
DebugInfo = CGM.getDebugInfo();
StartObjCMethod(OMD, OMD->getClassInterface());
EmitStmt(OMD->getBody(getContext()));
diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp
index a70f718a76f3..912479f0b0ed 100644
--- a/lib/CodeGen/CGObjCGNU.cpp
+++ b/lib/CodeGen/CGObjCGNU.cpp
@@ -104,6 +104,7 @@ private:
std::vector<llvm::Constant*> &V, const std::string &Name="");
llvm::GlobalVariable *ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
const ObjCIvarDecl *Ivar);
+ void EmitClassRef(const std::string &className);
public:
CGObjCGNU(CodeGen::CodeGenModule &cgm);
virtual llvm::Constant *GenerateConstantString(const ObjCStringLiteral *);
@@ -168,15 +169,31 @@ public:
} // end anonymous namespace
+/// Emits a reference to a dummy variable which is emitted with each class.
+/// This ensures that a linker error will be generated when trying to link
+/// together modules where a referenced class is not defined.
+void CGObjCGNU::EmitClassRef(const std::string &className){
+ std::string symbolRef = "__objc_class_ref_" + className;
+ // Don't emit two copies of the same symbol
+ if (TheModule.getGlobalVariable(symbolRef)) return;
+ std::string symbolName = "__objc_class_name_" + className;
+ llvm::GlobalVariable *ClassSymbol = TheModule.getGlobalVariable(symbolName);
+ if (!ClassSymbol) {
+ ClassSymbol = new llvm::GlobalVariable(LongTy, false,
+ llvm::GlobalValue::ExternalLinkage, 0, symbolName, &TheModule);
+ }
+ new llvm::GlobalVariable(ClassSymbol->getType(), true,
+ llvm::GlobalValue::CommonLinkage, ClassSymbol, symbolRef, &TheModule);
+}
static std::string SymbolNameForClass(const std::string &ClassName) {
- return "___objc_class_name_" + ClassName;
+ return "_OBJC_CLASS_" + ClassName;
}
static std::string SymbolNameForMethod(const std::string &ClassName, const
std::string &CategoryName, const std::string &MethodName, bool isClassMethod)
{
- return "._objc_method_" + ClassName +"("+CategoryName+")"+
+ return "_OBJC_METHOD_" + ClassName + "("+CategoryName+")"+
(isClassMethod ? "+" : "-") + MethodName;
}
@@ -217,6 +234,7 @@ CGObjCGNU::CGObjCGNU(CodeGen::CodeGenModule &cgm)
llvm::Value *CGObjCGNU::GetClass(CGBuilderTy &Builder,
const ObjCInterfaceDecl *OID) {
llvm::Value *ClassName = CGM.GetAddrOfConstantCString(OID->getNameAsString());
+ EmitClassRef(OID->getNameAsString());
ClassName = Builder.CreateStructGEP(ClassName, 0);
std::vector<const llvm::Type*> Params(1, PtrToInt8Ty);
@@ -831,14 +849,21 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
const ObjCInterfaceDecl * SuperClassDecl =
OID->getClassInterface()->getSuperClass();
std::string SuperClassName;
- if (SuperClassDecl)
+ if (SuperClassDecl) {
SuperClassName = SuperClassDecl->getNameAsString();
+ EmitClassRef(SuperClassName);
+ }
// Get the class name
ObjCInterfaceDecl *ClassDecl =
const_cast<ObjCInterfaceDecl *>(OID->getClassInterface());
std::string ClassName = ClassDecl->getNameAsString();
-
+ // Emit the symbol that is used to generate linker errors if this class is
+ // referenced in other modules but not declared.
+ new llvm::GlobalVariable(LongTy, false, llvm::GlobalValue::ExternalLinkage,
+ llvm::ConstantInt::get(LongTy, 0), "__objc_class_name_" + ClassName,
+ &TheModule);
+
// Get the size of instances.
int instanceSize = Context.getASTObjCImplementationLayout(OID).getSize() / 8;
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index bd5b05acf94a..6ffca8134afa 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -1356,11 +1356,12 @@ static llvm::Constant *getConstantGEP(llvm::Constant *C,
/// hasObjCExceptionAttribute - Return true if this class or any super
/// class has the __objc_exception__ attribute.
-static bool hasObjCExceptionAttribute(const ObjCInterfaceDecl *OID) {
- if (OID->hasAttr<ObjCExceptionAttr>())
+static bool hasObjCExceptionAttribute(ASTContext &Context,
+ const ObjCInterfaceDecl *OID) {
+ if (OID->hasAttr<ObjCExceptionAttr>(Context))
return true;
if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
- return hasObjCExceptionAttribute(Super);
+ return hasObjCExceptionAttribute(Context, Super);
return false;
}
@@ -4402,7 +4403,7 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
if (classIsHidden)
flags |= OBJC2_CLS_HIDDEN;
- if (hasObjCExceptionAttribute(ID->getClassInterface()))
+ if (hasObjCExceptionAttribute(CGM.getContext(), ID->getClassInterface()))
flags |= CLS_EXCEPTION;
if (!ID->getClassInterface()->getSuperClass()) {
@@ -5686,7 +5687,7 @@ CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
// If this type (or a super class) has the __objc_exception__
// attribute, emit an external reference.
- if (hasObjCExceptionAttribute(ID))
+ if (hasObjCExceptionAttribute(CGM.getContext(), ID))
return Entry =
new llvm::GlobalVariable(ObjCTypes.EHTypeTy, false,
llvm::GlobalValue::ExternalLinkage,
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index 672f6da502b1..f10a08f9db86 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -199,7 +199,7 @@ void CodeGenFunction::StartFunction(const Decl *D, QualType RetTy,
void CodeGenFunction::GenerateCode(const FunctionDecl *FD,
llvm::Function *Fn) {
// Check if we should generate debug info for this function.
- if (CGM.getDebugInfo() && !FD->hasAttr<NodebugAttr>())
+ if (CGM.getDebugInfo() && !FD->hasAttr<NodebugAttr>(getContext()))
DebugInfo = CGM.getDebugInfo();
FunctionArgList Args;
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 82156e9ffa5c..f926c05a9983 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -102,7 +102,7 @@ CodeGenModule::getDeclVisibilityMode(const Decl *D) const {
if (VD->getStorageClass() == VarDecl::PrivateExtern)
return LangOptions::Hidden;
- if (const VisibilityAttr *attr = D->getAttr<VisibilityAttr>()) {
+ if (const VisibilityAttr *attr = D->getAttr<VisibilityAttr>(getContext())) {
switch (attr->getVisibility()) {
default: assert(0 && "Unknown visibility!");
case VisibilityAttr::DefaultVisibility:
@@ -241,10 +241,11 @@ void CodeGenModule::EmitAnnotations() {
}
static CodeGenModule::GVALinkage
-GetLinkageForFunction(const FunctionDecl *FD, const LangOptions &Features) {
+GetLinkageForFunction(ASTContext &Context, const FunctionDecl *FD,
+ const LangOptions &Features) {
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
// C++ member functions defined inside the class are always inline.
- if (MD->isInline() || !MD->isOutOfLineDefinition())
+ if (MD->isInline() || !MD->isOutOfLine())
return CodeGenModule::GVA_CXXInline;
return CodeGenModule::GVA_StrongExternal;
@@ -265,11 +266,11 @@ GetLinkageForFunction(const FunctionDecl *FD, const LangOptions &Features) {
return CodeGenModule::GVA_C99Inline;
// Normal inline is a strong symbol.
return CodeGenModule::GVA_StrongExternal;
- } else if (FD->hasActiveGNUInlineAttribute()) {
+ } else if (FD->hasActiveGNUInlineAttribute(Context)) {
// GCC in C99 mode seems to use a different decision-making
// process for extern inline, which factors in previous
// declarations.
- if (FD->isExternGNUInline())
+ if (FD->isExternGNUInline(Context))
return CodeGenModule::GVA_C99Inline;
// Normal inline is a strong symbol.
return CodeGenModule::GVA_StrongExternal;
@@ -293,13 +294,13 @@ GetLinkageForFunction(const FunctionDecl *FD, const LangOptions &Features) {
/// variables (these details are set in EmitGlobalVarDefinition for variables).
void CodeGenModule::SetFunctionDefinitionAttributes(const FunctionDecl *D,
llvm::GlobalValue *GV) {
- GVALinkage Linkage = GetLinkageForFunction(D, Features);
+ GVALinkage Linkage = GetLinkageForFunction(getContext(), D, Features);
if (Linkage == GVA_Internal) {
GV->setLinkage(llvm::Function::InternalLinkage);
- } else if (D->hasAttr<DLLExportAttr>()) {
+ } else if (D->hasAttr<DLLExportAttr>(getContext())) {
GV->setLinkage(llvm::Function::DLLExportLinkage);
- } else if (D->hasAttr<WeakAttr>()) {
+ } else if (D->hasAttr<WeakAttr>(getContext())) {
GV->setLinkage(llvm::Function::WeakAnyLinkage);
} else if (Linkage == GVA_C99Inline) {
// In C99 mode, 'inline' functions are guaranteed to have a strong
@@ -332,10 +333,10 @@ void CodeGenModule::SetLLVMFunctionAttributes(const Decl *D,
AttributeList.size()));
// Set the appropriate calling convention for the Function.
- if (D->hasAttr<FastCallAttr>())
+ if (D->hasAttr<FastCallAttr>(getContext()))
F->setCallingConv(llvm::CallingConv::X86_FastCall);
- if (D->hasAttr<StdCallAttr>())
+ if (D->hasAttr<StdCallAttr>(getContext()))
F->setCallingConv(llvm::CallingConv::X86_StdCall);
}
@@ -344,10 +345,10 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
if (!Features.Exceptions && !Features.ObjCNonFragileABI)
F->addFnAttr(llvm::Attribute::NoUnwind);
- if (D->hasAttr<AlwaysInlineAttr>())
+ if (D->hasAttr<AlwaysInlineAttr>(getContext()))
F->addFnAttr(llvm::Attribute::AlwaysInline);
- if (D->hasAttr<NoinlineAttr>())
+ if (D->hasAttr<NoinlineAttr>(getContext()))
F->addFnAttr(llvm::Attribute::NoInline);
}
@@ -355,10 +356,10 @@ void CodeGenModule::SetCommonAttributes(const Decl *D,
llvm::GlobalValue *GV) {
setGlobalVisibility(GV, D);
- if (D->hasAttr<UsedAttr>())
+ if (D->hasAttr<UsedAttr>(getContext()))
AddUsedGlobal(GV);
- if (const SectionAttr *SA = D->getAttr<SectionAttr>())
+ if (const SectionAttr *SA = D->getAttr<SectionAttr>(getContext()))
GV->setSection(SA->getName());
}
@@ -382,9 +383,10 @@ void CodeGenModule::SetFunctionAttributes(const FunctionDecl *FD,
// Only a few attributes are set on declarations; these may later be
// overridden by a definition.
- if (FD->hasAttr<DLLImportAttr>()) {
+ if (FD->hasAttr<DLLImportAttr>(getContext())) {
F->setLinkage(llvm::Function::DLLImportLinkage);
- } else if (FD->hasAttr<WeakAttr>() || FD->hasAttr<WeakImportAttr>()) {
+ } else if (FD->hasAttr<WeakAttr>(getContext()) ||
+ FD->hasAttr<WeakImportAttr>(getContext())) {
// "extern_weak" is overloaded in LLVM; we probably should have
// separate linkage types for this.
F->setLinkage(llvm::Function::ExternalWeakLinkage);
@@ -392,7 +394,7 @@ void CodeGenModule::SetFunctionAttributes(const FunctionDecl *FD,
F->setLinkage(llvm::Function::ExternalLinkage);
}
- if (const SectionAttr *SA = FD->getAttr<SectionAttr>())
+ if (const SectionAttr *SA = FD->getAttr<SectionAttr>(getContext()))
F->setSection(SA->getName());
}
@@ -499,15 +501,16 @@ llvm::Constant *CodeGenModule::EmitAnnotateAttr(llvm::GlobalValue *GV,
bool CodeGenModule::MayDeferGeneration(const ValueDecl *Global) {
// Never defer when EmitAllDecls is specified or the decl has
// attribute used.
- if (Features.EmitAllDecls || Global->hasAttr<UsedAttr>())
+ if (Features.EmitAllDecls || Global->hasAttr<UsedAttr>(getContext()))
return false;
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Global)) {
// Constructors and destructors should never be deferred.
- if (FD->hasAttr<ConstructorAttr>() || FD->hasAttr<DestructorAttr>())
+ if (FD->hasAttr<ConstructorAttr>(getContext()) ||
+ FD->hasAttr<DestructorAttr>(getContext()))
return false;
- GVALinkage Linkage = GetLinkageForFunction(FD, Features);
+ GVALinkage Linkage = GetLinkageForFunction(getContext(), FD, Features);
// static, static inline, always_inline, and extern inline functions can
// always be deferred. Normal inline functions can be deferred in C99/C++.
@@ -528,7 +531,7 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
// If this is an alias definition (which otherwise looks like a declaration)
// emit it now.
- if (Global->hasAttr<AliasAttr>())
+ if (Global->hasAttr<AliasAttr>(getContext()))
return EmitAliasDefinition(Global);
// Ignore declarations, they will be emitted on their first use.
@@ -717,7 +720,8 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMGlobal(const char *MangledName,
if (D->getStorageClass() == VarDecl::PrivateExtern)
GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
- if (D->hasAttr<WeakAttr>() || D->hasAttr<WeakImportAttr>())
+ if (D->hasAttr<WeakAttr>(getContext()) ||
+ D->hasAttr<WeakImportAttr>(getContext()))
GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
GV->setThreadLocal(D->isThreadSpecified());
@@ -837,7 +841,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
cast<llvm::GlobalValue>(Entry)->eraseFromParent();
}
- if (const AnnotateAttr *AA = D->getAttr<AnnotateAttr>()) {
+ if (const AnnotateAttr *AA = D->getAttr<AnnotateAttr>(getContext())) {
SourceManager &SM = Context.getSourceManager();
AddAnnotation(EmitAnnotateAttr(GV, AA,
SM.getInstantiationLineNumber(D->getLocation())));
@@ -850,11 +854,11 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
// Set the llvm linkage type as appropriate.
if (D->getStorageClass() == VarDecl::Static)
GV->setLinkage(llvm::Function::InternalLinkage);
- else if (D->hasAttr<DLLImportAttr>())
+ else if (D->hasAttr<DLLImportAttr>(getContext()))
GV->setLinkage(llvm::Function::DLLImportLinkage);
- else if (D->hasAttr<DLLExportAttr>())
+ else if (D->hasAttr<DLLExportAttr>(getContext()))
GV->setLinkage(llvm::Function::DLLExportLinkage);
- else if (D->hasAttr<WeakAttr>())
+ else if (D->hasAttr<WeakAttr>(getContext()))
GV->setLinkage(llvm::GlobalVariable::WeakAnyLinkage);
else if (!CompileOpts.NoCommon &&
(!D->hasExternalStorage() && !D->getInit()))
@@ -1017,14 +1021,14 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD) {
SetFunctionDefinitionAttributes(D, Fn);
SetLLVMFunctionAttributesForDefinition(D, Fn);
- if (const ConstructorAttr *CA = D->getAttr<ConstructorAttr>())
+ if (const ConstructorAttr *CA = D->getAttr<ConstructorAttr>(getContext()))
AddGlobalCtor(Fn, CA->getPriority());
- if (const DestructorAttr *DA = D->getAttr<DestructorAttr>())
+ if (const DestructorAttr *DA = D->getAttr<DestructorAttr>(getContext()))
AddGlobalDtor(Fn, DA->getPriority());
}
void CodeGenModule::EmitAliasDefinition(const ValueDecl *D) {
- const AliasAttr *AA = D->getAttr<AliasAttr>();
+ const AliasAttr *AA = D->getAttr<AliasAttr>(getContext());
assert(AA && "Not an alias?");
const llvm::Type *DeclTy = getTypes().ConvertTypeForMem(D->getType());
@@ -1080,7 +1084,7 @@ void CodeGenModule::EmitAliasDefinition(const ValueDecl *D) {
// Set attributes which are particular to an alias; this is a
// specialization of the attributes which may be set on a global
// variable/function.
- if (D->hasAttr<DLLExportAttr>()) {
+ if (D->hasAttr<DLLExportAttr>(getContext())) {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
// The dllexport attribute is ignored for undefined symbols.
if (FD->getBody(getContext()))
@@ -1088,7 +1092,8 @@ void CodeGenModule::EmitAliasDefinition(const ValueDecl *D) {
} else {
GA->setLinkage(llvm::Function::DLLExportLinkage);
}
- } else if (D->hasAttr<WeakAttr>() || D->hasAttr<WeakImportAttr>()) {
+ } else if (D->hasAttr<WeakAttr>(getContext()) ||
+ D->hasAttr<WeakImportAttr>(getContext())) {
GA->setLinkage(llvm::Function::WeakAnyLinkage);
}
@@ -1476,6 +1481,9 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
case Decl::Namespace:
EmitNamespace(cast<NamespaceDecl>(D));
break;
+ // No code generation needed.
+ case Decl::Using:
+ break;
case Decl::CXXConstructor:
EmitCXXConstructors(cast<CXXConstructorDecl>(D));
break;
diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp
index af791f63186c..f31c610bf97d 100644
--- a/lib/CodeGen/CodeGenTypes.cpp
+++ b/lib/CodeGen/CodeGenTypes.cpp
@@ -353,7 +353,7 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
return T;
}
- case Type::ObjCQualifiedId:
+ case Type::ObjCObjectPointer:
// Protocols don't influence the LLVM type.
return ConvertTypeRecursive(Context.getObjCIdType());
diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp
index 14392ab6e79f..24e441a29635 100644
--- a/lib/CodeGen/Mangle.cpp
+++ b/lib/CodeGen/Mangle.cpp
@@ -87,7 +87,7 @@ static bool isInCLinkageSpecification(const Decl *D) {
bool CXXNameMangler::mangleFunctionDecl(const FunctionDecl *FD) {
// Clang's "overloadable" attribute extension to C/C++ implies
// name mangling (always).
- if (!FD->hasAttr<OverloadableAttr>()) {
+ if (!FD->hasAttr<OverloadableAttr>(Context)) {
// C functions are not mangled, and "main" is never mangled.
if (!Context.getLangOptions().CPlusPlus || FD->isMain())
return false;
@@ -111,7 +111,7 @@ bool CXXNameMangler::mangleFunctionDecl(const FunctionDecl *FD) {
bool CXXNameMangler::mangle(const NamedDecl *D) {
// Any decl can be declared with __asm("foo") on it, and this takes
// precedence over all other naming in the .o file.
- if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) {
+ if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>(Context)) {
// If we have an asm name, then we use it as the mangling.
Out << '\01'; // LLVM IR Marker for __asm("foo")
Out << ALA->getLabel();
diff --git a/lib/Driver/CMakeLists.txt b/lib/Driver/CMakeLists.txt
index 7147d8f0be60..42cbff9be6c3 100644
--- a/lib/Driver/CMakeLists.txt
+++ b/lib/Driver/CMakeLists.txt
@@ -17,3 +17,5 @@ add_clang_library(clangDriver
Tools.cpp
Types.cpp
)
+
+add_dependencies(clangSema ClangDiagnosticDriver)
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index d8c6a0aeead6..8c2676b8cd7d 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -356,10 +356,15 @@ void Driver::PrintVersion(const Compilation &C) const {
// don't know what the client would like to do.
llvm::errs() << "clang version " CLANG_VERSION_STRING " ("
- << vers << " " << revision << ")" << "\n";
+ << vers << " " << revision << ")" << '\n';
const ToolChain &TC = C.getDefaultToolChain();
llvm::errs() << "Target: " << TC.getTripleString() << '\n';
+
+ // Print the threading model.
+ //
+ // FIXME: Implement correctly.
+ llvm::errs() << "Thread model: " << "posix" << '\n';
}
bool Driver::HandleImmediateArgs(const Compilation &C) {
@@ -429,6 +434,47 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
return false;
}
+ if (C.getArgs().hasArg(options::OPT_print_multi_lib)) {
+ // FIXME: We need tool chain support for this.
+ llvm::outs() << ".;\n";
+
+ switch (C.getDefaultToolChain().getTriple().getArch()) {
+ default:
+ break;
+
+ case llvm::Triple::x86_64:
+ llvm::outs() << "x86_64;@m64" << "\n";
+ break;
+
+ case llvm::Triple::ppc64:
+ llvm::outs() << "ppc64;@m64" << "\n";
+ break;
+ }
+ return false;
+ }
+
+ // FIXME: What is the difference between print-multi-directory and
+ // print-multi-os-directory?
+ if (C.getArgs().hasArg(options::OPT_print_multi_directory) ||
+ C.getArgs().hasArg(options::OPT_print_multi_os_directory)) {
+ switch (C.getDefaultToolChain().getTriple().getArch()) {
+ default:
+ case llvm::Triple::x86:
+ case llvm::Triple::ppc:
+ llvm::outs() << "." << "\n";
+ break;
+
+ case llvm::Triple::x86_64:
+ llvm::outs() << "x86_64" << "\n";
+ break;
+
+ case llvm::Triple::ppc64:
+ llvm::outs() << "ppc64" << "\n";
+ break;
+ }
+ return false;
+ }
+
return true;
}
diff --git a/lib/Driver/HostInfo.cpp b/lib/Driver/HostInfo.cpp
index 2d577f82fd40..831e11b98e42 100644
--- a/lib/Driver/HostInfo.cpp
+++ b/lib/Driver/HostInfo.cpp
@@ -108,16 +108,34 @@ ToolChain *DarwinHostInfo::getToolChain(const ArgList &Args,
const char *ArchName) const {
std::string Arch;
if (!ArchName) {
- Arch = getArchName();
+ // If we aren't looking for a specific arch, infer the default architecture
+ // based on -arch and -m32/-m64 command line options.
+ if (Arg *A = Args.getLastArg(options::OPT_arch)) {
+ // The gcc driver behavior with multiple -arch flags wasn't consistent for
+ // things which rely on a default architecture. We just use the last -arch
+ // to find the default tool chain.
+ Arch = A->getValue(Args);
+
+ // Normalize arch name; we shouldn't be doing this here.
+ //
+ // FIXME: This should be unnecessary once everything moves over to using
+ // the ID based Triple interface.
+ if (Arch == "ppc")
+ Arch = "powerpc";
+ else if (Arch == "ppc64")
+ Arch = "powerpc64";
+ } else {
+ // Otherwise default to the arch of the host.
+ Arch = getArchName();
+ }
ArchName = Arch.c_str();
-
- // If no arch name is specified, infer it from the host and
- // -m32/-m64.
+
+ // Honor -m32 and -m64 when finding the default tool chain.
if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) {
- if (getArchName() == "i386" || getArchName() == "x86_64") {
- ArchName =
- (A->getOption().getId() == options::OPT_m32) ? "i386" : "x86_64";
- } else if (getArchName() == "powerpc" || getArchName() == "powerpc64") {
+ if (Arch == "i386" || Arch == "x86_64") {
+ ArchName = (A->getOption().getId() == options::OPT_m32) ? "i386" :
+ "x86_64";
+ } else if (Arch == "powerpc" || Arch == "powerpc64") {
ArchName = (A->getOption().getId() == options::OPT_m32) ? "powerpc" :
"powerpc64";
}
diff --git a/lib/Frontend/ASTConsumers.cpp b/lib/Frontend/ASTConsumers.cpp
index 11c9251ae987..5844be826cf7 100644
--- a/lib/Frontend/ASTConsumers.cpp
+++ b/lib/Frontend/ASTConsumers.cpp
@@ -243,7 +243,7 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
}
case Decl::CXXMethod: {
const CXXMethodDecl* D = cast<CXXMethodDecl>(DC);
- if (D->isOutOfLineDefinition())
+ if (D->isOutOfLine())
Out << "[c++ method] ";
else if (D->isImplicit())
Out << "(c++ method) ";
@@ -273,7 +273,7 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
}
case Decl::CXXConstructor: {
const CXXConstructorDecl* D = cast<CXXConstructorDecl>(DC);
- if (D->isOutOfLineDefinition())
+ if (D->isOutOfLine())
Out << "[c++ ctor] ";
else if (D->isImplicit())
Out << "(c++ ctor) ";
@@ -302,7 +302,7 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
}
case Decl::CXXDestructor: {
const CXXDestructorDecl* D = cast<CXXDestructorDecl>(DC);
- if (D->isOutOfLineDefinition())
+ if (D->isOutOfLine())
Out << "[c++ dtor] ";
else if (D->isImplicit())
Out << "(c++ dtor) ";
@@ -318,7 +318,7 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
}
case Decl::CXXConversion: {
const CXXConversionDecl* D = cast<CXXConversionDecl>(DC);
- if (D->isOutOfLineDefinition())
+ if (D->isOutOfLine())
Out << "[c++ conversion] ";
else if (D->isImplicit())
Out << "(c++ conversion) ";
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
new file mode 100644
index 000000000000..a7fbcda8fc2b
--- /dev/null
+++ b/lib/Frontend/ASTUnit.cpp
@@ -0,0 +1,159 @@
+//===--- ASTUnit.cpp - ASTUnit utility ------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// ASTUnit Implementation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Frontend/PCHReader.h"
+#include "clang/Frontend/TextDiagnosticBuffer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/Diagnostic.h"
+#include "llvm/Support/Compiler.h"
+
+using namespace clang;
+
+ASTUnit::ASTUnit() { }
+ASTUnit::~ASTUnit() { }
+
+namespace {
+
+/// \brief Gathers information from PCHReader that will be used to initialize
+/// a Preprocessor.
+class VISIBILITY_HIDDEN PCHInfoCollector : public PCHReaderListener {
+ LangOptions &LangOpt;
+ HeaderSearch &HSI;
+ std::string &TargetTriple;
+ std::string &Predefines;
+ unsigned &Counter;
+
+ unsigned NumHeaderInfos;
+
+public:
+ PCHInfoCollector(LangOptions &LangOpt, HeaderSearch &HSI,
+ std::string &TargetTriple, std::string &Predefines,
+ unsigned &Counter)
+ : LangOpt(LangOpt), HSI(HSI), TargetTriple(TargetTriple),
+ Predefines(Predefines), Counter(Counter), NumHeaderInfos(0) {}
+
+ virtual bool ReadLanguageOptions(const LangOptions &LangOpts) {
+ LangOpt = LangOpts;
+ return false;
+ }
+
+ virtual bool ReadTargetTriple(const std::string &Triple) {
+ TargetTriple = Triple;
+ return false;
+ }
+
+ virtual bool ReadPredefinesBuffer(const char *PCHPredef,
+ unsigned PCHPredefLen,
+ FileID PCHBufferID,
+ std::string &SuggestedPredefines) {
+ Predefines = PCHPredef;
+ return false;
+ }
+
+ virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI) {
+ HSI.setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
+ }
+
+ virtual void ReadCounter(unsigned Value) {
+ Counter = Value;
+ }
+};
+
+} // anonymous namespace
+
+
+ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,
+ FileManager &FileMgr,
+ std::string *ErrMsg) {
+
+ llvm::OwningPtr<ASTUnit> AST(new ASTUnit());
+
+ AST->DiagClient.reset(new TextDiagnosticBuffer());
+ AST->Diags.reset(new Diagnostic(AST->DiagClient.get()));
+
+ AST->HeaderInfo.reset(new HeaderSearch(FileMgr));
+ AST->SourceMgr.reset(new SourceManager());
+
+ Diagnostic &Diags = *AST->Diags.get();
+ SourceManager &SourceMgr = *AST->SourceMgr.get();
+
+ // Gather Info for preprocessor construction later on.
+
+ LangOptions LangInfo;
+ HeaderSearch &HeaderInfo = *AST->HeaderInfo.get();
+ std::string TargetTriple;
+ std::string Predefines;
+ unsigned Counter;
+
+ llvm::OwningPtr<PCHReader> Reader;
+ llvm::OwningPtr<ExternalASTSource> Source;
+
+ Reader.reset(new PCHReader(SourceMgr, FileMgr, Diags));
+ Reader->setListener(new PCHInfoCollector(LangInfo, HeaderInfo, TargetTriple,
+ Predefines, Counter));
+
+ switch (Reader->ReadPCH(Filename)) {
+ case PCHReader::Success:
+ break;
+
+ case PCHReader::Failure:
+ // Unrecoverable failure: don't even try to process the input
+ // file.
+ if (ErrMsg)
+ *ErrMsg = "Could not load PCH file";
+ return NULL;
+
+ case PCHReader::IgnorePCH:
+ assert(0 && "Is there a validation that should not have happened ?");
+ }
+
+ // PCH loaded successfully. Now create the preprocessor.
+
+ // Get information about the target being compiled for.
+ AST->Target.reset(TargetInfo::CreateTargetInfo(TargetTriple));
+ AST->PP.reset(new Preprocessor(Diags, LangInfo, *AST->Target.get(),
+ SourceMgr, HeaderInfo));
+ Preprocessor &PP = *AST->PP.get();
+
+ PP.setPredefines(Predefines);
+ PP.setCounterValue(Counter);
+ Reader->setPreprocessor(PP);
+
+ // Create and initialize the ASTContext.
+
+ AST->Ctx.reset(new ASTContext(LangInfo,
+ SourceMgr,
+ *AST->Target.get(),
+ PP.getIdentifierTable(),
+ PP.getSelectorTable(),
+ PP.getBuiltinInfo(),
+ /* FreeMemory = */ true,
+ /* size_reserve = */0));
+ ASTContext &Context = *AST->Ctx.get();
+
+ Reader->InitializeContext(Context);
+
+ // Attach the PCH reader to the AST context as an external AST
+ // source, so that declarations will be deserialized from the
+ // PCH file as needed.
+ Source.reset(Reader.take());
+ Context.setExternalSource(Source);
+
+ return AST.take();
+}
diff --git a/lib/Frontend/CMakeLists.txt b/lib/Frontend/CMakeLists.txt
index 649f9dae37bd..330b4dba0663 100644
--- a/lib/Frontend/CMakeLists.txt
+++ b/lib/Frontend/CMakeLists.txt
@@ -5,6 +5,7 @@ add_clang_library(clangFrontend
ASTConsumers.cpp
Backend.cpp
CacheTokens.cpp
+ DeclXML.cpp
DependencyFile.cpp
DiagChecker.cpp
DocumentXML.cpp
@@ -31,5 +32,8 @@ add_clang_library(clangFrontend
StmtXML.cpp
TextDiagnosticBuffer.cpp
TextDiagnosticPrinter.cpp
+ TypeXML.cpp
Warnings.cpp
)
+
+add_dependencies(clangSema ClangDiagnosticFrontend)
diff --git a/lib/Frontend/DeclXML.cpp b/lib/Frontend/DeclXML.cpp
new file mode 100644
index 000000000000..5c21999bfa05
--- /dev/null
+++ b/lib/Frontend/DeclXML.cpp
@@ -0,0 +1,161 @@
+//===--- DeclXML.cpp - XML implementation for Decl ASTs -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the XML document class, which provides the means to
+// dump out the AST in a XML form that exposes type details and other fields.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/DocumentXML.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/Expr.h"
+
+namespace clang {
+
+//---------------------------------------------------------
+class DocumentXML::DeclPrinter : public DeclVisitor<DocumentXML::DeclPrinter>
+{
+ DocumentXML& Doc;
+
+ void addSubNodes(FunctionDecl* FD)
+ {
+ for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i)
+ {
+ Visit(FD->getParamDecl(i));
+ Doc.toParent();
+ }
+ }
+
+ void addSubNodes(RecordDecl* RD)
+ {
+ for (RecordDecl::field_iterator i = RD->field_begin(*Doc.Ctx), e = RD->field_end(*Doc.Ctx); i != e; ++i)
+ {
+ Visit(*i);
+ Doc.toParent();
+ }
+ }
+
+ void addSubNodes(EnumDecl* ED)
+ {
+ for (EnumDecl::enumerator_iterator i = ED->enumerator_begin(*Doc.Ctx), e = ED->enumerator_end(*Doc.Ctx); i != e; ++i)
+ {
+ Visit(*i);
+ Doc.toParent();
+ }
+ }
+
+ void addSubNodes(EnumConstantDecl* ECD)
+ {
+ if (ECD->getInitExpr())
+ {
+ Doc.PrintStmt(ECD->getInitExpr());
+ }
+ }
+
+ void addSubNodes(FieldDecl* FdD)
+ {
+ if (FdD->isBitField())
+ {
+ Doc.PrintStmt(FdD->getBitWidth());
+ }
+ }
+
+ void addSubNodes(VarDecl* V)
+ {
+ if (V->getInit())
+ {
+ Doc.PrintStmt(V->getInit());
+ }
+ }
+
+ void addSubNodes(ParmVarDecl* argDecl)
+ {
+ if (argDecl->getDefaultArg())
+ {
+ Doc.PrintStmt(argDecl->getDefaultArg());
+ }
+ }
+
+ void addSpecialAttribute(const char* pName, EnumDecl* ED)
+ {
+ const QualType& enumType = ED->getIntegerType();
+ if (!enumType.isNull())
+ {
+ Doc.addAttribute(pName, enumType);
+ }
+ }
+
+ void addIdAttribute(LinkageSpecDecl* ED)
+ {
+ Doc.addAttribute("id", ED);
+ }
+
+ void addIdAttribute(NamedDecl* ND)
+ {
+ Doc.addAttribute("id", ND);
+ }
+
+public:
+ DeclPrinter(DocumentXML& doc) : Doc(doc) {}
+
+#define NODE_XML( CLASS, NAME ) \
+ void Visit##CLASS(CLASS* T) \
+ { \
+ Doc.addSubNode(NAME);
+
+#define ID_ATTRIBUTE_XML addIdAttribute(T);
+#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, T->FN);
+#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, T->FN);
+#define ATTRIBUTE_FILE_LOCATION_XML Doc.addLocation(T->getLocation());
+#define ATTRIBUTE_SPECIAL_XML( FN, NAME ) addSpecialAttribute(NAME, T);
+
+#define ATTRIBUTE_ENUM_XML( FN, NAME ) \
+ { \
+ const char* pAttributeName = NAME; \
+ const bool optional = false; \
+ switch (T->FN) { \
+ default: assert(0 && "unknown enum value");
+
+#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \
+ { \
+ const char* pAttributeName = NAME; \
+ const bool optional = true; \
+ switch (T->FN) { \
+ default: assert(0 && "unknown enum value");
+
+#define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break;
+#define END_ENUM_XML } }
+#define END_NODE_XML }
+
+#define SUB_NODE_XML( CLASS ) addSubNodes(T);
+#define SUB_NODE_SEQUENCE_XML( CLASS ) addSubNodes(T);
+#define SUB_NODE_OPT_XML( CLASS ) addSubNodes(T);
+
+#include "clang/Frontend/DeclXML.def"
+};
+
+
+//---------------------------------------------------------
+void DocumentXML::writeDeclToXML(Decl *D)
+{
+ DeclPrinter(*this).Visit(D);
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ {
+ if (Stmt *Body = FD->getBody(*Ctx)) {
+ addSubNode("Body");
+ PrintStmt(Body);
+ toParent();
+ }
+ }
+ toParent();
+}
+
+//---------------------------------------------------------
+} // NS clang
+
diff --git a/lib/Frontend/DocumentXML.cpp b/lib/Frontend/DocumentXML.cpp
index 7562d2ae8714..19a757303f1b 100644
--- a/lib/Frontend/DocumentXML.cpp
+++ b/lib/Frontend/DocumentXML.cpp
@@ -14,92 +14,66 @@
#include "clang/Frontend/DocumentXML.h"
#include "clang/AST/Decl.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/Expr.h"
+#include "clang/AST/ASTContext.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/StringExtras.h"
namespace clang {
//---------------------------------------------------------
-struct DocumentXML::NodeXML
-{
- std::string Name;
- NodeXML* Parent;
-
- NodeXML(const std::string& name, NodeXML* parent) :
- Name(name),
- Parent(parent)
- {}
-};
-
-//---------------------------------------------------------
DocumentXML::DocumentXML(const std::string& rootName, llvm::raw_ostream& out) :
- Root(new NodeXML(rootName, 0)),
- CurrentNode(Root),
Out(out),
Ctx(0),
- CurrentIndent(0),
HasCurrentNodeSubNodes(false)
{
+ NodeStack.push(rootName);
Out << "<?xml version=\"1.0\"?>\n<" << rootName;
}
//---------------------------------------------------------
-DocumentXML::~DocumentXML()
-{
- assert(CurrentNode == Root && "not completely backtracked");
- delete Root;
-}
-
-//---------------------------------------------------------
DocumentXML& DocumentXML::addSubNode(const std::string& name)
{
if (!HasCurrentNodeSubNodes)
{
Out << ">\n";
}
- CurrentNode = new NodeXML(name, CurrentNode);
+ NodeStack.push(name);
HasCurrentNodeSubNodes = false;
- CurrentIndent += 2;
Indent();
- Out << "<" << CurrentNode->Name;
+ Out << "<" << NodeStack.top();
return *this;
}
//---------------------------------------------------------
void DocumentXML::Indent()
{
- for (int i = 0; i < CurrentIndent; ++i)
+ for (size_t i = 0, e = (NodeStack.size() - 1) * 2; i < e; ++i)
Out << ' ';
}
//---------------------------------------------------------
DocumentXML& DocumentXML::toParent()
{
- assert(CurrentNode != Root && "to much backtracking");
+ assert(NodeStack.size() > 1 && "to much backtracking");
if (HasCurrentNodeSubNodes)
{
Indent();
- Out << "</" << CurrentNode->Name << ">\n";
+ Out << "</" << NodeStack.top() << ">\n";
}
else
{
Out << "/>\n";
}
- NodeXML* NodeToDelete = CurrentNode;
- CurrentNode = CurrentNode->Parent;
- delete NodeToDelete;
+ NodeStack.pop();
HasCurrentNodeSubNodes = true;
- CurrentIndent -= 2;
return *this;
}
//---------------------------------------------------------
namespace {
-enum tIdType { ID_NORMAL, ID_FILE, ID_LAST };
+enum tIdType { ID_NORMAL, ID_FILE, ID_LABEL, ID_LAST };
unsigned getNewId(tIdType idType)
{
@@ -110,7 +84,7 @@ unsigned getNewId(tIdType idType)
//---------------------------------------------------------
inline std::string getPrefixedId(unsigned uId, tIdType idType)
{
- static const char idPrefix[ID_LAST] = { '_', 'f' };
+ static const char idPrefix[ID_LAST] = { '_', 'f', 'l' };
char buffer[20];
char* BufPtr = llvm::utohex_buffer(uId, buffer + 20);
*--BufPtr = idPrefix[idType];
@@ -132,6 +106,7 @@ bool addToMap(T& idMap, const V& value, tIdType idType = ID_NORMAL)
} // anon NS
+
//---------------------------------------------------------
std::string DocumentXML::escapeString(const char* pStr, std::string::size_type len)
{
@@ -170,7 +145,7 @@ std::string DocumentXML::escapeString(const char* pStr, std::string::size_type l
//---------------------------------------------------------
void DocumentXML::finalize()
{
- assert(CurrentNode == Root && "not completely backtracked");
+ assert(NodeStack.size() == 1 && "not completely backtracked");
addSubNode("ReferenceSection");
addSubNode("Types");
@@ -179,71 +154,15 @@ void DocumentXML::finalize()
{
if (i->first.getCVRQualifiers() != 0)
{
- addSubNode("CvQualifiedType");
+ writeTypeToXML(i->first);
addAttribute("id", getPrefixedId(i->second, ID_NORMAL));
- addAttribute("type", getPrefixedId(BasicTypes[i->first.getTypePtr()], ID_NORMAL));
- if (i->first.isConstQualified()) addAttribute("const", "1");
- if (i->first.isVolatileQualified()) addAttribute("volatile", "1");
- if (i->first.isRestrictQualified()) addAttribute("restrict", "1");
toParent();
}
}
for (XML::IdMap<const Type*>::iterator i = BasicTypes.begin(), e = BasicTypes.end(); i != e; ++i)
{
- // don't use the get methods as they strip of typedef infos
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(i->first)) {
- addSubNode("FundamentalType");
- addAttribute("name", BT->getName(Ctx->getLangOptions().CPlusPlus));
- }
- else if (const PointerType *PT = dyn_cast<PointerType>(i->first)) {
- addSubNode("PointerType");
- addTypeAttribute(PT->getPointeeType());
- }
- else if (dyn_cast<FunctionType>(i->first) != 0) {
- addSubNode("FunctionType");
- }
- else if (const ReferenceType *RT = dyn_cast<ReferenceType>(i->first)) {
- addSubNode("ReferenceType");
- addTypeAttribute(RT->getPointeeType());
- }
- else if (const TypedefType * TT = dyn_cast<TypedefType>(i->first)) {
- addSubNode("Typedef");
- addAttribute("name", TT->getDecl()->getNameAsString());
- addTypeAttribute(TT->getDecl()->getUnderlyingType());
- addContextAttribute(TT->getDecl()->getDeclContext());
- }
- else if (const QualifiedNameType *QT = dyn_cast<QualifiedNameType>(i->first)) {
- addSubNode("QualifiedNameType");
- addTypeAttribute(QT->getNamedType());
- }
- else if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(i->first)) {
- addSubNode("ArrayType");
- addAttribute("min", 0);
- addAttribute("max", (CAT->getSize() - 1).toString(10, false));
- addTypeAttribute(CAT->getElementType());
- }
- else if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(i->first)) {
- addSubNode("VariableArrayType");
- addTypeAttribute(VAT->getElementType());
- }
- else if (const TagType *RET = dyn_cast<TagType>(i->first)) {
- const TagDecl *tagDecl = RET->getDecl();
- std::string tagKind = tagDecl->getKindName();
- tagKind[0] = std::toupper(tagKind[0]);
- addSubNode(tagKind);
- addAttribute("name", tagDecl->getNameAsString());
- addContextAttribute(tagDecl->getDeclContext());
- }
- else if (const VectorType* VT = dyn_cast<VectorType>(i->first)) {
- addSubNode("VectorType");
- addTypeAttribute(VT->getElementType());
- addAttribute("num_elements", VT->getNumElements());
- }
- else
- {
- addSubNode("FIXMEType");
- }
+ writeTypeToXML(i->first);
addAttribute("id", getPrefixedId(i->second, ID_NORMAL));
toParent();
}
@@ -267,7 +186,7 @@ void DocumentXML::finalize()
if (const DeclContext* parent = i->first->getParent())
{
- addContextAttribute(parent);
+ addAttribute("context", parent);
}
toParent();
}
@@ -285,21 +204,21 @@ void DocumentXML::finalize()
toParent().toParent();
// write the root closing node (which has always subnodes)
- Out << "</" << CurrentNode->Name << ">\n";
+ Out << "</" << NodeStack.top() << ">\n";
}
//---------------------------------------------------------
-void DocumentXML::addTypeAttribute(const QualType& pType)
+void DocumentXML::addAttribute(const char* pAttributeName, const QualType& pType)
{
addTypeRecursively(pType);
- addAttribute("type", getPrefixedId(Types[pType], ID_NORMAL));
+ addAttribute(pAttributeName, getPrefixedId(Types[pType], ID_NORMAL));
}
//---------------------------------------------------------
-void DocumentXML::addTypeIdAttribute(const Type* pType)
+void DocumentXML::addPtrAttribute(const char* pAttributeName, const Type* pType)
{
- addBasicTypeRecursively(pType);
- addAttribute("id", getPrefixedId(BasicTypes[pType], ID_NORMAL));
+ addTypeRecursively(pType);
+ addAttribute(pAttributeName, getPrefixedId(BasicTypes[pType], ID_NORMAL));
}
//---------------------------------------------------------
@@ -307,7 +226,7 @@ void DocumentXML::addTypeRecursively(const QualType& pType)
{
if (addToMap(Types, pType))
{
- addBasicTypeRecursively(pType.getTypePtr());
+ addTypeRecursively(pType.getTypePtr());
// beautifier: a non-qualified type shall be transparent
if (pType.getCVRQualifiers() == 0)
{
@@ -317,43 +236,49 @@ void DocumentXML::addTypeRecursively(const QualType& pType)
}
//---------------------------------------------------------
-void DocumentXML::addBasicTypeRecursively(const Type* pType)
+void DocumentXML::addTypeRecursively(const Type* pType)
{
if (addToMap(BasicTypes, pType))
{
- if (const PointerType *PT = dyn_cast<PointerType>(pType)) {
- addTypeRecursively(PT->getPointeeType());
- }
- else if (const ReferenceType *RT = dyn_cast<ReferenceType>(pType)) {
- addTypeRecursively(RT->getPointeeType());
- }
- else if (const TypedefType *TT = dyn_cast<TypedefType>(pType)) {
- addTypeRecursively(TT->getDecl()->getUnderlyingType());
- addContextsRecursively(TT->getDecl()->getDeclContext());
- }
- else if (const QualifiedNameType *QT = dyn_cast<QualifiedNameType>(pType)) {
- addTypeRecursively(QT->getNamedType());
- // FIXME: what to do with NestedNameSpecifier or shall this type be transparent?
- }
- else if (const ArrayType *AT = dyn_cast<ArrayType>(pType)) {
- addTypeRecursively(AT->getElementType());
- // FIXME: doesn't work in the immediate streaming approach
- /*if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(AT))
- {
- addSubNode("VariableArraySizeExpression");
- PrintStmt(VAT->getSizeExpr());
- toParent();
- }*/
+ addParentTypes(pType);
+/*
+ // FIXME: doesn't work in the immediate streaming approach
+ if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(pType))
+ {
+ addSubNode("VariableArraySizeExpression");
+ PrintStmt(VAT->getSizeExpr());
+ toParent();
}
+*/
}
}
//---------------------------------------------------------
-void DocumentXML::addContextAttribute(const DeclContext *DC, tContextUsage usage)
+void DocumentXML::addPtrAttribute(const char* pName, const DeclContext* DC)
{
addContextsRecursively(DC);
- const char* pAttributeTags[2] = { "context", "id" };
- addAttribute(pAttributeTags[usage], getPrefixedId(Contexts[DC], ID_NORMAL));
+ addAttribute(pName, getPrefixedId(Contexts[DC], ID_NORMAL));
+}
+
+//---------------------------------------------------------
+void DocumentXML::addPtrAttribute(const char* pAttributeName, const NamedDecl* D)
+{
+ if (const DeclContext* DC = dyn_cast<DeclContext>(D))
+ {
+ addContextsRecursively(DC);
+ addAttribute(pAttributeName, getPrefixedId(Contexts[DC], ID_NORMAL));
+ }
+ else
+ {
+ addToMap(Decls, D);
+ addAttribute(pAttributeName, getPrefixedId(Decls[D], ID_NORMAL));
+ }
+}
+
+//---------------------------------------------------------
+void DocumentXML::addPtrAttribute(const char* pName, const NamespaceDecl* D)
+{
+ addPtrAttribute(pName, static_cast<const DeclContext*>(D));
}
//---------------------------------------------------------
@@ -372,6 +297,15 @@ void DocumentXML::addSourceFileAttribute(const std::string& fileName)
addAttribute("file", getPrefixedId(SourceFiles[fileName], ID_FILE));
}
+
+//---------------------------------------------------------
+void DocumentXML::addPtrAttribute(const char* pName, const LabelStmt* L)
+{
+ addToMap(Labels, L, ID_LABEL);
+ addAttribute(pName, getPrefixedId(Labels[L], ID_LABEL));
+}
+
+
//---------------------------------------------------------
PresumedLoc DocumentXML::addLocation(const SourceLocation& Loc)
{
@@ -417,161 +351,9 @@ void DocumentXML::addLocationRange(const SourceRange& R)
}
//---------------------------------------------------------
-void DocumentXML::PrintFunctionDecl(FunctionDecl *FD)
-{
- switch (FD->getStorageClass()) {
- default: assert(0 && "Unknown storage class");
- case FunctionDecl::None: break;
- case FunctionDecl::Extern: addAttribute("storage_class", "extern"); break;
- case FunctionDecl::Static: addAttribute("storage_class", "static"); break;
- case FunctionDecl::PrivateExtern: addAttribute("storage_class", "__private_extern__"); break;
- }
-
- if (FD->isInline())
- addAttribute("inline", "1");
-
- const FunctionType *AFT = FD->getType()->getAsFunctionType();
- addTypeAttribute(AFT->getResultType());
- addBasicTypeRecursively(AFT);
-
- if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(AFT)) {
- addAttribute("num_args", FD->getNumParams());
- for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) {
- addSubNode("Argument");
- ParmVarDecl *argDecl = FD->getParamDecl(i);
- addAttribute("name", argDecl->getNameAsString());
- addTypeAttribute(FT->getArgType(i));
- addDeclIdAttribute(argDecl);
- if (argDecl->getDefaultArg())
- {
- addAttribute("default_arg", "1");
- PrintStmt(argDecl->getDefaultArg());
- }
- toParent();
- }
-
- if (FT->isVariadic()) {
- addSubNode("Ellipsis").toParent();
- }
- } else {
- assert(isa<FunctionNoProtoType>(AFT));
- }
-}
-
-//---------------------------------------------------------
-void DocumentXML::addRefAttribute(const NamedDecl* D)
-{
- // FIXME: in case of CXX inline member functions referring to a member defined
- // after the function it needs to be tested, if the ids are already there
- // (should work, but I couldn't test it)
- if (const DeclContext* DC = dyn_cast<DeclContext>(D))
- {
- addAttribute("ref", getPrefixedId(Contexts[DC], ID_NORMAL));
- }
- else
- {
- addAttribute("ref", getPrefixedId(Decls[D], ID_NORMAL));
- }
-}
-
-//---------------------------------------------------------
-void DocumentXML::addDeclIdAttribute(const NamedDecl* D)
-{
- addToMap(Decls, D);
- addAttribute("id", getPrefixedId(Decls[D], ID_NORMAL));
-}
-
-//---------------------------------------------------------
void DocumentXML::PrintDecl(Decl *D)
{
- addSubNode(D->getDeclKindName());
- addContextAttribute(D->getDeclContext());
- addLocation(D->getLocation());
- if (DeclContext* DC = dyn_cast<DeclContext>(D))
- {
- addContextAttribute(DC, CONTEXT_AS_ID);
- }
-
- if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
- addAttribute("name", ND->getNameAsString());
-
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- PrintFunctionDecl(FD);
- if (Stmt *Body = FD->getBody(*Ctx)) {
- addSubNode("Body");
- PrintStmt(Body);
- toParent();
- }
- } else if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
- addBasicTypeRecursively(RD->getTypeForDecl());
- addAttribute("type", getPrefixedId(BasicTypes[RD->getTypeForDecl()], ID_NORMAL));
- if (!RD->isDefinition())
- {
- addAttribute("forward", "1");
- }
-
- for (RecordDecl::field_iterator i = RD->field_begin(*Ctx), e = RD->field_end(*Ctx); i != e; ++i)
- {
- PrintDecl(*i);
- }
- } else if (EnumDecl *ED = dyn_cast<EnumDecl>(D)) {
- const QualType& enumType = ED->getIntegerType();
- if (!enumType.isNull())
- {
- addTypeAttribute(enumType);
- for (EnumDecl::enumerator_iterator i = ED->enumerator_begin(*Ctx), e = ED->enumerator_end(*Ctx); i != e; ++i)
- {
- PrintDecl(*i);
- }
- }
- } else if (EnumConstantDecl* ECD = dyn_cast<EnumConstantDecl>(D)) {
- addTypeAttribute(ECD->getType());
- addAttribute("value", ECD->getInitVal().toString(10, true));
- if (ECD->getInitExpr())
- {
- PrintStmt(ECD->getInitExpr());
- }
- } else if (FieldDecl *FdD = dyn_cast<FieldDecl>(D)) {
- addTypeAttribute(FdD->getType());
- addDeclIdAttribute(ND);
- if (FdD->isMutable())
- addAttribute("mutable", "1");
- if (FdD->isBitField())
- {
- addAttribute("bitfield", "1");
- PrintStmt(FdD->getBitWidth());
- }
- } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
- addTypeIdAttribute(Ctx->getTypedefType(TD).getTypePtr());
- addTypeAttribute(TD->getUnderlyingType());
- } else if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
- addTypeAttribute(VD->getType());
- addDeclIdAttribute(ND);
-
- VarDecl *V = dyn_cast<VarDecl>(VD);
- if (V && V->getStorageClass() != VarDecl::None)
- {
- addAttribute("storage_class", VarDecl::getStorageClassSpecifierString(V->getStorageClass()));
- }
-
- if (V && V->getInit())
- {
- PrintStmt(V->getInit());
- }
- }
- } else if (LinkageSpecDecl* LSD = dyn_cast<LinkageSpecDecl>(D)) {
- switch (LSD->getLanguage())
- {
- case LinkageSpecDecl::lang_c: addAttribute("lang", "C"); break;
- case LinkageSpecDecl::lang_cxx: addAttribute("lang", "CXX"); break;
- default: assert(0 && "Unexpected lang id");
- }
- } else if (isa<FileScopeAsmDecl>(D)) {
- // FIXME: Implement this
- } else {
- assert(0 && "Unexpected decl");
- }
- toParent();
+ writeDeclToXML(D);
}
//---------------------------------------------------------
diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp
index 6383c2076ba4..7a2b3a7317b4 100644
--- a/lib/Frontend/InitHeaderSearch.cpp
+++ b/lib/Frontend/InitHeaderSearch.cpp
@@ -138,6 +138,12 @@ void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang) {
false);
AddPath("/usr/include/c++/4.1.3/backward", System, true, false, false);
+ // Ubuntu 9.04
+ AddPath("/usr/include/c++/4.3.3", System, true, false, false);
+ AddPath("/usr/include/c++/4.3.3/x86_64-linux-gnu/", System, true, false,
+ false);
+ AddPath("/usr/include/c++/4.3.3/backward", System, true, false, false);
+
// Fedora 8
AddPath("/usr/include/c++/4.1.2", System, true, false, false);
AddPath("/usr/include/c++/4.1.2/i386-redhat-linux", System, true, false,
diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp
index 6cff75daf3cb..41908ad00e49 100644
--- a/lib/Frontend/InitPreprocessor.cpp
+++ b/lib/Frontend/InitPreprocessor.cpp
@@ -472,11 +472,7 @@ bool InitializePreprocessor(Preprocessor &PP,
AddImplicitIncludePTH(PredefineBuffer, PP, I->first);
else
AddImplicitInclude(PredefineBuffer, I->first);
- }
-
- LineDirective = "# 2 \"<built-in>\" 2 3\n";
- PredefineBuffer.insert(PredefineBuffer.end(),
- LineDirective, LineDirective+strlen(LineDirective));
+ }
// Null terminate PredefinedBuffer and add it.
PredefineBuffer.push_back(0);
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index 87fc8394c8db..96f21f112867 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -36,11 +36,321 @@
using namespace clang;
//===----------------------------------------------------------------------===//
+// PCH reader validator implementation
+//===----------------------------------------------------------------------===//
+
+PCHReaderListener::~PCHReaderListener() {}
+
+bool
+PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) {
+ const LangOptions &PPLangOpts = PP.getLangOptions();
+#define PARSE_LANGOPT_BENIGN(Option)
+#define PARSE_LANGOPT_IMPORTANT(Option, DiagID) \
+ if (PPLangOpts.Option != LangOpts.Option) { \
+ Reader.Diag(DiagID) << LangOpts.Option << PPLangOpts.Option; \
+ return true; \
+ }
+
+ PARSE_LANGOPT_BENIGN(Trigraphs);
+ PARSE_LANGOPT_BENIGN(BCPLComment);
+ PARSE_LANGOPT_BENIGN(DollarIdents);
+ PARSE_LANGOPT_BENIGN(AsmPreprocessor);
+ PARSE_LANGOPT_IMPORTANT(GNUMode, diag::warn_pch_gnu_extensions);
+ PARSE_LANGOPT_BENIGN(ImplicitInt);
+ PARSE_LANGOPT_BENIGN(Digraphs);
+ PARSE_LANGOPT_BENIGN(HexFloats);
+ PARSE_LANGOPT_IMPORTANT(C99, diag::warn_pch_c99);
+ PARSE_LANGOPT_IMPORTANT(Microsoft, diag::warn_pch_microsoft_extensions);
+ PARSE_LANGOPT_IMPORTANT(CPlusPlus, diag::warn_pch_cplusplus);
+ PARSE_LANGOPT_IMPORTANT(CPlusPlus0x, diag::warn_pch_cplusplus0x);
+ PARSE_LANGOPT_BENIGN(CXXOperatorName);
+ PARSE_LANGOPT_IMPORTANT(ObjC1, diag::warn_pch_objective_c);
+ PARSE_LANGOPT_IMPORTANT(ObjC2, diag::warn_pch_objective_c2);
+ PARSE_LANGOPT_IMPORTANT(ObjCNonFragileABI, diag::warn_pch_nonfragile_abi);
+ PARSE_LANGOPT_BENIGN(PascalStrings);
+ PARSE_LANGOPT_BENIGN(WritableStrings);
+ PARSE_LANGOPT_IMPORTANT(LaxVectorConversions,
+ diag::warn_pch_lax_vector_conversions);
+ PARSE_LANGOPT_IMPORTANT(Exceptions, diag::warn_pch_exceptions);
+ PARSE_LANGOPT_IMPORTANT(NeXTRuntime, diag::warn_pch_objc_runtime);
+ PARSE_LANGOPT_IMPORTANT(Freestanding, diag::warn_pch_freestanding);
+ PARSE_LANGOPT_IMPORTANT(NoBuiltin, diag::warn_pch_builtins);
+ PARSE_LANGOPT_IMPORTANT(ThreadsafeStatics,
+ diag::warn_pch_thread_safe_statics);
+ PARSE_LANGOPT_IMPORTANT(Blocks, diag::warn_pch_blocks);
+ PARSE_LANGOPT_BENIGN(EmitAllDecls);
+ PARSE_LANGOPT_IMPORTANT(MathErrno, diag::warn_pch_math_errno);
+ PARSE_LANGOPT_IMPORTANT(OverflowChecking, diag::warn_pch_overflow_checking);
+ PARSE_LANGOPT_IMPORTANT(HeinousExtensions,
+ diag::warn_pch_heinous_extensions);
+ // FIXME: Most of the options below are benign if the macro wasn't
+ // used. Unfortunately, this means that a PCH compiled without
+ // optimization can't be used with optimization turned on, even
+ // though the only thing that changes is whether __OPTIMIZE__ was
+ // defined... but if __OPTIMIZE__ never showed up in the header, it
+ // doesn't matter. We could consider making this some special kind
+ // of check.
+ PARSE_LANGOPT_IMPORTANT(Optimize, diag::warn_pch_optimize);
+ PARSE_LANGOPT_IMPORTANT(OptimizeSize, diag::warn_pch_optimize_size);
+ PARSE_LANGOPT_IMPORTANT(Static, diag::warn_pch_static);
+ PARSE_LANGOPT_IMPORTANT(PICLevel, diag::warn_pch_pic_level);
+ PARSE_LANGOPT_IMPORTANT(GNUInline, diag::warn_pch_gnu_inline);
+ PARSE_LANGOPT_IMPORTANT(NoInline, diag::warn_pch_no_inline);
+ PARSE_LANGOPT_IMPORTANT(AccessControl, diag::warn_pch_access_control);
+ PARSE_LANGOPT_IMPORTANT(CharIsSigned, diag::warn_pch_char_signed);
+ if ((PPLangOpts.getGCMode() != 0) != (LangOpts.getGCMode() != 0)) {
+ Reader.Diag(diag::warn_pch_gc_mode)
+ << LangOpts.getGCMode() << PPLangOpts.getGCMode();
+ return true;
+ }
+ PARSE_LANGOPT_BENIGN(getVisibilityMode());
+ PARSE_LANGOPT_BENIGN(InstantiationDepth);
+#undef PARSE_LANGOPT_IRRELEVANT
+#undef PARSE_LANGOPT_BENIGN
+
+ return false;
+}
+
+bool PCHValidator::ReadTargetTriple(const std::string &Triple) {
+ if (Triple != PP.getTargetInfo().getTargetTriple()) {
+ Reader.Diag(diag::warn_pch_target_triple)
+ << Triple << PP.getTargetInfo().getTargetTriple();
+ return true;
+ }
+ return false;
+}
+
+/// \brief Split the given string into a vector of lines, eliminating
+/// any empty lines in the process.
+///
+/// \param Str the string to split.
+/// \param Len the length of Str.
+/// \param KeepEmptyLines true if empty lines should be included
+/// \returns a vector of lines, with the line endings removed
+static std::vector<std::string> splitLines(const char *Str, unsigned Len,
+ bool KeepEmptyLines = false) {
+ std::vector<std::string> Lines;
+ for (unsigned LineStart = 0; LineStart < Len; ++LineStart) {
+ unsigned LineEnd = LineStart;
+ while (LineEnd < Len && Str[LineEnd] != '\n')
+ ++LineEnd;
+ if (LineStart != LineEnd || KeepEmptyLines)
+ Lines.push_back(std::string(&Str[LineStart], &Str[LineEnd]));
+ LineStart = LineEnd;
+ }
+ return Lines;
+}
+
+/// \brief Determine whether the string Haystack starts with the
+/// substring Needle.
+static bool startsWith(const std::string &Haystack, const char *Needle) {
+ for (unsigned I = 0, N = Haystack.size(); Needle[I] != 0; ++I) {
+ if (I == N)
+ return false;
+ if (Haystack[I] != Needle[I])
+ return false;
+ }
+
+ return true;
+}
+
+/// \brief Determine whether the string Haystack starts with the
+/// substring Needle.
+static inline bool startsWith(const std::string &Haystack,
+ const std::string &Needle) {
+ return startsWith(Haystack, Needle.c_str());
+}
+
+bool PCHValidator::ReadPredefinesBuffer(const char *PCHPredef,
+ unsigned PCHPredefLen,
+ FileID PCHBufferID,
+ std::string &SuggestedPredefines) {
+ const char *Predef = PP.getPredefines().c_str();
+ unsigned PredefLen = PP.getPredefines().size();
+
+ // If the two predefines buffers compare equal, we're done!
+ if (PredefLen == PCHPredefLen &&
+ strncmp(Predef, PCHPredef, PCHPredefLen) == 0)
+ return false;
+
+ SourceManager &SourceMgr = PP.getSourceManager();
+
+ // The predefines buffers are different. Determine what the
+ // differences are, and whether they require us to reject the PCH
+ // file.
+ std::vector<std::string> CmdLineLines = splitLines(Predef, PredefLen);
+ std::vector<std::string> PCHLines = splitLines(PCHPredef, PCHPredefLen);
+
+ // Sort both sets of predefined buffer lines, since
+ std::sort(CmdLineLines.begin(), CmdLineLines.end());
+ std::sort(PCHLines.begin(), PCHLines.end());
+
+ // Determine which predefines that where used to build the PCH file
+ // are missing from the command line.
+ std::vector<std::string> MissingPredefines;
+ std::set_difference(PCHLines.begin(), PCHLines.end(),
+ CmdLineLines.begin(), CmdLineLines.end(),
+ std::back_inserter(MissingPredefines));
+
+ bool MissingDefines = false;
+ bool ConflictingDefines = false;
+ for (unsigned I = 0, N = MissingPredefines.size(); I != N; ++I) {
+ const std::string &Missing = MissingPredefines[I];
+ if (!startsWith(Missing, "#define ") != 0) {
+ Reader.Diag(diag::warn_pch_compiler_options_mismatch);
+ return true;
+ }
+
+ // This is a macro definition. Determine the name of the macro
+ // we're defining.
+ std::string::size_type StartOfMacroName = strlen("#define ");
+ std::string::size_type EndOfMacroName
+ = Missing.find_first_of("( \n\r", StartOfMacroName);
+ assert(EndOfMacroName != std::string::npos &&
+ "Couldn't find the end of the macro name");
+ std::string MacroName = Missing.substr(StartOfMacroName,
+ EndOfMacroName - StartOfMacroName);
+
+ // Determine whether this macro was given a different definition
+ // on the command line.
+ std::string MacroDefStart = "#define " + MacroName;
+ std::string::size_type MacroDefLen = MacroDefStart.size();
+ std::vector<std::string>::iterator ConflictPos
+ = std::lower_bound(CmdLineLines.begin(), CmdLineLines.end(),
+ MacroDefStart);
+ for (; ConflictPos != CmdLineLines.end(); ++ConflictPos) {
+ if (!startsWith(*ConflictPos, MacroDefStart)) {
+ // Different macro; we're done.
+ ConflictPos = CmdLineLines.end();
+ break;
+ }
+
+ assert(ConflictPos->size() > MacroDefLen &&
+ "Invalid #define in predefines buffer?");
+ if ((*ConflictPos)[MacroDefLen] != ' ' &&
+ (*ConflictPos)[MacroDefLen] != '(')
+ continue; // Longer macro name; keep trying.
+
+ // We found a conflicting macro definition.
+ break;
+ }
+
+ if (ConflictPos != CmdLineLines.end()) {
+ Reader.Diag(diag::warn_cmdline_conflicting_macro_def)
+ << MacroName;
+
+ // Show the definition of this macro within the PCH file.
+ const char *MissingDef = strstr(PCHPredef, Missing.c_str());
+ unsigned Offset = MissingDef - PCHPredef;
+ SourceLocation PCHMissingLoc
+ = SourceMgr.getLocForStartOfFile(PCHBufferID)
+ .getFileLocWithOffset(Offset);
+ Reader.Diag(PCHMissingLoc, diag::note_pch_macro_defined_as)
+ << MacroName;
+
+ ConflictingDefines = true;
+ continue;
+ }
+
+ // If the macro doesn't conflict, then we'll just pick up the
+ // macro definition from the PCH file. Warn the user that they
+ // made a mistake.
+ if (ConflictingDefines)
+ continue; // Don't complain if there are already conflicting defs
+
+ if (!MissingDefines) {
+ Reader.Diag(diag::warn_cmdline_missing_macro_defs);
+ MissingDefines = true;
+ }
+
+ // Show the definition of this macro within the PCH file.
+ const char *MissingDef = strstr(PCHPredef, Missing.c_str());
+ unsigned Offset = MissingDef - PCHPredef;
+ SourceLocation PCHMissingLoc
+ = SourceMgr.getLocForStartOfFile(PCHBufferID)
+ .getFileLocWithOffset(Offset);
+ Reader.Diag(PCHMissingLoc, diag::note_using_macro_def_from_pch);
+ }
+
+ if (ConflictingDefines)
+ return true;
+
+ // Determine what predefines were introduced based on command-line
+ // parameters that were not present when building the PCH
+ // file. Extra #defines are okay, so long as the identifiers being
+ // defined were not used within the precompiled header.
+ std::vector<std::string> ExtraPredefines;
+ std::set_difference(CmdLineLines.begin(), CmdLineLines.end(),
+ PCHLines.begin(), PCHLines.end(),
+ std::back_inserter(ExtraPredefines));
+ for (unsigned I = 0, N = ExtraPredefines.size(); I != N; ++I) {
+ const std::string &Extra = ExtraPredefines[I];
+ if (!startsWith(Extra, "#define ") != 0) {
+ Reader.Diag(diag::warn_pch_compiler_options_mismatch);
+ return true;
+ }
+
+ // This is an extra macro definition. Determine the name of the
+ // macro we're defining.
+ std::string::size_type StartOfMacroName = strlen("#define ");
+ std::string::size_type EndOfMacroName
+ = Extra.find_first_of("( \n\r", StartOfMacroName);
+ assert(EndOfMacroName != std::string::npos &&
+ "Couldn't find the end of the macro name");
+ std::string MacroName = Extra.substr(StartOfMacroName,
+ EndOfMacroName - StartOfMacroName);
+
+ // Check whether this name was used somewhere in the PCH file. If
+ // so, defining it as a macro could change behavior, so we reject
+ // the PCH file.
+ if (IdentifierInfo *II = Reader.get(MacroName.c_str(),
+ MacroName.c_str() + MacroName.size())) {
+ Reader.Diag(diag::warn_macro_name_used_in_pch)
+ << II;
+ return true;
+ }
+
+ // Add this definition to the suggested predefines buffer.
+ SuggestedPredefines += Extra;
+ SuggestedPredefines += '\n';
+ }
+
+ // If we get here, it's because the predefines buffer had compatible
+ // contents. Accept the PCH file.
+ return false;
+}
+
+void PCHValidator::ReadHeaderFileInfo(const HeaderFileInfo &HFI) {
+ PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
+}
+
+void PCHValidator::ReadCounter(unsigned Value) {
+ PP.setCounterValue(Value);
+}
+
+
+
+//===----------------------------------------------------------------------===//
// PCH reader implementation
//===----------------------------------------------------------------------===//
PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context)
- : SemaObj(0), PP(PP), Context(Context), Consumer(0),
+ : Listener(new PCHValidator(PP, *this)), SourceMgr(PP.getSourceManager()),
+ FileMgr(PP.getFileManager()), Diags(PP.getDiagnostics()),
+ SemaObj(0), PP(&PP), Context(Context), Consumer(0),
+ IdentifierTableData(0), IdentifierLookupTable(0),
+ IdentifierOffsets(0),
+ MethodPoolLookupTable(0), MethodPoolLookupTableData(0),
+ TotalSelectorsInMethodPool(0), SelectorOffsets(0),
+ TotalNumSelectors(0), NumStatHits(0), NumStatMisses(0),
+ NumSLocEntriesRead(0), NumStatementsRead(0),
+ NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0),
+ NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0) { }
+
+PCHReader::PCHReader(SourceManager &SourceMgr, FileManager &FileMgr,
+ Diagnostic &Diags)
+ : SourceMgr(SourceMgr), FileMgr(FileMgr), Diags(Diags),
+ SemaObj(0), PP(0), Context(0), Consumer(0),
IdentifierTableData(0), IdentifierLookupTable(0),
IdentifierOffsets(0),
MethodPoolLookupTable(0), MethodPoolLookupTableData(0),
@@ -314,53 +624,11 @@ typedef OnDiskChainedHashTable<PCHIdentifierLookupTrait>
// FIXME: use the diagnostics machinery
bool PCHReader::Error(const char *Msg) {
- Diagnostic &Diags = PP.getDiagnostics();
unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Fatal, Msg);
Diag(DiagID);
return true;
}
-/// \brief Split the given string into a vector of lines, eliminating
-/// any empty lines in the process.
-///
-/// \param Str the string to split.
-/// \param Len the length of Str.
-/// \param KeepEmptyLines true if empty lines should be included
-/// \returns a vector of lines, with the line endings removed
-std::vector<std::string> splitLines(const char *Str, unsigned Len,
- bool KeepEmptyLines = false) {
- std::vector<std::string> Lines;
- for (unsigned LineStart = 0; LineStart < Len; ++LineStart) {
- unsigned LineEnd = LineStart;
- while (LineEnd < Len && Str[LineEnd] != '\n')
- ++LineEnd;
- if (LineStart != LineEnd || KeepEmptyLines)
- Lines.push_back(std::string(&Str[LineStart], &Str[LineEnd]));
- LineStart = LineEnd;
- }
- return Lines;
-}
-
-/// \brief Determine whether the string Haystack starts with the
-/// substring Needle.
-static bool startsWith(const std::string &Haystack, const char *Needle) {
- for (unsigned I = 0, N = Haystack.size(); Needle[I] != 0; ++I) {
- if (I == N)
- return false;
- if (Haystack[I] != Needle[I])
- return false;
- }
-
- return true;
-}
-
-/// \brief Determine whether the string Haystack starts with the
-/// substring Needle.
-static inline bool startsWith(const std::string &Haystack,
- const std::string &Needle) {
- return startsWith(Haystack, Needle.c_str());
-}
-
/// \brief Check the contents of the predefines buffer against the
/// contents of the predefines buffer used to build the PCH file.
///
@@ -381,158 +649,9 @@ static inline bool startsWith(const std::string &Haystack,
bool PCHReader::CheckPredefinesBuffer(const char *PCHPredef,
unsigned PCHPredefLen,
FileID PCHBufferID) {
- const char *Predef = PP.getPredefines().c_str();
- unsigned PredefLen = PP.getPredefines().size();
-
- // If the two predefines buffers compare equal, we're done!
- if (PredefLen == PCHPredefLen &&
- strncmp(Predef, PCHPredef, PCHPredefLen) == 0)
- return false;
-
- SourceManager &SourceMgr = PP.getSourceManager();
-
- // The predefines buffers are different. Determine what the
- // differences are, and whether they require us to reject the PCH
- // file.
- std::vector<std::string> CmdLineLines = splitLines(Predef, PredefLen);
- std::vector<std::string> PCHLines = splitLines(PCHPredef, PCHPredefLen);
-
- // Sort both sets of predefined buffer lines, since
- std::sort(CmdLineLines.begin(), CmdLineLines.end());
- std::sort(PCHLines.begin(), PCHLines.end());
-
- // Determine which predefines that where used to build the PCH file
- // are missing from the command line.
- std::vector<std::string> MissingPredefines;
- std::set_difference(PCHLines.begin(), PCHLines.end(),
- CmdLineLines.begin(), CmdLineLines.end(),
- std::back_inserter(MissingPredefines));
-
- bool MissingDefines = false;
- bool ConflictingDefines = false;
- for (unsigned I = 0, N = MissingPredefines.size(); I != N; ++I) {
- const std::string &Missing = MissingPredefines[I];
- if (!startsWith(Missing, "#define ") != 0) {
- Diag(diag::warn_pch_compiler_options_mismatch);
- return true;
- }
-
- // This is a macro definition. Determine the name of the macro
- // we're defining.
- std::string::size_type StartOfMacroName = strlen("#define ");
- std::string::size_type EndOfMacroName
- = Missing.find_first_of("( \n\r", StartOfMacroName);
- assert(EndOfMacroName != std::string::npos &&
- "Couldn't find the end of the macro name");
- std::string MacroName = Missing.substr(StartOfMacroName,
- EndOfMacroName - StartOfMacroName);
-
- // Determine whether this macro was given a different definition
- // on the command line.
- std::string MacroDefStart = "#define " + MacroName;
- std::string::size_type MacroDefLen = MacroDefStart.size();
- std::vector<std::string>::iterator ConflictPos
- = std::lower_bound(CmdLineLines.begin(), CmdLineLines.end(),
- MacroDefStart);
- for (; ConflictPos != CmdLineLines.end(); ++ConflictPos) {
- if (!startsWith(*ConflictPos, MacroDefStart)) {
- // Different macro; we're done.
- ConflictPos = CmdLineLines.end();
- break;
- }
-
- assert(ConflictPos->size() > MacroDefLen &&
- "Invalid #define in predefines buffer?");
- if ((*ConflictPos)[MacroDefLen] != ' ' &&
- (*ConflictPos)[MacroDefLen] != '(')
- continue; // Longer macro name; keep trying.
-
- // We found a conflicting macro definition.
- break;
- }
-
- if (ConflictPos != CmdLineLines.end()) {
- Diag(diag::warn_cmdline_conflicting_macro_def)
- << MacroName;
-
- // Show the definition of this macro within the PCH file.
- const char *MissingDef = strstr(PCHPredef, Missing.c_str());
- unsigned Offset = MissingDef - PCHPredef;
- SourceLocation PCHMissingLoc
- = SourceMgr.getLocForStartOfFile(PCHBufferID)
- .getFileLocWithOffset(Offset);
- Diag(PCHMissingLoc, diag::note_pch_macro_defined_as)
- << MacroName;
-
- ConflictingDefines = true;
- continue;
- }
-
- // If the macro doesn't conflict, then we'll just pick up the
- // macro definition from the PCH file. Warn the user that they
- // made a mistake.
- if (ConflictingDefines)
- continue; // Don't complain if there are already conflicting defs
-
- if (!MissingDefines) {
- Diag(diag::warn_cmdline_missing_macro_defs);
- MissingDefines = true;
- }
-
- // Show the definition of this macro within the PCH file.
- const char *MissingDef = strstr(PCHPredef, Missing.c_str());
- unsigned Offset = MissingDef - PCHPredef;
- SourceLocation PCHMissingLoc
- = SourceMgr.getLocForStartOfFile(PCHBufferID)
- .getFileLocWithOffset(Offset);
- Diag(PCHMissingLoc, diag::note_using_macro_def_from_pch);
- }
-
- if (ConflictingDefines)
- return true;
-
- // Determine what predefines were introduced based on command-line
- // parameters that were not present when building the PCH
- // file. Extra #defines are okay, so long as the identifiers being
- // defined were not used within the precompiled header.
- std::vector<std::string> ExtraPredefines;
- std::set_difference(CmdLineLines.begin(), CmdLineLines.end(),
- PCHLines.begin(), PCHLines.end(),
- std::back_inserter(ExtraPredefines));
- for (unsigned I = 0, N = ExtraPredefines.size(); I != N; ++I) {
- const std::string &Extra = ExtraPredefines[I];
- if (!startsWith(Extra, "#define ") != 0) {
- Diag(diag::warn_pch_compiler_options_mismatch);
- return true;
- }
-
- // This is an extra macro definition. Determine the name of the
- // macro we're defining.
- std::string::size_type StartOfMacroName = strlen("#define ");
- std::string::size_type EndOfMacroName
- = Extra.find_first_of("( \n\r", StartOfMacroName);
- assert(EndOfMacroName != std::string::npos &&
- "Couldn't find the end of the macro name");
- std::string MacroName = Extra.substr(StartOfMacroName,
- EndOfMacroName - StartOfMacroName);
-
- // Check whether this name was used somewhere in the PCH file. If
- // so, defining it as a macro could change behavior, so we reject
- // the PCH file.
- if (IdentifierInfo *II = get(MacroName.c_str(),
- MacroName.c_str() + MacroName.size())) {
- Diag(diag::warn_macro_name_used_in_pch)
- << II;
- return true;
- }
-
- // Add this definition to the suggested predefines buffer.
- SuggestedPredefines += Extra;
- SuggestedPredefines += '\n';
- }
-
- // If we get here, it's because the predefines buffer had compatible
- // contents. Accept the PCH file.
+ if (Listener)
+ return Listener->ReadPredefinesBuffer(PCHPredef, PCHPredefLen, PCHBufferID,
+ SuggestedPredefines);
return false;
}
@@ -714,9 +833,7 @@ PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() {
return Failure;
}
- SourceManager &SourceMgr = PP.getSourceManager();
RecordData Record;
- unsigned NumHeaderInfos = 0;
while (true) {
unsigned Code = SLocEntryCursor.ReadCode();
if (Code == llvm::bitc::END_BLOCK) {
@@ -761,7 +878,8 @@ PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() {
HFI.DirInfo = Record[1];
HFI.NumIncludes = Record[2];
HFI.ControllingMacroID = Record[3];
- PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
+ if (Listener)
+ Listener->ReadHeaderFileInfo(HFI);
break;
}
@@ -794,7 +912,6 @@ PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) {
return Failure;
}
- SourceManager &SourceMgr = PP.getSourceManager();
RecordData Record;
const char *BlobStart;
unsigned BlobLen;
@@ -804,9 +921,15 @@ PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) {
return Failure;
case pch::SM_SLOC_FILE_ENTRY: {
- const FileEntry *File
- = PP.getFileManager().getFile(BlobStart, BlobStart + BlobLen);
- // FIXME: Error recovery if file cannot be found.
+ const FileEntry *File = FileMgr.getFile(BlobStart, BlobStart + BlobLen);
+ if (File == 0) {
+ std::string ErrorStr = "could not find file '";
+ ErrorStr.append(BlobStart, BlobLen);
+ ErrorStr += "' referenced by PCH file";
+ Error(ErrorStr.c_str());
+ return Failure;
+ }
+
FileID FID = SourceMgr.createFileID(File,
SourceLocation::getFromRawEncoding(Record[1]),
(SrcMgr::CharacteristicKind)Record[2],
@@ -879,6 +1002,8 @@ bool PCHReader::ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor,
}
void PCHReader::ReadMacroRecord(uint64_t Offset) {
+ assert(PP && "Forgot to set Preprocessor ?");
+
// Keep track of where we are in the stream, then jump back there
// after reading this macro.
SavedStreamPosition SavedPosition(Stream);
@@ -930,7 +1055,7 @@ void PCHReader::ReadMacroRecord(uint64_t Offset) {
SourceLocation Loc = SourceLocation::getFromRawEncoding(Record[1]);
bool isUsed = Record[2];
- MacroInfo *MI = PP.AllocateMacroInfo(Loc);
+ MacroInfo *MI = PP->AllocateMacroInfo(Loc);
MI->setIsUsed(isUsed);
if (RecType == pch::PP_MACRO_FUNCTION_LIKE) {
@@ -947,11 +1072,11 @@ void PCHReader::ReadMacroRecord(uint64_t Offset) {
if (isC99VarArgs) MI->setIsC99Varargs();
if (isGNUVarArgs) MI->setIsGNUVarargs();
MI->setArgumentList(MacroArgs.data(), MacroArgs.size(),
- PP.getPreprocessorAllocator());
+ PP->getPreprocessorAllocator());
}
// Finally, install the macro.
- PP.setMacroInfo(II, MI);
+ PP->setMacroInfo(II, MI);
// Remember that we saw this macro last so that we add the tokens that
// form its body to it.
@@ -1092,11 +1217,10 @@ PCHReader::ReadPCHBlock() {
return IgnorePCH;
}
- std::string TargetTriple(BlobStart, BlobLen);
- if (TargetTriple != PP.getTargetInfo().getTargetTriple()) {
- Diag(diag::warn_pch_target_triple)
- << TargetTriple << PP.getTargetInfo().getTargetTriple();
- return IgnorePCH;
+ if (Listener) {
+ std::string TargetTriple(BlobStart, BlobLen);
+ if (Listener->ReadTargetTriple(TargetTriple))
+ return IgnorePCH;
}
break;
}
@@ -1109,7 +1233,8 @@ PCHReader::ReadPCHBlock() {
(const unsigned char *)IdentifierTableData + Record[0],
(const unsigned char *)IdentifierTableData,
PCHIdentifierLookupTrait(*this));
- PP.getIdentifierTable().setExternalIdentifierLookup(this);
+ if (PP)
+ PP->getIdentifierTable().setExternalIdentifierLookup(this);
}
break;
@@ -1120,7 +1245,8 @@ PCHReader::ReadPCHBlock() {
}
IdentifierOffsets = (const uint32_t *)BlobStart;
IdentifiersLoaded.resize(Record[0]);
- PP.getHeaderSearchInfo().SetExternalLookup(this);
+ if (PP)
+ PP->getHeaderSearchInfo().SetExternalLookup(this);
break;
case pch::EXTERNAL_DEFINITIONS:
@@ -1176,14 +1302,14 @@ PCHReader::ReadPCHBlock() {
break;
case pch::PP_COUNTER_VALUE:
- if (!Record.empty())
- PP.setCounterValue(Record[0]);
+ if (!Record.empty() && Listener)
+ Listener->ReadCounter(Record[0]);
break;
case pch::SOURCE_LOCATION_OFFSETS:
SLocOffsets = (const uint32_t *)BlobStart;
TotalNumSLocEntries = Record[0];
- PP.getSourceManager().PreallocateSLocEntries(this,
+ SourceMgr.PreallocateSLocEntries(this,
TotalNumSLocEntries,
Record[1]);
break;
@@ -1197,7 +1323,7 @@ PCHReader::ReadPCHBlock() {
break;
case pch::STAT_CACHE:
- PP.getFileManager().setStatCache(
+ FileMgr.setStatCache(
new PCHStatCache((const unsigned char *)BlobStart + Record[0],
(const unsigned char *)BlobStart,
NumStatHits, NumStatMisses));
@@ -1287,10 +1413,10 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
// Clear out any preallocated source location entries, so that
// the source manager does not try to resolve them later.
- PP.getSourceManager().ClearPreallocatedSLocEntries();
+ SourceMgr.ClearPreallocatedSLocEntries();
// Remove the stat cache.
- PP.getFileManager().setStatCache(0);
+ FileMgr.setStatCache(0);
return IgnorePCH;
}
@@ -1303,71 +1429,82 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
break;
}
}
-
- // Load the translation unit declaration
- if (Context)
- ReadDeclRecord(DeclOffsets[0], 0);
// Check the predefines buffer.
if (CheckPredefinesBuffer(PCHPredefines, PCHPredefinesLen,
PCHPredefinesBufferID))
return IgnorePCH;
- // Initialization of builtins and library builtins occurs before the
- // PCH file is read, so there may be some identifiers that were
- // loaded into the IdentifierTable before we intercepted the
- // creation of identifiers. Iterate through the list of known
- // identifiers and determine whether we have to establish
- // preprocessor definitions or top-level identifier declaration
- // chains for those identifiers.
- //
- // We copy the IdentifierInfo pointers to a small vector first,
- // since de-serializing declarations or macro definitions can add
- // new entries into the identifier table, invalidating the
- // iterators.
- llvm::SmallVector<IdentifierInfo *, 128> Identifiers;
- for (IdentifierTable::iterator Id = PP.getIdentifierTable().begin(),
- IdEnd = PP.getIdentifierTable().end();
- Id != IdEnd; ++Id)
- Identifiers.push_back(Id->second);
- PCHIdentifierLookupTable *IdTable
- = (PCHIdentifierLookupTable *)IdentifierLookupTable;
- for (unsigned I = 0, N = Identifiers.size(); I != N; ++I) {
- IdentifierInfo *II = Identifiers[I];
- // Look in the on-disk hash table for an entry for
- PCHIdentifierLookupTrait Info(*this, II);
- std::pair<const char*, unsigned> Key(II->getName(), II->getLength());
- PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key, &Info);
- if (Pos == IdTable->end())
- continue;
-
- // Dereferencing the iterator has the effect of populating the
- // IdentifierInfo node with the various declarations it needs.
- (void)*Pos;
+ if (PP) {
+ // Initialization of builtins and library builtins occurs before the
+ // PCH file is read, so there may be some identifiers that were
+ // loaded into the IdentifierTable before we intercepted the
+ // creation of identifiers. Iterate through the list of known
+ // identifiers and determine whether we have to establish
+ // preprocessor definitions or top-level identifier declaration
+ // chains for those identifiers.
+ //
+ // We copy the IdentifierInfo pointers to a small vector first,
+ // since de-serializing declarations or macro definitions can add
+ // new entries into the identifier table, invalidating the
+ // iterators.
+ llvm::SmallVector<IdentifierInfo *, 128> Identifiers;
+ for (IdentifierTable::iterator Id = PP->getIdentifierTable().begin(),
+ IdEnd = PP->getIdentifierTable().end();
+ Id != IdEnd; ++Id)
+ Identifiers.push_back(Id->second);
+ PCHIdentifierLookupTable *IdTable
+ = (PCHIdentifierLookupTable *)IdentifierLookupTable;
+ for (unsigned I = 0, N = Identifiers.size(); I != N; ++I) {
+ IdentifierInfo *II = Identifiers[I];
+ // Look in the on-disk hash table for an entry for
+ PCHIdentifierLookupTrait Info(*this, II);
+ std::pair<const char*, unsigned> Key(II->getName(), II->getLength());
+ PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key, &Info);
+ if (Pos == IdTable->end())
+ continue;
+
+ // Dereferencing the iterator has the effect of populating the
+ // IdentifierInfo node with the various declarations it needs.
+ (void)*Pos;
+ }
}
- // Load the special types.
- if (Context) {
- Context->setBuiltinVaListType(
- GetType(SpecialTypes[pch::SPECIAL_TYPE_BUILTIN_VA_LIST]));
- if (unsigned Id = SpecialTypes[pch::SPECIAL_TYPE_OBJC_ID])
- Context->setObjCIdType(GetType(Id));
- if (unsigned Sel = SpecialTypes[pch::SPECIAL_TYPE_OBJC_SELECTOR])
- Context->setObjCSelType(GetType(Sel));
- if (unsigned Proto = SpecialTypes[pch::SPECIAL_TYPE_OBJC_PROTOCOL])
- Context->setObjCProtoType(GetType(Proto));
- if (unsigned Class = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS])
- Context->setObjCClassType(GetType(Class));
- if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_CF_CONSTANT_STRING])
- Context->setCFConstantStringType(GetType(String));
- if (unsigned FastEnum
- = SpecialTypes[pch::SPECIAL_TYPE_OBJC_FAST_ENUMERATION_STATE])
- Context->setObjCFastEnumerationStateType(GetType(FastEnum));
- }
+ if (Context)
+ InitializeContext(*Context);
return Success;
}
+void PCHReader::InitializeContext(ASTContext &Ctx) {
+ Context = &Ctx;
+ assert(Context && "Passed null context!");
+
+ assert(PP && "Forgot to set Preprocessor ?");
+ PP->getIdentifierTable().setExternalIdentifierLookup(this);
+ PP->getHeaderSearchInfo().SetExternalLookup(this);
+
+ // Load the translation unit declaration
+ ReadDeclRecord(DeclOffsets[0], 0);
+
+ // Load the special types.
+ Context->setBuiltinVaListType(
+ GetType(SpecialTypes[pch::SPECIAL_TYPE_BUILTIN_VA_LIST]));
+ if (unsigned Id = SpecialTypes[pch::SPECIAL_TYPE_OBJC_ID])
+ Context->setObjCIdType(GetType(Id));
+ if (unsigned Sel = SpecialTypes[pch::SPECIAL_TYPE_OBJC_SELECTOR])
+ Context->setObjCSelType(GetType(Sel));
+ if (unsigned Proto = SpecialTypes[pch::SPECIAL_TYPE_OBJC_PROTOCOL])
+ Context->setObjCProtoType(GetType(Proto));
+ if (unsigned Class = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS])
+ Context->setObjCClassType(GetType(Class));
+ if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_CF_CONSTANT_STRING])
+ Context->setCFConstantStringType(GetType(String));
+ if (unsigned FastEnum
+ = SpecialTypes[pch::SPECIAL_TYPE_OBJC_FAST_ENUMERATION_STATE])
+ Context->setObjCFastEnumerationStateType(GetType(FastEnum));
+}
+
/// \brief Retrieve the name of the original source file name
/// directly from the PCH file, without actually loading the PCH
/// file.
@@ -1465,73 +1602,60 @@ std::string PCHReader::getOriginalSourceFile(const std::string &PCHFileName) {
/// \returns true if the PCH file is unacceptable, false otherwise.
bool PCHReader::ParseLanguageOptions(
const llvm::SmallVectorImpl<uint64_t> &Record) {
- const LangOptions &LangOpts = PP.getLangOptions();
-#define PARSE_LANGOPT_BENIGN(Option) ++Idx
-#define PARSE_LANGOPT_IMPORTANT(Option, DiagID) \
- if (Record[Idx] != LangOpts.Option) { \
- Diag(DiagID) << (unsigned)Record[Idx] << LangOpts.Option; \
- return true; \
- } \
- ++Idx
-
- unsigned Idx = 0;
- PARSE_LANGOPT_BENIGN(Trigraphs);
- PARSE_LANGOPT_BENIGN(BCPLComment);
- PARSE_LANGOPT_BENIGN(DollarIdents);
- PARSE_LANGOPT_BENIGN(AsmPreprocessor);
- PARSE_LANGOPT_IMPORTANT(GNUMode, diag::warn_pch_gnu_extensions);
- PARSE_LANGOPT_BENIGN(ImplicitInt);
- PARSE_LANGOPT_BENIGN(Digraphs);
- PARSE_LANGOPT_BENIGN(HexFloats);
- PARSE_LANGOPT_IMPORTANT(C99, diag::warn_pch_c99);
- PARSE_LANGOPT_IMPORTANT(Microsoft, diag::warn_pch_microsoft_extensions);
- PARSE_LANGOPT_IMPORTANT(CPlusPlus, diag::warn_pch_cplusplus);
- PARSE_LANGOPT_IMPORTANT(CPlusPlus0x, diag::warn_pch_cplusplus0x);
- PARSE_LANGOPT_BENIGN(CXXOperatorName);
- PARSE_LANGOPT_IMPORTANT(ObjC1, diag::warn_pch_objective_c);
- PARSE_LANGOPT_IMPORTANT(ObjC2, diag::warn_pch_objective_c2);
- PARSE_LANGOPT_IMPORTANT(ObjCNonFragileABI, diag::warn_pch_nonfragile_abi);
- PARSE_LANGOPT_BENIGN(PascalStrings);
- PARSE_LANGOPT_BENIGN(WritableStrings);
- PARSE_LANGOPT_IMPORTANT(LaxVectorConversions,
- diag::warn_pch_lax_vector_conversions);
- PARSE_LANGOPT_IMPORTANT(Exceptions, diag::warn_pch_exceptions);
- PARSE_LANGOPT_IMPORTANT(NeXTRuntime, diag::warn_pch_objc_runtime);
- PARSE_LANGOPT_IMPORTANT(Freestanding, diag::warn_pch_freestanding);
- PARSE_LANGOPT_IMPORTANT(NoBuiltin, diag::warn_pch_builtins);
- PARSE_LANGOPT_IMPORTANT(ThreadsafeStatics,
- diag::warn_pch_thread_safe_statics);
- PARSE_LANGOPT_IMPORTANT(Blocks, diag::warn_pch_blocks);
- PARSE_LANGOPT_BENIGN(EmitAllDecls);
- PARSE_LANGOPT_IMPORTANT(MathErrno, diag::warn_pch_math_errno);
- PARSE_LANGOPT_IMPORTANT(OverflowChecking, diag::warn_pch_overflow_checking);
- PARSE_LANGOPT_IMPORTANT(HeinousExtensions,
- diag::warn_pch_heinous_extensions);
- // FIXME: Most of the options below are benign if the macro wasn't
- // used. Unfortunately, this means that a PCH compiled without
- // optimization can't be used with optimization turned on, even
- // though the only thing that changes is whether __OPTIMIZE__ was
- // defined... but if __OPTIMIZE__ never showed up in the header, it
- // doesn't matter. We could consider making this some special kind
- // of check.
- PARSE_LANGOPT_IMPORTANT(Optimize, diag::warn_pch_optimize);
- PARSE_LANGOPT_IMPORTANT(OptimizeSize, diag::warn_pch_optimize_size);
- PARSE_LANGOPT_IMPORTANT(Static, diag::warn_pch_static);
- PARSE_LANGOPT_IMPORTANT(PICLevel, diag::warn_pch_pic_level);
- PARSE_LANGOPT_IMPORTANT(GNUInline, diag::warn_pch_gnu_inline);
- PARSE_LANGOPT_IMPORTANT(NoInline, diag::warn_pch_no_inline);
- PARSE_LANGOPT_IMPORTANT(AccessControl, diag::warn_pch_access_control);
- PARSE_LANGOPT_IMPORTANT(CharIsSigned, diag::warn_pch_char_signed);
- if ((LangOpts.getGCMode() != 0) != (Record[Idx] != 0)) {
- Diag(diag::warn_pch_gc_mode)
- << (unsigned)Record[Idx] << LangOpts.getGCMode();
- return true;
+ if (Listener) {
+ LangOptions LangOpts;
+
+ #define PARSE_LANGOPT(Option) \
+ LangOpts.Option = Record[Idx]; \
+ ++Idx
+
+ unsigned Idx = 0;
+ PARSE_LANGOPT(Trigraphs);
+ PARSE_LANGOPT(BCPLComment);
+ PARSE_LANGOPT(DollarIdents);
+ PARSE_LANGOPT(AsmPreprocessor);
+ PARSE_LANGOPT(GNUMode);
+ PARSE_LANGOPT(ImplicitInt);
+ PARSE_LANGOPT(Digraphs);
+ PARSE_LANGOPT(HexFloats);
+ PARSE_LANGOPT(C99);
+ PARSE_LANGOPT(Microsoft);
+ PARSE_LANGOPT(CPlusPlus);
+ PARSE_LANGOPT(CPlusPlus0x);
+ PARSE_LANGOPT(CXXOperatorNames);
+ PARSE_LANGOPT(ObjC1);
+ PARSE_LANGOPT(ObjC2);
+ PARSE_LANGOPT(ObjCNonFragileABI);
+ PARSE_LANGOPT(PascalStrings);
+ PARSE_LANGOPT(WritableStrings);
+ PARSE_LANGOPT(LaxVectorConversions);
+ PARSE_LANGOPT(Exceptions);
+ PARSE_LANGOPT(NeXTRuntime);
+ PARSE_LANGOPT(Freestanding);
+ PARSE_LANGOPT(NoBuiltin);
+ PARSE_LANGOPT(ThreadsafeStatics);
+ PARSE_LANGOPT(Blocks);
+ PARSE_LANGOPT(EmitAllDecls);
+ PARSE_LANGOPT(MathErrno);
+ PARSE_LANGOPT(OverflowChecking);
+ PARSE_LANGOPT(HeinousExtensions);
+ PARSE_LANGOPT(Optimize);
+ PARSE_LANGOPT(OptimizeSize);
+ PARSE_LANGOPT(Static);
+ PARSE_LANGOPT(PICLevel);
+ PARSE_LANGOPT(GNUInline);
+ PARSE_LANGOPT(NoInline);
+ PARSE_LANGOPT(AccessControl);
+ PARSE_LANGOPT(CharIsSigned);
+ LangOpts.setGCMode((LangOptions::GCMode)Record[Idx]);
+ ++Idx;
+ LangOpts.setVisibilityMode((LangOptions::VisibilityMode)Record[Idx]);
+ ++Idx;
+ PARSE_LANGOPT(InstantiationDepth);
+ #undef PARSE_LANGOPT
+
+ return Listener->ReadLanguageOptions(LangOpts);
}
- ++Idx;
- PARSE_LANGOPT_BENIGN(getVisibilityMode());
- PARSE_LANGOPT_BENIGN(InstantiationDepth);
-#undef PARSE_LANGOPT_IRRELEVANT
-#undef PARSE_LANGOPT_BENIGN
return false;
}
@@ -1722,13 +1846,15 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
return Context->getObjCQualifiedInterfaceType(ItfD, Protos.data(), NumProtos);
}
- case pch::TYPE_OBJC_QUALIFIED_ID: {
+ case pch::TYPE_OBJC_OBJECT_POINTER: {
unsigned Idx = 0;
+ ObjCInterfaceDecl *ItfD =
+ cast_or_null<ObjCInterfaceDecl>(GetDecl(Record[Idx++]));
unsigned NumProtos = Record[Idx++];
llvm::SmallVector<ObjCProtocolDecl*, 4> Protos;
for (unsigned I = 0; I != NumProtos; ++I)
Protos.push_back(cast<ObjCProtocolDecl>(GetDecl(Record[Idx++])));
- return Context->getObjCQualifiedIdType(Protos.data(), NumProtos);
+ return Context->getObjCObjectPointerType(ItfD, Protos.data(), NumProtos);
}
}
// Suppress a GCC warning
@@ -2056,6 +2182,7 @@ IdentifierInfo *PCHReader::DecodeIdentifierInfo(unsigned ID) {
return 0;
}
+ assert(PP && "Forgot to set Preprocessor ?");
if (!IdentifiersLoaded[ID - 1]) {
uint32_t Offset = IdentifierOffsets[ID - 1];
const char *Str = IdentifierTableData + Offset;
@@ -2067,7 +2194,7 @@ IdentifierInfo *PCHReader::DecodeIdentifierInfo(unsigned ID) {
unsigned StrLen = (((unsigned) StrLenPtr[0])
| (((unsigned) StrLenPtr[1]) << 8)) - 1;
IdentifiersLoaded[ID - 1]
- = &PP.getIdentifierTable().get(Str, Str + StrLen);
+ = &PP->getIdentifierTable().get(Str, Str + StrLen);
}
return IdentifiersLoaded[ID - 1];
@@ -2170,15 +2297,14 @@ DiagnosticBuilder PCHReader::Diag(unsigned DiagID) {
}
DiagnosticBuilder PCHReader::Diag(SourceLocation Loc, unsigned DiagID) {
- return PP.getDiagnostics().Report(FullSourceLoc(Loc,
- PP.getSourceManager()),
- DiagID);
+ return Diags.Report(FullSourceLoc(Loc, SourceMgr), DiagID);
}
/// \brief Retrieve the identifier table associated with the
/// preprocessor.
IdentifierTable &PCHReader::getIdentifierTable() {
- return PP.getIdentifierTable();
+ assert(PP && "Forgot to set Preprocessor ?");
+ return PP->getIdentifierTable();
}
/// \brief Record that the given ID maps to the given switch-case
diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp
index 6856623e60c9..3dd84c7b08ad 100644
--- a/lib/Frontend/PCHReaderDecl.cpp
+++ b/lib/Frontend/PCHReaderDecl.cpp
@@ -80,8 +80,9 @@ void PCHDeclReader::VisitDecl(Decl *D) {
D->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
D->setInvalidDecl(Record[Idx++]);
if (Record[Idx++])
- D->addAttr(Reader.ReadAttributes());
+ D->addAttr(*Reader.getContext(), Reader.ReadAttributes());
D->setImplicit(Record[Idx++]);
+ D->setUsed(Record[Idx++]);
D->setAccess((AccessSpecifier)Record[Idx++]);
}
@@ -156,6 +157,7 @@ void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
FD->setHasWrittenPrototype(Record[Idx++]);
FD->setDeleted(Record[Idx++]);
FD->setTypeSpecStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ FD->setLocEnd(SourceLocation::getFromRawEncoding(Record[Idx++]));
// FIXME: C++ TemplateOrInstantiation
unsigned NumParams = Record[Idx++];
llvm::SmallVector<ParmVarDecl *, 16> Params;
diff --git a/lib/Frontend/PCHReaderStmt.cpp b/lib/Frontend/PCHReaderStmt.cpp
index e6871e3a0eb6..d09638806169 100644
--- a/lib/Frontend/PCHReaderStmt.cpp
+++ b/lib/Frontend/PCHReaderStmt.cpp
@@ -667,6 +667,7 @@ unsigned PCHStmtReader::VisitBlockDeclRefExpr(BlockDeclRefExpr *E) {
E->setDecl(cast<ValueDecl>(Reader.GetDecl(Record[Idx++])));
E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
E->setByRef(Record[Idx++]);
+ E->setConstQualAdded(Record[Idx++]);
return 0;
}
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
index 765fecbf852f..3b1eb080f229 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -229,12 +229,14 @@ PCHTypeWriter::VisitObjCQualifiedInterfaceType(
Code = pch::TYPE_OBJC_QUALIFIED_INTERFACE;
}
-void PCHTypeWriter::VisitObjCQualifiedIdType(const ObjCQualifiedIdType *T) {
+void
+PCHTypeWriter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
+ Writer.AddDeclRef(T->getDecl(), Record);
Record.push_back(T->getNumProtocols());
- for (ObjCQualifiedIdType::qual_iterator I = T->qual_begin(),
+ for (ObjCInterfaceType::qual_iterator I = T->qual_begin(),
E = T->qual_end(); I != E; ++I)
Writer.AddDeclRef(*I, Record);
- Code = pch::TYPE_OBJC_QUALIFIED_ID;
+ Code = pch::TYPE_OBJC_OBJECT_POINTER;
}
//===----------------------------------------------------------------------===//
@@ -407,7 +409,7 @@ void PCHWriter::WriteBlockInfoBlock() {
RECORD(TYPE_ENUM);
RECORD(TYPE_OBJC_INTERFACE);
RECORD(TYPE_OBJC_QUALIFIED_INTERFACE);
- RECORD(TYPE_OBJC_QUALIFIED_ID);
+ RECORD(TYPE_OBJC_OBJECT_POINTER);
// Statements and Exprs can occur in the Types block.
AddStmtsExprs(Stream, Record);
diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp
index 67346619978e..44da4d72f2df 100644
--- a/lib/Frontend/PCHWriterDecl.cpp
+++ b/lib/Frontend/PCHWriterDecl.cpp
@@ -82,6 +82,7 @@ void PCHDeclWriter::VisitDecl(Decl *D) {
Record.push_back(D->isInvalidDecl());
Record.push_back(D->hasAttrs());
Record.push_back(D->isImplicit());
+ Record.push_back(D->isUsed());
Record.push_back(D->getAccess());
}
@@ -156,6 +157,7 @@ void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
Record.push_back(D->hasWrittenPrototype());
Record.push_back(D->isDeleted());
Writer.AddSourceLocation(D->getTypeSpecStartLoc(), Record);
+ Writer.AddSourceLocation(D->getLocEnd(), Record);
// FIXME: C++ TemplateOrInstantiation
Record.push_back(D->param_size());
for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end();
@@ -360,6 +362,7 @@ void PCHDeclWriter::VisitParmVarDecl(ParmVarDecl *D) {
// know are true of all PARM_VAR_DECLs.
if (!D->hasAttrs() &&
!D->isImplicit() &&
+ !D->isUsed() &&
D->getAccess() == AS_none &&
D->getStorageClass() == 0 &&
!D->hasCXXDirectInitializer() && // Can params have this ever?
@@ -434,6 +437,7 @@ void PCHWriter::WriteDeclsBlockAbbrevs() {
Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl (!?)
Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs
Abv->Add(BitCodeAbbrevOp(0)); // isImplicit
+ Abv->Add(BitCodeAbbrevOp(0)); // isUsed
Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier
// NamedDecl
@@ -516,7 +520,7 @@ void PCHWriter::WriteDeclsBlock(ASTContext &Context) {
// If the declaration had any attributes, write them now.
if (D->hasAttrs())
- WriteAttributeRecord(D->getAttrs());
+ WriteAttributeRecord(D->getAttrs(Context));
// Flush any expressions that were written as part of this declaration.
FlushStmts();
diff --git a/lib/Frontend/PCHWriterStmt.cpp b/lib/Frontend/PCHWriterStmt.cpp
index 73dea1061c28..c63c03c8823f 100644
--- a/lib/Frontend/PCHWriterStmt.cpp
+++ b/lib/Frontend/PCHWriterStmt.cpp
@@ -602,6 +602,7 @@ void PCHStmtWriter::VisitBlockDeclRefExpr(BlockDeclRefExpr *E) {
Writer.AddDeclRef(E->getDecl(), Record);
Writer.AddSourceLocation(E->getLocation(), Record);
Record.push_back(E->isByRef());
+ Record.push_back(E->isConstQualAdded());
Code = pch::EXPR_BLOCK_DECL_REF;
}
diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp
index 89d099caf8a9..d63d9cbba989 100644
--- a/lib/Frontend/PrintPreprocessedOutput.cpp
+++ b/lib/Frontend/PrintPreprocessedOutput.cpp
@@ -123,6 +123,8 @@ public:
}
void WriteLineInfo(unsigned LineNo, const char *Extra=0, unsigned ExtraLen=0);
+ void HandleNewlinesInToken(const char *TokStr, unsigned Len);
+
/// MacroDefined - This hook is called whenever a macro definition is seen.
void MacroDefined(const IdentifierInfo *II, const MacroInfo *MI);
@@ -327,6 +329,29 @@ bool PrintPPOutputPPCallbacks::HandleFirstTokOnLine(Token &Tok) {
return true;
}
+void PrintPPOutputPPCallbacks::HandleNewlinesInToken(const char *TokStr,
+ unsigned Len) {
+ unsigned NumNewlines = 0;
+ for (; Len; --Len, ++TokStr) {
+ if (*TokStr != '\n' &&
+ *TokStr != '\r')
+ continue;
+
+ ++NumNewlines;
+
+ // If we have \n\r or \r\n, skip both and count as one line.
+ if (Len != 1 &&
+ (TokStr[1] == '\n' || TokStr[1] == '\r') &&
+ TokStr[0] != TokStr[1])
+ ++TokStr, --Len;
+ }
+
+ if (NumNewlines == 0) return;
+
+ CurLine += NumNewlines;
+}
+
+
namespace {
struct UnknownPragmaHandler : public PragmaHandler {
const char *Prefix;
@@ -382,9 +407,19 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok,
const char *TokPtr = Buffer;
unsigned Len = PP.getSpelling(Tok, TokPtr);
OS.write(TokPtr, Len);
+
+ // Tokens that can contain embedded newlines need to adjust our current
+ // line number.
+ if (Tok.getKind() == tok::comment)
+ Callbacks->HandleNewlinesInToken(TokPtr, Len);
} else {
std::string S = PP.getSpelling(Tok);
OS.write(&S[0], S.size());
+
+ // Tokens that can contain embedded newlines need to adjust our current
+ // line number.
+ if (Tok.getKind() == tok::comment)
+ Callbacks->HandleNewlinesInToken(&S[0], S.size());
}
Callbacks->SetEmittedTokensOnThisLine();
diff --git a/lib/Frontend/RewriteBlocks.cpp b/lib/Frontend/RewriteBlocks.cpp
index 8393574d1e66..d20d5cd152c4 100644
--- a/lib/Frontend/RewriteBlocks.cpp
+++ b/lib/Frontend/RewriteBlocks.cpp
@@ -132,7 +132,7 @@ public:
if (const PointerType *PT = OCT->getAsPointerType()) {
if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||
- isa<ObjCQualifiedIdType>(PT->getPointeeType()))
+ PT->getPointeeType()->isObjCQualifiedIdType())
return true;
}
return false;
diff --git a/lib/Frontend/RewriteObjC.cpp b/lib/Frontend/RewriteObjC.cpp
index f382704014f7..dce271070e03 100644
--- a/lib/Frontend/RewriteObjC.cpp
+++ b/lib/Frontend/RewriteObjC.cpp
@@ -356,7 +356,7 @@ namespace {
if (const PointerType *PT = OCT->getAsPointerType()) {
if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||
- isa<ObjCQualifiedIdType>(PT->getPointeeType()))
+ PT->getPointeeType()->isObjCQualifiedIdType())
return true;
}
return false;
diff --git a/lib/Frontend/StmtXML.cpp b/lib/Frontend/StmtXML.cpp
index c861881486b3..6ba0a28c7d20 100644
--- a/lib/Frontend/StmtXML.cpp
+++ b/lib/Frontend/StmtXML.cpp
@@ -28,8 +28,31 @@ namespace {
class VISIBILITY_HIDDEN StmtXML : public StmtVisitor<StmtXML> {
DocumentXML& Doc;
- static const char *getOpcodeStr(UnaryOperator::Opcode Op);
- static const char *getOpcodeStr(BinaryOperator::Opcode Op);
+ //static const char *getOpcodeStr(UnaryOperator::Opcode Op);
+ //static const char *getOpcodeStr(BinaryOperator::Opcode Op);
+
+
+ void addSpecialAttribute(const char* pName, StringLiteral* Str)
+ {
+ Doc.addAttribute(pName, Doc.escapeString(Str->getStrData(), Str->getByteLength()));
+ }
+
+ void addSpecialAttribute(const char* pName, SizeOfAlignOfExpr* S)
+ {
+ if (S->isArgumentType())
+ {
+ Doc.addAttribute(pName, S->getArgumentType());
+ }
+ }
+
+ void addSpecialAttribute(const char* pName, CXXTypeidExpr* S)
+ {
+ if (S->isTypeOperand())
+ {
+ Doc.addAttribute(pName, S->getTypeOperand());
+ }
+ }
+
public:
StmtXML(DocumentXML& doc)
@@ -39,12 +62,21 @@ namespace {
void DumpSubTree(Stmt *S) {
if (S)
{
- Doc.addSubNode(S->getStmtClassName());
- Doc.addLocationRange(S->getSourceRange());
- if (DeclStmt* DS = dyn_cast<DeclStmt>(S)) {
- VisitDeclStmt(DS);
- } else {
- Visit(S);
+ Visit(S);
+ if (DeclStmt* DS = dyn_cast<DeclStmt>(S))
+ {
+ for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end();
+ DI != DE; ++DI)
+ {
+ Doc.PrintDecl(*DI);
+ }
+ }
+ else
+ {
+ if (CXXConditionDeclExpr* CCDE = dyn_cast<CXXConditionDeclExpr>(S))
+ {
+ Doc.PrintDecl(CCDE->getVarDecl());
+ }
for (Stmt::child_iterator i = S->child_begin(), e = S->child_end(); i != e; ++i)
{
DumpSubTree(*i);
@@ -56,17 +88,46 @@ namespace {
}
}
- void DumpTypeExpr(const QualType& T)
- {
- Doc.addSubNode("TypeExpr");
- Doc.addTypeAttribute(T);
- Doc.toParent();
- }
- void DumpExpr(const Expr *Node) {
- Doc.addTypeAttribute(Node->getType());
- }
+#define NODE_XML( CLASS, NAME ) \
+ void Visit##CLASS(CLASS* S) \
+ { \
+ typedef CLASS tStmtType; \
+ Doc.addSubNode(NAME);
+
+#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, S->FN);
+#define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type")
+#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, S->FN);
+#define ATTRIBUTE_SPECIAL_XML( FN, NAME ) addSpecialAttribute(NAME, S);
+#define ATTRIBUTE_FILE_LOCATION_XML Doc.addLocationRange(S->getSourceRange());
+
+#define ATTRIBUTE_ENUM_XML( FN, NAME ) \
+ { \
+ const char* pAttributeName = NAME; \
+ const bool optional = false; \
+ switch (S->FN) { \
+ default: assert(0 && "unknown enum value");
+
+#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \
+ { \
+ const char* pAttributeName = NAME; \
+ const bool optional = true; \
+ switch (S->FN) { \
+ default: assert(0 && "unknown enum value");
+
+#define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break;
+#define END_ENUM_XML } }
+#define END_NODE_XML }
+
+#define ID_ATTRIBUTE_XML Doc.addAttribute("id", S);
+#define SUB_NODE_XML( CLASS )
+#define SUB_NODE_SEQUENCE_XML( CLASS )
+#define SUB_NODE_OPT_XML( CLASS )
+
+#include "clang/Frontend/StmtXML.def"
+
+#if (0)
// Stmts.
void VisitStmt(Stmt *Node);
void VisitDeclStmt(DeclStmt *Node);
@@ -105,13 +166,14 @@ namespace {
void VisitObjCKVCRefExpr(ObjCKVCRefExpr *Node);
void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node);
void VisitObjCSuperExpr(ObjCSuperExpr *Node);
+#endif
};
}
//===----------------------------------------------------------------------===//
// Stmt printing methods.
//===----------------------------------------------------------------------===//
-
+#if (0)
void StmtXML::VisitStmt(Stmt *Node)
{
// nothing special to do
@@ -396,7 +458,7 @@ void StmtXML::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
if (Node->isFreeIvar())
Doc.addAttribute("isFreeIvar", "1");
}
-
+#endif
//===----------------------------------------------------------------------===//
// Stmt method implementations
//===----------------------------------------------------------------------===//
diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp
index 6699c65f52de..d4c7e0f6f330 100644
--- a/lib/Frontend/TextDiagnosticPrinter.cpp
+++ b/lib/Frontend/TextDiagnosticPrinter.cpp
@@ -640,9 +640,18 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
SourceLocation B = Info.getRange(i).getBegin();
SourceLocation E = Info.getRange(i).getEnd();
- std::pair<FileID, unsigned> BInfo=SM.getDecomposedInstantiationLoc(B);
-
+ B = SM.getInstantiationLoc(B);
E = SM.getInstantiationLoc(E);
+
+ // If the End location and the start location are the same and are a
+ // macro location, then the range was something that came from a macro
+ // expansion or _Pragma. If this is an object-like macro, the best we
+ // can do is to highlight the range. If this is a function-like
+ // macro, we'd also like to highlight the arguments.
+ if (B == E && Info.getRange(i).getEnd().isMacroID())
+ E = SM.getInstantiationRange(Info.getRange(i).getEnd()).second;
+
+ std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(B);
std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(E);
// If the start or end of the range is in another file, just discard
diff --git a/lib/Frontend/TypeXML.cpp b/lib/Frontend/TypeXML.cpp
new file mode 100644
index 000000000000..f32fbbd2413b
--- /dev/null
+++ b/lib/Frontend/TypeXML.cpp
@@ -0,0 +1,127 @@
+//===--- DocumentXML.cpp - XML document for ASTs --------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the XML document class, which provides the means to
+// dump out the AST in a XML form that exposes type details and other fields.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/DocumentXML.h"
+#include "clang/AST/TypeVisitor.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/Decl.h"
+
+namespace clang {
+ namespace XML {
+ namespace {
+
+//---------------------------------------------------------
+class TypeWriter : public TypeVisitor<TypeWriter>
+{
+ DocumentXML& Doc;
+
+public:
+ TypeWriter(DocumentXML& doc) : Doc(doc) {}
+
+#define NODE_XML( CLASS, NAME ) \
+ void Visit##CLASS(CLASS* T) \
+ { \
+ Doc.addSubNode(NAME);
+
+#define ID_ATTRIBUTE_XML // done by the Document class itself
+#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, T->FN);
+#define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type")
+#define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context")
+#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, T->FN);
+
+#define ATTRIBUTE_ENUM_XML( FN, NAME ) \
+ { \
+ const char* pAttributeName = NAME; \
+ const bool optional = false; \
+ switch (T->FN) { \
+ default: assert(0 && "unknown enum value");
+
+#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \
+ { \
+ const char* pAttributeName = NAME; \
+ const bool optional = true; \
+ switch (T->FN) { \
+ default: assert(0 && "unknown enum value");
+
+#define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break;
+#define END_ENUM_XML } }
+#define END_NODE_XML }
+
+#include "clang/Frontend/TypeXML.def"
+
+};
+
+//---------------------------------------------------------
+ } // anon clang
+ } // NS XML
+
+//---------------------------------------------------------
+class DocumentXML::TypeAdder : public TypeVisitor<DocumentXML::TypeAdder>
+{
+ DocumentXML& Doc;
+
+ void addIfType(const Type* pType)
+ {
+ Doc.addTypeRecursively(pType);
+ }
+
+ void addIfType(const QualType& pType)
+ {
+ Doc.addTypeRecursively(pType);
+ }
+
+ template<class T> void addIfType(T) {}
+
+public:
+ TypeAdder(DocumentXML& doc) : Doc(doc) {}
+
+#define NODE_XML( CLASS, NAME ) \
+ void Visit##CLASS(CLASS* T) \
+ {
+
+#define ID_ATTRIBUTE_XML
+#define TYPE_ATTRIBUTE_XML( FN ) Doc.addTypeRecursively(T->FN);
+#define CONTEXT_ATTRIBUTE_XML( FN )
+#define ATTRIBUTE_XML( FN, NAME ) addIfType(T->FN);
+#define ATTRIBUTE_OPT_XML( FN, NAME )
+#define ATTRIBUTE_ENUM_XML( FN, NAME )
+#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME )
+#define ENUM_XML( VALUE, NAME )
+#define END_ENUM_XML
+#define END_NODE_XML }
+
+#include "clang/Frontend/TypeXML.def"
+};
+
+//---------------------------------------------------------
+void DocumentXML::addParentTypes(const Type* pType)
+{
+ TypeAdder(*this).Visit(const_cast<Type*>(pType));
+}
+
+//---------------------------------------------------------
+void DocumentXML::writeTypeToXML(const Type* pType)
+{
+ XML::TypeWriter(*this).Visit(const_cast<Type*>(pType));
+}
+
+//---------------------------------------------------------
+void DocumentXML::writeTypeToXML(const QualType& pType)
+{
+ XML::TypeWriter(*this).VisitQualType(const_cast<QualType*>(&pType));
+}
+
+//---------------------------------------------------------
+} // NS clang
+
diff --git a/lib/Headers/CMakeLists.txt b/lib/Headers/CMakeLists.txt
index e44c37aabc8f..318685a89949 100644
--- a/lib/Headers/CMakeLists.txt
+++ b/lib/Headers/CMakeLists.txt
@@ -15,7 +15,12 @@ set(files
xmmintrin.h)
#FIXME: Centralize Clang version info
-set(output_dir ${LLVM_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib/clang/1.0/include)
+if (MSVC_IDE OR XCODE)
+ set(output_dir ${LLVM_BINARY_DIR}/bin/lib/clang/1.0/include)
+else ()
+ set(output_dir ${LLVM_BINARY_DIR}/lib/clang/1.0/include)
+endif ()
+
foreach( f ${files} )
set( src ${CMAKE_CURRENT_SOURCE_DIR}/${f} )
diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp
index 129fa1ae35fa..9023b11022b1 100644
--- a/lib/Lex/HeaderSearch.cpp
+++ b/lib/Lex/HeaderSearch.cpp
@@ -215,9 +215,7 @@ const FileEntry *HeaderSearch::LookupFile(const char *FilenameStart,
const DirectoryLookup *&CurDir,
const FileEntry *CurFileEnt) {
// If 'Filename' is absolute, check to see if it exists and no searching.
- // FIXME: Portability. This should be a sys::Path interface, this doesn't
- // handle things like C:\foo.txt right, nor win32 \\network\device\blah.
- if (FilenameStart[0] == '/') {
+ if (llvm::sys::Path::isAbsolute(FilenameStart, FilenameEnd-FilenameStart)) {
CurDir = 0;
// If this was an #include_next "/absolute/file", fail.
diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp
index ce5934134f42..3227d1cf09c5 100644
--- a/lib/Lex/Pragma.cpp
+++ b/lib/Lex/Pragma.cpp
@@ -93,7 +93,7 @@ void Preprocessor::HandlePragmaDirective() {
PragmaHandlers->HandlePragma(*this, Tok);
// If the pragma handler didn't read the rest of the line, consume it now.
- if (CurPPLexer->ParsingPreprocessorDirective)
+ if (CurPPLexer && CurPPLexer->ParsingPreprocessorDirective)
DiscardUntilEndOfDirective();
}
@@ -195,8 +195,10 @@ void Preprocessor::HandlePragmaOnce(Token &OnceTok) {
void Preprocessor::HandlePragmaMark() {
assert(CurPPLexer && "No current lexer?");
- if (CurLexer) CurLexer->ReadToEndOfLine();
- else CurPTHLexer->DiscardToEndOfLine();
+ if (CurLexer)
+ CurLexer->ReadToEndOfLine();
+ else
+ CurPTHLexer->DiscardToEndOfLine();
}
@@ -254,6 +256,18 @@ void Preprocessor::HandlePragmaSystemHeader(Token &SysHeaderTok) {
// Mark the file as a system header.
HeaderInfo.MarkFileSystemHeader(TheLexer->getFileEntry());
+
+ PresumedLoc PLoc = SourceMgr.getPresumedLoc(SysHeaderTok.getLocation());
+ unsigned FilenameLen = strlen(PLoc.getFilename());
+ unsigned FilenameID = SourceMgr.getLineTableFilenameID(PLoc.getFilename(),
+ FilenameLen);
+
+ // Emit a line marker. This will change any source locations from this point
+ // forward to realize they are in a system header.
+ // Create a line note with this information.
+ SourceMgr.AddLineNote(SysHeaderTok.getLocation(), PLoc.getLine(), FilenameID,
+ false, false, true, false);
+
// Notify the client, if desired, that we are in a new source file.
if (Callbacks)
Callbacks->FileChanged(SysHeaderTok.getLocation(),
diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp
index 0a7d92eb83cf..24ee5d8a8f92 100644
--- a/lib/Lex/Preprocessor.cpp
+++ b/lib/Lex/Preprocessor.cpp
@@ -51,7 +51,7 @@ Preprocessor::Preprocessor(Diagnostic &diags, const LangOptions &opts,
IdentifierInfoLookup* IILookup)
: Diags(&diags), Features(opts), Target(target),FileMgr(Headers.getFileMgr()),
SourceMgr(SM), HeaderInfo(Headers), Identifiers(opts, IILookup),
- CurPPLexer(0), CurDirLookup(0), Callbacks(0) {
+ BuiltinInfo(Target), CurPPLexer(0), CurDirLookup(0), Callbacks(0) {
ScratchBuf = new ScratchBuffer(SourceMgr);
CounterValue = 0; // __COUNTER__ starts at 0.
diff --git a/lib/Lex/TokenConcatenation.cpp b/lib/Lex/TokenConcatenation.cpp
index ab989cafc156..be13b274574a 100644
--- a/lib/Lex/TokenConcatenation.cpp
+++ b/lib/Lex/TokenConcatenation.cpp
@@ -192,7 +192,8 @@ bool TokenConcatenation::AvoidConcat(const Token &PrevTok,
return isalnum(FirstChar) || Tok.is(tok::numeric_constant) ||
FirstChar == '+' || FirstChar == '-' || FirstChar == '.';
case tok::period: // ..., .*, .1234
- return FirstChar == '.' || isdigit(FirstChar) || FirstChar == '*';
+ return FirstChar == '.' || isdigit(FirstChar) ||
+ (PP.getLangOptions().CPlusPlus && FirstChar == '*');
case tok::amp: // &&
return FirstChar == '&';
case tok::plus: // ++
@@ -210,10 +211,11 @@ bool TokenConcatenation::AvoidConcat(const Token &PrevTok,
case tok::percent: // %>, %:
return FirstChar == '>' || FirstChar == ':';
case tok::colon: // ::, :>
- return FirstChar == ':' ||FirstChar == '>';
+ return FirstChar == '>' ||
+ (PP.getLangOptions().CPlusPlus && FirstChar == ':');
case tok::hash: // ##, #@, %:%:
return FirstChar == '#' || FirstChar == '@' || FirstChar == '%';
case tok::arrow: // ->*
- return FirstChar == '*';
+ return PP.getLangOptions().CPlusPlus && FirstChar == '*';
}
}
diff --git a/lib/Parse/MinimalAction.cpp b/lib/Parse/MinimalAction.cpp
index b018e36519f3..9ded366b29f9 100644
--- a/lib/Parse/MinimalAction.cpp
+++ b/lib/Parse/MinimalAction.cpp
@@ -42,6 +42,22 @@ Action::DeclPtrTy Action::ActOnUsingDirective(Scope *CurScope,
return DeclPtrTy();
}
+// Defined out-of-line here because of dependecy on AttributeList
+Action::DeclPtrTy Action::ActOnUsingDeclaration(Scope *CurScope,
+ SourceLocation UsingLoc,
+ const CXXScopeSpec &SS,
+ SourceLocation IdentLoc,
+ IdentifierInfo *TargetName,
+ AttributeList *AttrList,
+ bool IsTypeName) {
+
+ // FIXME: Parser seems to assume that Action::ActOn* takes ownership over
+ // passed AttributeList, however other actions don't free it, is it
+ // temporary state or bug?
+ delete AttrList;
+ return DeclPtrTy();
+}
+
void PrettyStackTraceActionsDecl::print(llvm::raw_ostream &OS) const {
if (Loc.isValid()) {
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 9073c6dbd193..69152523a112 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -402,7 +402,14 @@ Parser::DeclPtrTy Parser::ParseDeclarationAfterDeclarator(Declarator &D) {
SourceLocation DelLoc = ConsumeToken();
Actions.SetDeclDeleted(ThisDecl, DelLoc);
} else {
+ if (getLang().CPlusPlus)
+ Actions.ActOnCXXEnterDeclInitializer(CurScope, ThisDecl);
+
OwningExprResult Init(ParseInitializer());
+
+ if (getLang().CPlusPlus)
+ Actions.ActOnCXXExitDeclInitializer(CurScope, ThisDecl);
+
if (Init.isInvalid()) {
SkipUntil(tok::semi, true, true);
return DeclPtrTy();
@@ -2692,8 +2699,12 @@ void Parser::ParseBracketDeclarator(Declarator &D) {
// things like '=' and '*='. Sema rejects these in C89 mode because they
// are not i-c-e's, so we don't need to distinguish between the two here.
- // Parse the assignment-expression now.
- NumElements = ParseAssignmentExpression();
+ // Parse the constant-expression or assignment-expression now (depending
+ // on dialect).
+ if (getLang().CPlusPlus)
+ NumElements = ParseConstantExpression();
+ else
+ NumElements = ParseAssignmentExpression();
}
// If there was an error parsing the assignment-expression, recover.
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 498eaf19cd66..44f231a66786 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -48,6 +48,8 @@ Parser::DeclPtrTy Parser::ParseNamespace(unsigned Context,
SourceLocation IdentLoc;
IdentifierInfo *Ident = 0;
+
+ Token attrTok;
if (Tok.is(tok::identifier)) {
Ident = Tok.getIdentifierInfo();
@@ -56,13 +58,19 @@ Parser::DeclPtrTy Parser::ParseNamespace(unsigned Context,
// Read label attributes, if present.
Action::AttrTy *AttrList = 0;
- if (Tok.is(tok::kw___attribute))
+ if (Tok.is(tok::kw___attribute)) {
+ attrTok = Tok;
+
// FIXME: save these somewhere.
AttrList = ParseAttributes();
+ }
- if (Tok.is(tok::equal))
- // FIXME: Verify no attributes were present.
+ if (Tok.is(tok::equal)) {
+ if (AttrList)
+ Diag(attrTok, diag::err_unexpected_namespace_attributes_alias);
+
return ParseNamespaceAlias(NamespaceLoc, IdentLoc, Ident, DeclEnd);
+ }
if (Tok.isNot(tok::l_brace)) {
Diag(Tok, Ident ? diag::err_expected_lbrace :
@@ -245,15 +253,62 @@ Parser::DeclPtrTy Parser::ParseUsingDirective(unsigned Context,
///
/// using-declaration: [C++ 7.3.p3: namespace.udecl]
/// 'using' 'typename'[opt] ::[opt] nested-name-specifier
-/// unqualified-id [TODO]
-/// 'using' :: unqualified-id [TODO]
+/// unqualified-id
+/// 'using' :: unqualified-id
///
Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
SourceLocation UsingLoc,
SourceLocation &DeclEnd) {
- assert(false && "Not implemented");
- // FIXME: Implement parsing.
- return DeclPtrTy();
+ CXXScopeSpec SS;
+ bool IsTypeName;
+
+ // Ignore optional 'typename'.
+ if (Tok.is(tok::kw_typename)) {
+ ConsumeToken();
+ IsTypeName = true;
+ }
+ else
+ IsTypeName = false;
+
+ // Parse nested-name-specifier.
+ ParseOptionalCXXScopeSpecifier(SS);
+
+ AttributeList *AttrList = 0;
+ IdentifierInfo *TargetName = 0;
+ SourceLocation IdentLoc = SourceLocation();
+
+ // Check nested-name specifier.
+ if (SS.isInvalid()) {
+ SkipUntil(tok::semi);
+ return DeclPtrTy();
+ }
+ if (Tok.is(tok::annot_template_id)) {
+ Diag(Tok, diag::err_unexpected_template_spec_in_using);
+ SkipUntil(tok::semi);
+ return DeclPtrTy();
+ }
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_expected_ident_in_using);
+ // If there was invalid identifier, skip to end of decl, and eat ';'.
+ SkipUntil(tok::semi);
+ return DeclPtrTy();
+ }
+
+ // Parse identifier.
+ TargetName = Tok.getIdentifierInfo();
+ IdentLoc = ConsumeToken();
+
+ // Parse (optional) attributes (most likely GNU strong-using extension).
+ if (Tok.is(tok::kw___attribute))
+ AttrList = ParseAttributes();
+
+ // Eat ';'.
+ DeclEnd = Tok.getLocation();
+ ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
+ AttrList ? "attributes list" : "namespace name", tok::semi);
+
+ return Actions.ActOnUsingDeclaration(CurScope, UsingLoc, SS,
+ IdentLoc, TargetName, AttrList, IsTypeName);
}
/// ParseStaticAssertDeclaration - Parse C++0x static_assert-declaratoion.
@@ -271,7 +326,7 @@ Parser::DeclPtrTy Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){
}
SourceLocation LParenLoc = ConsumeParen();
-
+
OwningExprResult AssertExpr(ParseConstantExpression());
if (AssertExpr.isInvalid()) {
SkipUntil(tok::semi);
@@ -782,7 +837,23 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) {
ConsumeToken();
return ParseCXXClassMemberDeclaration(AS);
}
-
+
+ if (Tok.is(tok::kw_using)) {
+ // Eat 'using'.
+ SourceLocation UsingLoc = ConsumeToken();
+
+ if (Tok.is(tok::kw_namespace)) {
+ Diag(UsingLoc, diag::err_using_namespace_in_class);
+ SkipUntil(tok::semi, true, true);
+ }
+ else {
+ SourceLocation DeclEnd;
+ // Otherwise, it must be using-declaration.
+ ParseUsingDeclaration(Declarator::MemberContext, UsingLoc, DeclEnd);
+ }
+ return;
+ }
+
SourceLocation DSStart = Tok.getLocation();
// decl-specifier-seq:
// Parse the common declaration-specifiers piece.
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 3fee78bb719f..4a07d05650bd 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -276,6 +276,11 @@ Parser::ParseAssignmentExprWithObjCMessageExprStart(SourceLocation LBracLoc,
Parser::OwningExprResult Parser::ParseConstantExpression() {
+ // C++ [basic.def.odr]p2:
+ // An expression is potentially evaluated unless it appears where an
+ // integral constant expression is required (see 5.19) [...].
+ EnterUnevaluatedOperand Unevaluated(Actions);
+
OwningExprResult LHS(ParseCastExpression(false));
if (LHS.isInvalid()) return move(LHS);
@@ -971,8 +976,15 @@ Parser::ParseExprAfterTypeofSizeofAlignof(const Token &OpTok,
Diag(Tok,diag::err_expected_lparen_after_id) << OpTok.getIdentifierInfo();
return ExprError();
}
+
+ // C++0x [expr.sizeof]p1:
+ // [...] The operand is either an expression, which is an unevaluated
+ // operand (Clause 5) [...]
+ //
+ // The GNU typeof and alignof extensions also behave as unevaluated
+ // operands.
+ EnterUnevaluatedOperand Unevaluated(Actions);
Operand = ParseCastExpression(true/*isUnaryExpression*/);
-
} else {
// If it starts with a '(', we know that it is either a parenthesized
// type-name, or it is a unary-expression that starts with a compound
@@ -980,6 +992,14 @@ Parser::ParseExprAfterTypeofSizeofAlignof(const Token &OpTok,
// expression.
ParenParseOption ExprType = CastExpr;
SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
+
+ // C++0x [expr.sizeof]p1:
+ // [...] The operand is either an expression, which is an unevaluated
+ // operand (Clause 5) [...]
+ //
+ // The GNU typeof and alignof extensions also behave as unevaluated
+ // operands.
+ EnterUnevaluatedOperand Unevaluated(Actions);
Operand = ParseParenExpression(ExprType, true/*stopIfCastExpr*/,
CastTy, RParenLoc);
CastRange = SourceRange(LParenLoc, RParenLoc);
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 681c6adb2ea9..87aa5dc67116 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -377,6 +377,17 @@ Parser::OwningExprResult Parser::ParseCXXTypeid() {
Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true,
Ty.get(), RParenLoc);
} else {
+ // C++0x [expr.typeid]p3:
+ // When typeid is applied to an expression other than an lvalue of a
+ // polymorphic class type [...] The expression is an unevaluated
+ // operand (Clause 5).
+ //
+ // Note that we can't tell whether the expression is an lvalue of a
+ // polymorphic class type until after we've parsed the expression, so
+ // we treat the expression as an unevaluated operand and let semantic
+ // analysis cope with case where the expression is not an unevaluated
+ // operand.
+ EnterUnevaluatedOperand Unevaluated(Actions);
Result = ParseExpression();
// Match the ')'.
diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp
index ae863f2df1ee..425d80443955 100644
--- a/lib/Sema/JumpDiagnostics.cpp
+++ b/lib/Sema/JumpDiagnostics.cpp
@@ -77,11 +77,11 @@ JumpScopeChecker::JumpScopeChecker(Stmt *Body, Sema &s) : S(s) {
/// GetDiagForGotoScopeDecl - If this decl induces a new goto scope, return a
/// diagnostic that should be emitted if control goes over it. If not, return 0.
-static unsigned GetDiagForGotoScopeDecl(const Decl *D) {
+static unsigned GetDiagForGotoScopeDecl(ASTContext &Context, const Decl *D) {
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
if (VD->getType()->isVariablyModifiedType())
return diag::note_protected_by_vla;
- if (VD->hasAttr<CleanupAttr>())
+ if (VD->hasAttr<CleanupAttr>(Context))
return diag::note_protected_by_cleanup;
} else if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
if (TD->getUnderlyingType()->isVariablyModifiedType())
@@ -125,7 +125,7 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned ParentScope) {
for (DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
I != E; ++I) {
// If this decl causes a new scope, push and switch to it.
- if (unsigned Diag = GetDiagForGotoScopeDecl(*I)) {
+ if (unsigned Diag = GetDiagForGotoScopeDecl(this->S.Context, *I)) {
Scopes.push_back(GotoScope(ParentScope, Diag, (*I)->getLocation()));
ParentScope = Scopes.size()-1;
}
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index a5f243816abd..e756b41b12f5 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -125,6 +125,7 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
if (!PP.getLangOptions().ObjC1) return;
+ // Built-in ObjC types may already be set by PCHReader (hence isNull checks).
if (Context.getObjCSelType().isNull()) {
// Synthesize "typedef struct objc_selector *SEL;"
RecordDecl *SelTag = CreateStructDecl(Context, "objc_selector");
@@ -163,7 +164,7 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
// Synthesize "typedef struct objc_object { Class isa; } *id;"
if (Context.getObjCIdType().isNull()) {
RecordDecl *ObjectTag = CreateStructDecl(Context, "objc_object");
-
+
QualType ObjT = Context.getPointerType(Context.getTagDeclType(ObjectTag));
PushOnScopeChains(ObjectTag, TUScope);
TypedefDecl *IdTypedef = TypedefDecl::Create(Context, CurContext,
@@ -181,7 +182,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
ExternalSource(0), CurContext(0), PreDeclaratorDC(0),
CurBlock(0), PackContext(0), IdResolver(pp.getLangOptions()),
- GlobalNewDeleteDeclared(false),
+ GlobalNewDeleteDeclared(false), InUnevaluatedOperand(false),
CompleteTranslationUnit(CompleteTranslationUnit),
NumSFINAEErrors(0), CurrentInstantiationScope(0) {
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 0607a893da86..560f952bffa5 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -18,7 +18,9 @@
#include "IdentifierResolver.h"
#include "CXXFieldCollector.h"
#include "SemaOverload.h"
+#include "clang/AST/Attr.h"
#include "clang/AST/DeclBase.h"
+#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/Parse/Action.h"
@@ -102,7 +104,7 @@ struct BlockSemaInfo {
/// ReturnType - This will get set to block result type, by looking at
/// return types, if any, in the block body.
- Type *ReturnType;
+ QualType ReturnType;
/// LabelMap - This is a mapping from label identifiers to the LabelStmt for
/// it (which acts like the label decl in some ways). Forward referenced
@@ -245,6 +247,12 @@ public:
/// have been declared.
bool GlobalNewDeleteDeclared;
+ /// A flag that indicates when we are processing an unevaluated operand
+ /// (C++0x [expr]). C99 has the same notion of declarations being
+ /// "used" and C++03 has the notion of "potentially evaluated", but we
+ /// adopt the C++0x terminology since it is most precise.
+ bool InUnevaluatedOperand;
+
/// \brief Whether the code handled by Sema should be considered a
/// complete translation unit or not.
///
@@ -312,24 +320,8 @@ public:
// If we encountered an error during template argument
// deduction, and that error is one of the SFINAE errors,
// suppress the diagnostic.
- bool Fatal = false;
- switch (Diags.getDiagnosticLevel(DiagID)) {
- case Diagnostic::Ignored:
- case Diagnostic::Note:
- case Diagnostic::Warning:
- break;
-
- case Diagnostic::Error:
- ++NumSFINAEErrors;
- break;
-
- case Diagnostic::Fatal:
- Fatal = true;
- break;
- }
-
- if (!Fatal)
- return SemaDiagnosticBuilder(*this);
+ ++NumSFINAEErrors;
+ return SemaDiagnosticBuilder(*this);
}
DiagnosticBuilder DB = Diags.Report(FullSourceLoc(Loc, SourceMgr), DiagID);
@@ -375,6 +367,8 @@ public:
QualType BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
Expr *ArraySize, unsigned Quals,
SourceLocation Loc, DeclarationName Entity);
+ QualType BuildExtVectorType(QualType T, ExprArg ArraySize,
+ SourceLocation AttrLoc);
QualType BuildFunctionType(QualType T,
QualType *ParamTypes, unsigned NumParamTypes,
bool Variadic, unsigned Quals,
@@ -468,6 +462,19 @@ public:
virtual DeclPtrTy ActOnFinishFunctionBody(DeclPtrTy Decl, StmtArg Body);
DeclPtrTy ActOnFinishFunctionBody(DeclPtrTy Decl, StmtArg Body,
bool IsInstantiation);
+
+ /// \brief Diagnose any unused parameters in the given sequence of
+ /// ParmVarDecl pointers.
+ template<typename InputIterator>
+ void DiagnoseUnusedParameters(InputIterator Param, InputIterator ParamEnd) {
+ for (; Param != ParamEnd; ++Param) {
+ if (!(*Param)->isUsed() && (*Param)->getDeclName() &&
+ !(*Param)->template hasAttr<UnusedAttr>(Context))
+ Diag((*Param)->getLocation(), diag::warn_unused_parameter)
+ << (*Param)->getDeclName();
+ }
+ }
+
void DiagnoseInvalidJumps(Stmt *Body);
virtual DeclPtrTy ActOnFileScopeAsmDecl(SourceLocation Loc, ExprArg expr);
@@ -553,6 +560,12 @@ public:
void PushDeclContext(Scope *S, DeclContext *DC);
void PopDeclContext();
+ /// EnterDeclaratorContext - Used when we must lookup names in the context
+ /// of a declarator's nested name specifier.
+ void EnterDeclaratorContext(Scope *S, DeclContext *DC);
+ void ExitDeclaratorContext(Scope *S);
+
+
/// getCurFunctionDecl - If inside of a function body, this returns a pointer
/// to the function decl for the function being parsed. If we're currently
/// in a 'block', this returns the containing context.
@@ -702,6 +715,7 @@ public:
bool isBetterOverloadCandidate(const OverloadCandidate& Cand1,
const OverloadCandidate& Cand2);
OverloadingResult BestViableFunction(OverloadCandidateSet& CandidateSet,
+ SourceLocation Loc,
OverloadCandidateSet::iterator& Best);
void PrintOverloadCandidates(OverloadCandidateSet& CandidateSet,
bool OnlyViable);
@@ -1132,8 +1146,8 @@ public:
// More parsing and symbol table subroutines.
// Decl attributes - this routine is the top level dispatcher.
- void ProcessDeclAttributes(Decl *D, const Declarator &PD);
- void ProcessDeclAttributeList(Decl *D, const AttributeList *AttrList);
+ void ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD);
+ void ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AttrList);
void WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method,
bool &IncompleteImpl);
@@ -1320,6 +1334,14 @@ public:
void DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
Expr **Args, unsigned NumArgs);
+ virtual bool setUnevaluatedOperand(bool UnevaluatedOperand) {
+ bool Result = InUnevaluatedOperand;
+ InUnevaluatedOperand = UnevaluatedOperand;
+ return Result;
+ }
+
+ void MarkDeclarationReferenced(SourceLocation Loc, Decl *D);
+
// Primary Expressions.
virtual SourceRange getExprRange(ExprTy *E) const;
@@ -1525,6 +1547,14 @@ public:
const CXXScopeSpec &SS,
SourceLocation IdentLoc,
IdentifierInfo *Ident);
+
+ virtual DeclPtrTy ActOnUsingDeclaration(Scope *CurScope,
+ SourceLocation UsingLoc,
+ const CXXScopeSpec &SS,
+ SourceLocation IdentLoc,
+ IdentifierInfo *TargetName,
+ AttributeList *AttrList,
+ bool IsTypeName);
/// AddCXXDirectInitializerToDecl - This action is called immediately after
/// ActOnDeclarator, when a C++ direct initializer is present.
@@ -1541,6 +1571,11 @@ public:
CXXConstructorDecl *Constructor,
QualType DeclInitType,
Expr **Exprs, unsigned NumExprs);
+
+ /// DefineImplicitDefaultConstructor - Checks for feasibilityt of
+ /// defining this constructor as the default constructor.
+ void DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
+ CXXConstructorDecl *Constructor);
/// MaybeBindToTemporary - If the passed in expression has a record type with
/// a non-trivial destructor, this will return CXXBindTemporaryExpr. Otherwise
@@ -1677,8 +1712,8 @@ public:
/// MaybeCreateCXXExprWithTemporaries - If the list of temporaries is
/// non-empty, will create a new CXXExprWithTemporaries expression.
/// Otherwise, just returs the passed in expression.
- Expr *MaybeCreateCXXExprWithTemporaries(Expr *SubExpr,
- bool DestroyTemps = true);
+ Expr *MaybeCreateCXXExprWithTemporaries(Expr *SubExpr,
+ bool ShouldDestroyTemporaries);
virtual OwningExprResult ActOnFinishFullExpr(ExprArg Expr);
@@ -1735,6 +1770,17 @@ public:
/// defining scope.
virtual void ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS);
+ /// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse an
+ /// initializer for the declaration 'Dcl'.
+ /// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a
+ /// static data member of class X, nam