summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 2f63051..bb128d6 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 f4313f4..b686b0e 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 7440e7b..77b7bf6 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 5c9fd34..a75eecd 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 4a74a2c..9ca1823 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 d1b921a..1e44403 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 a480f54..af06965f 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 98de5f9..2ed9112 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 e44ccca..f9f5da1 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 ef78c40..e00833b 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 1b01238..ca55ea6 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 76cbed3..5555a9b 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 0000000..a02e39b
--- /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 c8e5e85..eb519e0 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 fde8b16..0fc49f5 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 2068b1b..4af8a7c 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 6c23745..0f3a137 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 d61feea..6f95c6f 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 0f353d0..c2f8f5a 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 0e8da2a..8afcc4c 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 ee6d4dc..c9d1e25 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 1f081f4..0c5df2e 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 d424526..d074e30 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 89af975..b86f4e8 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 6463a4f..f770c50 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 501807d..2896f79 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 e2b9eb7..d65a97e 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 fa4f430..755cfce 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 2405c2f..7d78087 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 57ae9a4..bcfb83b 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 7045f14..abd07a9 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 6196c13..c9d0ef1 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 0000000..68c06f5
--- /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 0000000..39ed5f9
--- /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 0000000..956d971
--- /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 0000000..4c52bd8
--- /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 99db717..4ed11e1 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 0862cd6..e546a12 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 1e00ae3..b3ed364 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 0000000..26430f7
--- /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 0000000..2a78fd9
--- /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 f1207e4..5b57521 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 d613ae1..75458d8 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 7ed9e45..b80142f 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 a3e406b..bf63932 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 a39a506..02e71d7 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 8430da2..7a930d7 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 5b1bf9b..23c2637 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 309be41..4a3ad26 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 8fd66a2..18c0f77 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 710da63..b300940 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 e304f54..7b45b21 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 b272214..ffa8a86 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 98e9551..aa85769 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 6c594ea..5c9701e 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 2dd46c3..fcb405d 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 32998e1..5dbbfc3 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 f5ca322..c58ceb4 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 69433d6..0f61a5e 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 ff9da0f..c91442b 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 f50d7a1..2ba7d86 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 7979f9c..92c50e2 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 2bc071a..7ada6d8 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 7a8fef5..87432d4 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 9aea124..7f7270d 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 e1c4848..7e54f1a 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 e0e478c..aeb1c04 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 69c09d9..3c14ee9 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 9f066f4..9e11a26 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 f6ac2b9..73c68bc 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 eae3aef..5f2b8f8 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 e19b168..77c3c8f 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 f79dba0..82801eb 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 fb41e2f..1e1a10d 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 13326ab..5aa756e 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 5c885cd..4e38a34 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 ebe0514..6cb5dab 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 323f7a7..78b8b0a 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 ed5eb46..8dfc5d1 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 a919dfa..66b1f17 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 141726a..a6e6d11 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 4037f32..ec6058a 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 049e716..a2b8d13 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 de65580..8f3368e 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 29eaaad..4e603c3 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 eb0db61..51c5b3d 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 e1332ff..3555c8c 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 0e21a00..0b109f9 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 ed18d32..2af0639 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 51f9a76..e7cf8e6 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 a70f718..912479f 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 bd5b05a..6ffca81 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 672f6da..f10a08f 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 82156e9..f926c05 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 af791f6..f31c610 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 14392ab..24e441a 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 7147d8f..42cbff9 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 d8c6a0a..8c2676b8 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 2d577f8..831e11b 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 11c9251..5844be8 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 0000000..a7fbcda
--- /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 649f9da..330b4db 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 0000000..5c21999
--- /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 7562d2a..19a7573 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 6383c20..7a2b3a7 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 6cff75d..41908ad 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 87fc839..96f21f1 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 6856623..3dd84c7 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 e6871e3..d096388 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 765fecb..3b1eb08 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 6734661..44da4d7 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 73dea10..c63c03c 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 89d099c..d63d9cb 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 8393574..d20d5cd 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 f382704..dce2710 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 c861881..6ba0a28 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 6699c65..d4c7e0f 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 0000000..f32fbbd
--- /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 e44c37a..318685a 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 129fa1a..9023b11 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 ce59341..3227d1c 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 0a7d92e..24ee5d8 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 ab989ca..be13b27 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 b018e36..9ded366 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 9073c6d..6915252 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 498eaf1..44f231a 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 3fee78b..4a07d05 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 681c6ad..87aa5dc 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 ae863f2..425d804 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 a5f2438..e756b41 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 0607a89..560f952 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, 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);
+
// ParseObjCStringLiteral - Parse Objective-C string literals.
virtual ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,
ExprTy **Strings,
diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp
index 1bf8444..cbfa56a 100644
--- a/lib/Sema/SemaAttr.cpp
+++ b/lib/Sema/SemaAttr.cpp
@@ -205,7 +205,7 @@ void Sema::ActOnPragmaUnused(ExprTy **Exprs, unsigned NumExprs,
// Otherwise, add the 'unused' attribute to each referenced declaration.
for (unsigned i = 0; i < NumExprs; ++i) {
DeclRefExpr *DR = (DeclRefExpr*) Exprs[i];
- DR->getDecl()->addAttr(::new (Context) UnusedAttr());
+ DR->getDecl()->addAttr(Context, ::new (Context) UnusedAttr());
DR->Destroy(Context);
}
}
diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp
index 11ac0bd..a14bcd5 100644
--- a/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/lib/Sema/SemaCXXScopeSpec.cpp
@@ -286,11 +286,7 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
/// The 'SS' should be a non-empty valid CXXScopeSpec.
void Sema::ActOnCXXEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
assert(SS.isSet() && "Parser passed invalid CXXScopeSpec.");
- assert(PreDeclaratorDC == 0 && "Previous declarator context not popped?");
- PreDeclaratorDC = static_cast<DeclContext*>(S->getEntity());
- CurContext = computeDeclContext(SS);
- assert(CurContext && "No context?");
- S->setEntity(CurContext);
+ EnterDeclaratorContext(S, computeDeclContext(SS));
}
/// ActOnCXXExitDeclaratorScope - Called when a declarator that previously
@@ -301,12 +297,5 @@ void Sema::ActOnCXXEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
void Sema::ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
assert(SS.isSet() && "Parser passed invalid CXXScopeSpec.");
assert(S->getEntity() == computeDeclContext(SS) && "Context imbalance!");
- S->setEntity(PreDeclaratorDC);
- PreDeclaratorDC = 0;
-
- // Reset CurContext to the nearest enclosing context.
- while (!S->getEntity() && S->getParent())
- S = S->getParent();
- CurContext = static_cast<DeclContext*>(S->getEntity());
- assert(CurContext && "No context?");
+ ExitDeclaratorContext(S);
}
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 4856e7f..a2ceafa 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -166,7 +166,7 @@ Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) {
// handlers.
// Printf checking.
- if (const FormatAttr *Format = FDecl->getAttr<FormatAttr>()) {
+ if (const FormatAttr *Format = FDecl->getAttr<FormatAttr>(Context)) {
if (Format->getType() == "printf") {
bool HasVAListArg = Format->getFirstArg() == 0;
if (!HasVAListArg) {
@@ -178,7 +178,8 @@ Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) {
HasVAListArg ? 0 : Format->getFirstArg() - 1);
}
}
- for (const Attr *attr = FDecl->getAttrs(); attr; attr = attr->getNext()) {
+ for (const Attr *attr = FDecl->getAttrs(Context);
+ attr; attr = attr->getNext()) {
if (const NonNullAttr *NonNull = dyn_cast<NonNullAttr>(attr))
CheckNonNullArguments(NonNull, TheCall);
}
@@ -191,7 +192,7 @@ Sema::CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall) {
OwningExprResult TheCallResult(Owned(TheCall));
// Printf checking.
- const FormatAttr *Format = NDecl->getAttr<FormatAttr>();
+ const FormatAttr *Format = NDecl->getAttr<FormatAttr>(Context);
if (!Format)
return move(TheCallResult);
const VarDecl *V = dyn_cast<VarDecl>(NDecl);
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index b995717..06fd1a1 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -183,7 +183,7 @@ DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) {
DeclContext *Sema::getContainingDC(DeclContext *DC) {
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC)) {
// A C++ out-of-line method will return to the file declaration context.
- if (MD->isOutOfLineDefinition())
+ if (MD->isOutOfLine())
return MD->getLexicalDeclContext();
// A C++ inline method is parsed *after* the topmost class it was declared
@@ -219,6 +219,27 @@ void Sema::PopDeclContext() {
CurContext = getContainingDC(CurContext);
}
+/// EnterDeclaratorContext - Used when we must lookup names in the context
+/// of a declarator's nested name specifier.
+void Sema::EnterDeclaratorContext(Scope *S, DeclContext *DC) {
+ assert(PreDeclaratorDC == 0 && "Previous declarator context not popped?");
+ PreDeclaratorDC = static_cast<DeclContext*>(S->getEntity());
+ CurContext = DC;
+ assert(CurContext && "No context?");
+ S->setEntity(CurContext);
+}
+
+void Sema::ExitDeclaratorContext(Scope *S) {
+ S->setEntity(PreDeclaratorDC);
+ PreDeclaratorDC = 0;
+
+ // Reset CurContext to the nearest enclosing context.
+ while (!S->getEntity() && S->getParent())
+ S = S->getParent();
+ CurContext = static_cast<DeclContext*>(S->getEntity());
+ assert(CurContext && "No context?");
+}
+
/// \brief Determine whether we allow overloading of the function
/// PrevDecl with another declaration.
///
@@ -235,7 +256,7 @@ static bool AllowOverloadingOfFunction(Decl *PrevDecl, ASTContext &Context) {
if (isa<OverloadedFunctionDecl>(PrevDecl))
return true;
- return PrevDecl->getAttr<OverloadableAttr>() != 0;
+ return PrevDecl->getAttr<OverloadableAttr>(Context) != 0;
}
/// Add this decl to the scope shadowed decl chains.
@@ -590,8 +611,9 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
/// DeclhasAttr - returns true if decl Declaration already has the target
/// attribute.
-static bool DeclHasAttr(const Decl *decl, const Attr *target) {
- for (const Attr *attr = decl->getAttrs(); attr; attr = attr->getNext())
+static bool
+DeclHasAttr(ASTContext &Context, const Decl *decl, const Attr *target) {
+ for (const Attr *attr = decl->getAttrs(Context); attr; attr = attr->getNext())
if (attr->getKind() == target->getKind())
return true;
@@ -600,11 +622,11 @@ static bool DeclHasAttr(const Decl *decl, const Attr *target) {
/// MergeAttributes - append attributes from the Old decl to the New one.
static void MergeAttributes(Decl *New, Decl *Old, ASTContext &C) {
- for (const Attr *attr = Old->getAttrs(); attr; attr = attr->getNext()) {
- if (!DeclHasAttr(New, attr) && attr->isMerged()) {
+ for (const Attr *attr = Old->getAttrs(C); attr; attr = attr->getNext()) {
+ if (!DeclHasAttr(C, New, attr) && attr->isMerged()) {
Attr *NewAttr = attr->clone(C);
NewAttr->setInherited(true);
- New->addAttr(NewAttr);
+ New->addAttr(C, NewAttr);
}
}
}
@@ -1615,7 +1637,7 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
NewTD->setInvalidDecl();
// Handle attributes prior to checking for duplicates in MergeVarDecl
- ProcessDeclAttributes(NewTD, D);
+ ProcessDeclAttributes(S, NewTD, D);
// Merge the decl with the existing one if appropriate. If the decl is
// in an outer scope, it isn't the same thing.
if (PrevDecl && isDeclInScope(PrevDecl, DC, S)) {
@@ -1801,13 +1823,14 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
NewVD->setLexicalDeclContext(CurContext);
// Handle attributes prior to checking for duplicates in MergeVarDecl
- ProcessDeclAttributes(NewVD, D);
+ ProcessDeclAttributes(S, NewVD, D);
// Handle GNU asm-label extension (encoded as an attribute).
if (Expr *E = (Expr*) D.getAsmLabel()) {
// The parser guarantees this is a string.
StringLiteral *SE = cast<StringLiteral>(E);
- NewVD->addAttr(::new (Context) AsmLabelAttr(std::string(SE->getStrData(),
+ NewVD->addAttr(Context,
+ ::new (Context) AsmLabelAttr(std::string(SE->getStrData(),
SE->getByteLength())));
}
@@ -1886,11 +1909,11 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl,
}
if (NewVD->hasLocalStorage() && T.isObjCGCWeak()
- && !NewVD->hasAttr<BlocksAttr>())
+ && !NewVD->hasAttr<BlocksAttr>(Context))
Diag(NewVD->getLocation(), diag::warn_attribute_weak_on_local);
bool isVM = T->isVariablyModifiedType();
- if (isVM || NewVD->hasAttr<CleanupAttr>())
+ if (isVM || NewVD->hasAttr<CleanupAttr>(Context))
CurFunctionNeedsScopeChecking = true;
if ((isVM && NewVD->hasLinkage()) ||
@@ -1945,12 +1968,12 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl,
return NewVD->setInvalidDecl();
}
- if (!NewVD->hasLocalStorage() && NewVD->hasAttr<BlocksAttr>()) {
+ if (!NewVD->hasLocalStorage() && NewVD->hasAttr<BlocksAttr>(Context)) {
Diag(NewVD->getLocation(), diag::err_block_on_nonlocal);
return NewVD->setInvalidDecl();
}
- if (isVM && NewVD->hasAttr<BlocksAttr>()) {
+ if (isVM && NewVD->hasAttr<BlocksAttr>(Context)) {
Diag(NewVD->getLocation(), diag::err_block_on_vm);
return NewVD->setInvalidDecl();
}
@@ -2180,7 +2203,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
if (Expr *E = (Expr*) D.getAsmLabel()) {
// The parser guarantees this is a string.
StringLiteral *SE = cast<StringLiteral>(E);
- NewFD->addAttr(::new (Context) AsmLabelAttr(std::string(SE->getStrData(),
+ NewFD->addAttr(Context,
+ ::new (Context) AsmLabelAttr(std::string(SE->getStrData(),
SE->getByteLength())));
}
@@ -2260,7 +2284,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
Diag(NewFD->getLocation(), diag::err_out_of_line_declaration)
<< D.getCXXScopeSpec().getRange();
NewFD->setInvalidDecl();
- } else if (!Redeclaration) {
+ } else if (!Redeclaration && (!PrevDecl || !isa<UsingDecl>(PrevDecl))) {
// The user tried to provide an out-of-line definition for a
// function that is a member of a class or namespace, but there
// was no such member function declared (C++ [class.mfct]p2,
@@ -2298,10 +2322,10 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// (for example to check for conflicts, etc).
// FIXME: This needs to happen before we merge declarations. Then,
// let attribute merging cope with attribute conflicts.
- ProcessDeclAttributes(NewFD, D);
+ ProcessDeclAttributes(S, NewFD, D);
AddKnownFunctionAttributes(NewFD);
- if (OverloadableAttrRequired && !NewFD->getAttr<OverloadableAttr>()) {
+ if (OverloadableAttrRequired && !NewFD->getAttr<OverloadableAttr>(Context)) {
// If a function name is overloadable in C, then every function
// with that name must be marked "overloadable".
Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing)
@@ -2309,7 +2333,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
if (PrevDecl)
Diag(PrevDecl->getLocation(),
diag::note_attribute_overloadable_prev_overload);
- NewFD->addAttr(::new (Context) OverloadableAttr());
+ NewFD->addAttr(Context, ::new (Context) OverloadableAttr());
}
// If this is a locally-scoped extern C function, update the
@@ -2431,7 +2455,8 @@ void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
if (PrevDecl &&
(!AllowOverloadingOfFunction(PrevDecl, Context) ||
- !IsOverload(NewFD, PrevDecl, MatchedDecl))) {
+ !IsOverload(NewFD, PrevDecl, MatchedDecl)) &&
+ !isa<UsingDecl>(PrevDecl)) {
Redeclaration = true;
Decl *OldDecl = PrevDecl;
@@ -2708,8 +2733,12 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl) {
IK_Default);
if (!Constructor)
Var->setInvalidDecl();
- else if (!RD->hasTrivialConstructor())
- InitializeVarWithConstructor(Var, Constructor, InitType, 0, 0);
+ else {
+ if (!RD->hasTrivialConstructor())
+ InitializeVarWithConstructor(Var, Constructor, InitType, 0, 0);
+ // Check for valid construction.
+ DefineImplicitDefaultConstructor(Var->getLocation(), Constructor);
+ }
}
}
@@ -2907,9 +2936,9 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
if (II)
IdResolver.AddDecl(New);
- ProcessDeclAttributes(New, D);
+ ProcessDeclAttributes(S, New, D);
- if (New->hasAttr<BlocksAttr>()) {
+ if (New->hasAttr<BlocksAttr>(Context)) {
Diag(New->getLocation(), diag::err_block_on_nonlocal);
}
return DeclPtrTy::make(New);
@@ -3035,9 +3064,10 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) {
// Checking attributes of current function definition
// dllimport attribute.
- if (FD->getAttr<DLLImportAttr>() && (!FD->getAttr<DLLExportAttr>())) {
+ if (FD->getAttr<DLLImportAttr>(Context) &&
+ (!FD->getAttr<DLLExportAttr>(Context))) {
// dllimport attribute cannot be applied to definition.
- if (!(FD->getAttr<DLLImportAttr>())->isInherited()) {
+ if (!(FD->getAttr<DLLImportAttr>(Context))->isInherited()) {
Diag(FD->getLocation(),
diag::err_attribute_can_be_applied_only_to_symbol_declaration)
<< "dllimport";
@@ -3065,10 +3095,23 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg,
Stmt *Body = BodyArg.takeAs<Stmt>();
if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(dcl)) {
FD->setBody(Body);
+
+ if (!FD->isInvalidDecl())
+ DiagnoseUnusedParameters(FD->param_begin(), FD->param_end());
+
+ // C++ [basic.def.odr]p2:
+ // [...] A virtual member function is used if it is not pure. [...]
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FD))
+ if (Method->isVirtual() && !Method->isPure())
+ MarkDeclarationReferenced(Method->getLocation(), Method);
+
assert(FD == getCurFunctionDecl() && "Function parsing confused");
} else if (ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(dcl)) {
assert(MD == getCurMethodDecl() && "Method parsing confused");
MD->setBody(Body);
+
+ if (!MD->isInvalidDecl())
+ DiagnoseUnusedParameters(MD->param_begin(), MD->param_end());
} else {
Body->Destroy(Context);
return DeclPtrTy();
@@ -3206,8 +3249,9 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
unsigned FormatIdx;
bool HasVAListArg;
if (Context.BuiltinInfo.isPrintfLike(BuiltinID, FormatIdx, HasVAListArg)) {
- if (!FD->getAttr<FormatAttr>())
- FD->addAttr(::new (Context) FormatAttr("printf", FormatIdx + 1,
+ if (!FD->getAttr<FormatAttr>(Context))
+ FD->addAttr(Context,
+ ::new (Context) FormatAttr("printf", FormatIdx + 1,
HasVAListArg ? 0 : FormatIdx + 2));
}
@@ -3216,8 +3260,8 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
// IRgen to use LLVM intrinsics for such functions.
if (!getLangOptions().MathErrno &&
Context.BuiltinInfo.isConstWithoutErrno(BuiltinID)) {
- if (!FD->getAttr<ConstAttr>())
- FD->addAttr(::new (Context) ConstAttr());
+ if (!FD->getAttr<ConstAttr>(Context))
+ FD->addAttr(Context, ::new (Context) ConstAttr());
}
}
@@ -3235,15 +3279,17 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
return;
if (Name->isStr("NSLog") || Name->isStr("NSLogv")) {
- if (const FormatAttr *Format = FD->getAttr<FormatAttr>()) {
+ if (const FormatAttr *Format = FD->getAttr<FormatAttr>(Context)) {
// FIXME: We known better than our headers.
const_cast<FormatAttr *>(Format)->setType("printf");
} else
- FD->addAttr(::new (Context) FormatAttr("printf", 1,
+ FD->addAttr(Context,
+ ::new (Context) FormatAttr("printf", 1,
Name->isStr("NSLogv") ? 0 : 2));
} else if (Name->isStr("asprintf") || Name->isStr("vasprintf")) {
- if (!FD->getAttr<FormatAttr>())
- FD->addAttr(::new (Context) FormatAttr("printf", 2,
+ if (!FD->getAttr<FormatAttr>(Context))
+ FD->addAttr(Context,
+ ::new (Context) FormatAttr("printf", 2,
Name->isStr("vasprintf") ? 0 : 3));
}
}
@@ -3599,7 +3645,7 @@ CreateNewDecl:
// the #pragma tokens are effectively skipped over during the
// parsing of the struct).
if (unsigned Alignment = getPragmaPackAlignment())
- New->addAttr(::new (Context) PackedAttr(Alignment * 8));
+ New->addAttr(Context, ::new (Context) PackedAttr(Alignment * 8));
}
if (getLangOptions().CPlusPlus && SS.isEmpty() && Name && !Invalid) {
@@ -3628,7 +3674,7 @@ CreateNewDecl:
New->setInvalidDecl();
if (Attr)
- ProcessDeclAttributeList(New, Attr);
+ ProcessDeclAttributeList(S, New, Attr);
// If we're declaring or defining a tag in function prototype scope
// in C, note that this type can only be used within the function.
@@ -3786,6 +3832,14 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record,
Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread);
NamedDecl *PrevDecl = LookupName(S, II, LookupMemberName, true);
+
+ if (PrevDecl && PrevDecl->isTemplateParameter()) {
+ // Maybe we will complain about the shadowed template parameter.
+ DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
+ // Just pretend that we didn't see the previous declaration.
+ PrevDecl = 0;
+ }
+
if (PrevDecl && !isDeclInScope(PrevDecl, Record, S))
PrevDecl = 0;
@@ -3878,7 +3932,8 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
// FIXME: We need to pass in the attributes given an AST
// representation, not a parser representation.
if (D)
- ProcessDeclAttributes(NewFD, *D);
+ // FIXME: What to pass instead of TUScope?
+ ProcessDeclAttributes(TUScope, NewFD, *D);
if (T.isObjCGCWeak())
Diag(Loc, diag::warn_attribute_weak_on_field);
@@ -3985,7 +4040,7 @@ Sema::DeclPtrTy Sema::ActOnIvar(Scope *S,
}
// Process attributes attached to the ivar.
- ProcessDeclAttributes(NewID, D);
+ ProcessDeclAttributes(S, NewID, D);
if (D.isInvalidType())
NewID->setInvalidDecl();
@@ -4151,7 +4206,7 @@ void Sema::ActOnFields(Scope* S,
}
if (Attr)
- ProcessDeclAttributeList(Record, Attr);
+ ProcessDeclAttributeList(S, Record, Attr);
}
EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
@@ -4441,7 +4496,7 @@ void Sema::ActOnPragmaWeakID(IdentifierInfo* Name,
// FIXME: This implementation is an ugly hack!
if (PrevDecl) {
- PrevDecl->addAttr(::new (Context) WeakAttr());
+ PrevDecl->addAttr(Context, ::new (Context) WeakAttr());
return;
}
Diag(PragmaLoc, diag::err_unsupported_pragma_weak);
@@ -4457,8 +4512,8 @@ void Sema::ActOnPragmaWeakAlias(IdentifierInfo* Name,
// FIXME: This implementation is an ugly hack!
if (PrevDecl) {
- PrevDecl->addAttr(::new (Context) AliasAttr(AliasName->getName()));
- PrevDecl->addAttr(::new (Context) WeakAttr());
+ PrevDecl->addAttr(Context, ::new (Context) AliasAttr(AliasName->getName()));
+ PrevDecl->addAttr(Context, ::new (Context) WeakAttr());
return;
}
Diag(PragmaLoc, diag::err_unsupported_pragma_weak);
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 1afdb60..d57630e 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -156,8 +156,8 @@ static inline bool isCFStringType(QualType T, ASTContext &Ctx) {
// least add some helper functions to check most argument patterns (#
// and types of args).
-static void HandleExtVectorTypeAttr(Decl *d, const AttributeList &Attr,
- Sema &S) {
+static void HandleExtVectorTypeAttr(Scope *scope, Decl *d,
+ const AttributeList &Attr, Sema &S) {
TypedefDecl *tDecl = dyn_cast<TypedefDecl>(d);
if (tDecl == 0) {
S.Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef);
@@ -165,37 +165,32 @@ static void HandleExtVectorTypeAttr(Decl *d, const AttributeList &Attr,
}
QualType curType = tDecl->getUnderlyingType();
- // check the attribute arguments.
- if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
- return;
- }
- Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
- llvm::APSInt vecSize(32);
- if (!sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) {
- S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
- << "ext_vector_type" << sizeExpr->getSourceRange();
- return;
- }
- // unlike gcc's vector_size attribute, we do not allow vectors to be defined
- // in conjunction with complex types (pointers, arrays, functions, etc.).
- if (!curType->isIntegerType() && !curType->isRealFloatingType()) {
- S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << curType;
- return;
+
+ Expr *sizeExpr;
+
+ // Special case where the argument is a template id.
+ if (Attr.getParameterName()) {
+ sizeExpr = S.ActOnDeclarationNameExpr(scope, Attr.getLoc(),
+ Attr.getParameterName(),
+ false, 0, false).takeAs<Expr>();
+ } else {
+ // check the attribute arguments.
+ if (Attr.getNumArgs() != 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ return;
+ }
+ sizeExpr = static_cast<Expr *>(Attr.getArg(0));
}
- // unlike gcc's vector_size attribute, the size is specified as the
- // number of elements, not the number of bytes.
- unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue());
-
- if (vectorSize == 0) {
- S.Diag(Attr.getLoc(), diag::err_attribute_zero_size)
- << sizeExpr->getSourceRange();
- return;
+
+ // Instantiate/Install the vector type, and let Sema build the type for us.
+ // This will run the reguired checks.
+ QualType T = S.BuildExtVectorType(curType, S.Owned(sizeExpr), Attr.getLoc());
+ if (!T.isNull()) {
+ tDecl->setUnderlyingType(T);
+
+ // Remember this typedef decl, we will need it later for diagnostics.
+ S.ExtVectorDecls.push_back(tDecl);
}
- // Instantiate/Install the vector type, the number of elements is > 0.
- tDecl->setUnderlyingType(S.Context.getExtVectorType(curType, vectorSize));
- // Remember this typedef decl, we will need it later for diagnostics.
- S.ExtVectorDecls.push_back(tDecl);
}
@@ -289,7 +284,7 @@ static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
}
if (TagDecl *TD = dyn_cast<TagDecl>(d))
- TD->addAttr(::new (S.Context) PackedAttr(1));
+ TD->addAttr(S.Context, ::new (S.Context) PackedAttr(1));
else if (FieldDecl *FD = dyn_cast<FieldDecl>(d)) {
// If the alignment is less than or equal to 8 bits, the packed attribute
// has no effect.
@@ -298,7 +293,7 @@ static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored_for_field_of_type)
<< Attr.getName() << FD->getType();
else
- FD->addAttr(::new (S.Context) PackedAttr(1));
+ FD->addAttr(S.Context, ::new (S.Context) PackedAttr(1));
} else
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
}
@@ -313,7 +308,7 @@ static void HandleIBOutletAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// The IBOutlet attribute only applies to instance variables of Objective-C
// classes.
if (isa<ObjCIvarDecl>(d) || isa<ObjCPropertyDecl>(d))
- d->addAttr(::new (S.Context) IBOutletAttr());
+ d->addAttr(S.Context, ::new (S.Context) IBOutletAttr());
else
S.Diag(Attr.getLoc(), diag::err_attribute_iboutlet);
}
@@ -385,7 +380,7 @@ static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) {
unsigned* start = &NonNullArgs[0];
unsigned size = NonNullArgs.size();
std::sort(start, start + size);
- d->addAttr(::new (S.Context) NonNullAttr(start, size));
+ d->addAttr(S.Context, ::new (S.Context) NonNullAttr(start, size));
}
static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -410,7 +405,7 @@ static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// FIXME: check if target symbol exists in current file
- d->addAttr(::new (S.Context) AliasAttr(std::string(Alias, AliasLen)));
+ d->addAttr(S.Context, ::new (S.Context) AliasAttr(std::string(Alias, AliasLen)));
}
static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr,
@@ -427,7 +422,7 @@ static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr,
return;
}
- d->addAttr(::new (S.Context) AlwaysInlineAttr());
+ d->addAttr(S.Context, ::new (S.Context) AlwaysInlineAttr());
}
static bool HandleCommonNoReturnAttr(Decl *d, const AttributeList &Attr,
@@ -452,13 +447,13 @@ static bool HandleCommonNoReturnAttr(Decl *d, const AttributeList &Attr,
static void HandleNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) {
if (HandleCommonNoReturnAttr(d, Attr, S))
- d->addAttr(::new (S.Context) NoReturnAttr());
+ d->addAttr(S.Context, ::new (S.Context) NoReturnAttr());
}
static void HandleAnalyzerNoReturnAttr(Decl *d, const AttributeList &Attr,
Sema &S) {
if (HandleCommonNoReturnAttr(d, Attr, S))
- d->addAttr(::new (S.Context) AnalyzerNoReturnAttr());
+ d->addAttr(S.Context, ::new (S.Context) AnalyzerNoReturnAttr());
}
static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -474,7 +469,7 @@ static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) UnusedAttr());
+ d->addAttr(S.Context, ::new (S.Context) UnusedAttr());
}
static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -495,7 +490,7 @@ static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) UsedAttr());
+ d->addAttr(S.Context, ::new (S.Context) UsedAttr());
}
static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -524,7 +519,7 @@ static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) ConstructorAttr(priority));
+ d->addAttr(S.Context, ::new (S.Context) ConstructorAttr(priority));
}
static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -553,7 +548,7 @@ static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) DestructorAttr(priority));
+ d->addAttr(S.Context, ::new (S.Context) DestructorAttr(priority));
}
static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -563,7 +558,7 @@ static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) DeprecatedAttr());
+ d->addAttr(S.Context, ::new (S.Context) DeprecatedAttr());
}
static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -573,7 +568,7 @@ static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) UnavailableAttr());
+ d->addAttr(S.Context, ::new (S.Context) UnavailableAttr());
}
static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -610,7 +605,7 @@ static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) VisibilityAttr(type));
+ d->addAttr(S.Context, ::new (S.Context) VisibilityAttr(type));
}
static void HandleObjCExceptionAttr(Decl *D, const AttributeList &Attr,
@@ -626,7 +621,7 @@ static void HandleObjCExceptionAttr(Decl *D, const AttributeList &Attr,
return;
}
- D->addAttr(::new (S.Context) ObjCExceptionAttr());
+ D->addAttr(S.Context, ::new (S.Context) ObjCExceptionAttr());
}
static void HandleObjCNSObject(Decl *D, const AttributeList &Attr, Sema &S) {
@@ -642,7 +637,7 @@ static void HandleObjCNSObject(Decl *D, const AttributeList &Attr, Sema &S) {
return;
}
}
- D->addAttr(::new (S.Context) ObjCNSObjectAttr());
+ D->addAttr(S.Context, ::new (S.Context) ObjCNSObjectAttr());
}
static void
@@ -657,7 +652,7 @@ HandleOverloadableAttr(Decl *D, const AttributeList &Attr, Sema &S) {
return;
}
- D->addAttr(::new (S.Context) OverloadableAttr());
+ D->addAttr(S.Context, ::new (S.Context) OverloadableAttr());
}
static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -681,7 +676,7 @@ static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) BlocksAttr(type));
+ d->addAttr(S.Context, ::new (S.Context) BlocksAttr(type));
}
static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -773,7 +768,7 @@ static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) {
<< Attr.getName() << 6 /*function, method or block */;
return;
}
- d->addAttr(::new (S.Context) SentinelAttr(sentinel, nullPos));
+ d->addAttr(S.Context, ::new (S.Context) SentinelAttr(sentinel, nullPos));
}
static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S) {
@@ -791,7 +786,7 @@ static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S)
return;
}
- Fn->addAttr(::new (S.Context) WarnUnusedResultAttr());
+ Fn->addAttr(S.Context, ::new (S.Context) WarnUnusedResultAttr());
}
static void HandleWeakAttr(Decl *D, const AttributeList &Attr, Sema &S) {
@@ -808,7 +803,7 @@ static void HandleWeakAttr(Decl *D, const AttributeList &Attr, Sema &S) {
return;
}
- D->addAttr(::new (S.Context) WeakAttr());
+ D->addAttr(S.Context, ::new (S.Context) WeakAttr());
}
static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
@@ -841,7 +836,7 @@ static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
return;
}
- D->addAttr(::new (S.Context) WeakImportAttr());
+ D->addAttr(S.Context, ::new (S.Context) WeakImportAttr());
}
static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
@@ -853,7 +848,7 @@ static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
// Attribute can be applied only to functions or variables.
if (isa<VarDecl>(D)) {
- D->addAttr(::new (S.Context) DLLImportAttr());
+ D->addAttr(S.Context, ::new (S.Context) DLLImportAttr());
return;
}
@@ -881,12 +876,12 @@ static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
}
}
- if (D->getAttr<DLLExportAttr>()) {
+ if (D->getAttr<DLLExportAttr>(S.Context)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
return;
}
- D->addAttr(::new (S.Context) DLLImportAttr());
+ D->addAttr(S.Context, ::new (S.Context) DLLImportAttr());
}
static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
@@ -898,7 +893,7 @@ static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
// Attribute can be applied only to functions or variables.
if (isa<VarDecl>(D)) {
- D->addAttr(::new (S.Context) DLLExportAttr());
+ D->addAttr(S.Context, ::new (S.Context) DLLExportAttr());
return;
}
@@ -917,7 +912,7 @@ static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
return;
}
- D->addAttr(::new (S.Context) DLLExportAttr());
+ D->addAttr(S.Context, ::new (S.Context) DLLExportAttr());
}
static void HandleSectionAttr(Decl *D, const AttributeList &Attr, Sema &S) {
@@ -936,7 +931,8 @@ static void HandleSectionAttr(Decl *D, const AttributeList &Attr, Sema &S) {
S.Diag(Attr.getLoc(), diag::err_attribute_annotate_no_string);
return;
}
- D->addAttr(::new (S.Context) SectionAttr(std::string(SE->getStrData(),
+ D->addAttr(S.Context,
+ ::new (S.Context) SectionAttr(std::string(SE->getStrData(),
SE->getByteLength())));
}
@@ -955,13 +951,13 @@ static void HandleStdCallAttr(Decl *d, const AttributeList &Attr, Sema &S) {
}
// stdcall and fastcall attributes are mutually incompatible.
- if (d->getAttr<FastCallAttr>()) {
+ if (d->getAttr<FastCallAttr>(S.Context)) {
S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
<< "stdcall" << "fastcall";
return;
}
- d->addAttr(::new (S.Context) StdCallAttr());
+ d->addAttr(S.Context, ::new (S.Context) StdCallAttr());
}
static void HandleFastCallAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -978,13 +974,13 @@ static void HandleFastCallAttr(Decl *d, const AttributeList &Attr, Sema &S) {
}
// stdcall and fastcall attributes are mutually incompatible.
- if (d->getAttr<StdCallAttr>()) {
+ if (d->getAttr<StdCallAttr>(S.Context)) {
S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
<< "fastcall" << "stdcall";
return;
}
- d->addAttr(::new (S.Context) FastCallAttr());
+ d->addAttr(S.Context, ::new (S.Context) FastCallAttr());
}
static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -994,7 +990,7 @@ static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) NoThrowAttr());
+ d->addAttr(S.Context, ::new (S.Context) NoThrowAttr());
}
static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -1004,7 +1000,7 @@ static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) ConstAttr());
+ d->addAttr(S.Context, ::new (S.Context) ConstAttr());
}
static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -1014,7 +1010,7 @@ static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) PureAttr());
+ d->addAttr(S.Context, ::new (S.Context) PureAttr());
}
static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -1072,7 +1068,7 @@ static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) CleanupAttr(FD));
+ d->addAttr(S.Context, ::new (S.Context) CleanupAttr(FD));
}
/// Handle __attribute__((format_arg((idx)))) attribute
@@ -1135,7 +1131,7 @@ static void HandleFormatArgAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) FormatArgAttr(Idx.getZExtValue()));
+ d->addAttr(S.Context, ::new (S.Context) FormatArgAttr(Idx.getZExtValue()));
}
/// Handle __attribute__((format(type,idx,firstarg))) attributes
@@ -1276,7 +1272,8 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) FormatAttr(std::string(Format, FormatLen),
+ d->addAttr(S.Context,
+ ::new (S.Context) FormatAttr(std::string(Format, FormatLen),
Idx.getZExtValue(), FirstArg.getZExtValue()));
}
@@ -1344,7 +1341,7 @@ static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr,
}
}
- RD->addAttr(::new (S.Context) TransparentUnionAttr());
+ RD->addAttr(S.Context, ::new (S.Context) TransparentUnionAttr());
}
static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -1362,7 +1359,8 @@ static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) {
S.Diag(Attr.getLoc(), diag::err_attribute_annotate_no_string);
return;
}
- d->addAttr(::new (S.Context) AnnotateAttr(std::string(SE->getStrData(),
+ d->addAttr(S.Context,
+ ::new (S.Context) AnnotateAttr(std::string(SE->getStrData(),
SE->getByteLength())));
}
@@ -1378,7 +1376,7 @@ static void HandleAlignedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// FIXME: This should be the target specific maximum alignment.
// (For now we just use 128 bits which is the maximum on X86).
Align = 128;
- d->addAttr(::new (S.Context) AlignedAttr(Align));
+ d->addAttr(S.Context, ::new (S.Context) AlignedAttr(Align));
return;
}
@@ -1395,7 +1393,7 @@ static void HandleAlignedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) AlignedAttr(Alignment.getZExtValue() * 8));
+ d->addAttr(S.Context, ::new (S.Context) AlignedAttr(Alignment.getZExtValue() * 8));
}
/// HandleModeAttr - This attribute modifies the width of a decl with
@@ -1576,7 +1574,7 @@ static void HandleNodebugAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) NodebugAttr());
+ d->addAttr(S.Context, ::new (S.Context) NodebugAttr());
}
static void HandleNoinlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -1592,7 +1590,7 @@ static void HandleNoinlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) NoinlineAttr());
+ d->addAttr(S.Context, ::new (S.Context) NoinlineAttr());
}
static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -1614,7 +1612,7 @@ static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) GNUInlineAttr());
+ d->addAttr(S.Context, ::new (S.Context) GNUInlineAttr());
}
static void HandleRegparmAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -1650,7 +1648,8 @@ static void HandleRegparmAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) RegparmAttr(NumParams.getZExtValue()));
+ d->addAttr(S.Context,
+ ::new (S.Context) RegparmAttr(NumParams.getZExtValue()));
}
//===----------------------------------------------------------------------===//
@@ -1683,10 +1682,10 @@ static void HandleNSReturnsRetainedAttr(Decl *d, const AttributeList &Attr,
assert(0 && "invalid ownership attribute");
return;
case AttributeList::AT_cf_returns_retained:
- d->addAttr(::new (S.Context) CFReturnsRetainedAttr());
+ d->addAttr(S.Context, ::new (S.Context) CFReturnsRetainedAttr());
return;
case AttributeList::AT_ns_returns_retained:
- d->addAttr(::new (S.Context) NSReturnsRetainedAttr());
+ d->addAttr(S.Context, ::new (S.Context) NSReturnsRetainedAttr());
return;
};
}
@@ -1698,7 +1697,7 @@ static void HandleNSReturnsRetainedAttr(Decl *d, const AttributeList &Attr,
/// ProcessDeclAttribute - Apply the specific attribute to the specified decl if
/// the attribute applies to decls. If the attribute is a type attribute, just
/// silently ignore it.
-static void ProcessDeclAttribute(Decl *D, const AttributeList &Attr, Sema &S) {
+static void ProcessDeclAttribute(Scope *scope, Decl *D, const AttributeList &Attr, Sema &S) {
if (Attr.isDeclspecAttribute())
// FIXME: Try to deal with __declspec attributes!
return;
@@ -1721,7 +1720,7 @@ static void ProcessDeclAttribute(Decl *D, const AttributeList &Attr, Sema &S) {
case AttributeList::AT_dllexport: HandleDLLExportAttr (D, Attr, S); break;
case AttributeList::AT_dllimport: HandleDLLImportAttr (D, Attr, S); break;
case AttributeList::AT_ext_vector_type:
- HandleExtVectorTypeAttr(D, Attr, S);
+ HandleExtVectorTypeAttr(scope, D, Attr, S);
break;
case AttributeList::AT_fastcall: HandleFastCallAttr (D, Attr, S); break;
case AttributeList::AT_format: HandleFormatAttr (D, Attr, S); break;
@@ -1777,9 +1776,9 @@ static void ProcessDeclAttribute(Decl *D, const AttributeList &Attr, Sema &S) {
/// ProcessDeclAttributeList - Apply all the decl attributes in the specified
/// attribute list to the specified decl, ignoring any type attributes.
-void Sema::ProcessDeclAttributeList(Decl *D, const AttributeList *AttrList) {
+void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AttrList) {
while (AttrList) {
- ProcessDeclAttribute(D, *AttrList, *this);
+ ProcessDeclAttribute(S, D, *AttrList, *this);
AttrList = AttrList->getNext();
}
}
@@ -1787,10 +1786,10 @@ void Sema::ProcessDeclAttributeList(Decl *D, const AttributeList *AttrList) {
/// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in
/// it, apply them to D. This is a bit tricky because PD can have attributes
/// specified in many different places, and we need to find and apply them all.
-void Sema::ProcessDeclAttributes(Decl *D, const Declarator &PD) {
+void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) {
// Apply decl attributes from the DeclSpec if present.
if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes())
- ProcessDeclAttributeList(D, Attrs);
+ ProcessDeclAttributeList(S, D, Attrs);
// Walk the declarator structure, applying decl attributes that were in a type
// position to the decl itself. This handles cases like:
@@ -1798,9 +1797,9 @@ void Sema::ProcessDeclAttributes(Decl *D, const Declarator &PD) {
// when X is a decl attribute.
for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i)
if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs())
- ProcessDeclAttributeList(D, Attrs);
+ ProcessDeclAttributeList(S, D, Attrs);
// Finally, apply any attributes on the decl itself.
if (const AttributeList *Attrs = PD.getAttributes())
- ProcessDeclAttributeList(D, Attrs);
+ ProcessDeclAttributeList(S, D, Attrs);
}
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 8f64e78..6d740eb 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -147,8 +147,11 @@ Sema::ActOnParamDefaultArgument(DeclPtrTy param, SourceLocation EqualLoc,
return;
}
+ DefaultArgPtr = MaybeCreateCXXExprWithTemporaries(DefaultArg.take(),
+ /*DestroyTemps=*/false);
+
// Okay: add the default argument to the parameter
- Param->setDefaultArg(DefaultArg.take());
+ Param->setDefaultArg(DefaultArgPtr);
}
/// ActOnParamUnparsedDefaultArgument - We've seen a default
@@ -1031,9 +1034,6 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
DefaultCon->setAccess(AS_public);
DefaultCon->setImplicit();
ClassDecl->addDecl(Context, DefaultCon);
-
- // Notify the class that we've added a constructor.
- ClassDecl->addedConstructor(Context, DefaultCon);
}
if (!ClassDecl->hasUserDeclaredCopyConstructor()) {
@@ -1110,8 +1110,6 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
/*IdentifierInfo=*/0,
ArgType, VarDecl::None, 0);
CopyConstructor->setParams(Context, &FromParam, 1);
-
- ClassDecl->addedConstructor(Context, CopyConstructor);
ClassDecl->addDecl(Context, CopyConstructor);
}
@@ -1750,6 +1748,43 @@ void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) {
S->PushUsingDirective(DeclPtrTy::make(UDir));
}
+
+Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S,
+ SourceLocation UsingLoc,
+ const CXXScopeSpec &SS,
+ SourceLocation IdentLoc,
+ IdentifierInfo *TargetName,
+ AttributeList *AttrList,
+ bool IsTypeName) {
+ assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
+ assert(TargetName && "Invalid TargetName.");
+ assert(IdentLoc.isValid() && "Invalid TargetName location.");
+ assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");
+
+ UsingDecl *UsingAlias = 0;
+
+ // Lookup target name.
+ LookupResult R = LookupParsedName(S, &SS, TargetName,
+ LookupOrdinaryName, false);
+
+ if (NamedDecl *NS = R) {
+ if (IsTypeName && !isa<TypeDecl>(NS)) {
+ Diag(IdentLoc, diag::err_using_typename_non_type);
+ }
+ UsingAlias = UsingDecl::Create(Context, CurContext, IdentLoc, SS.getRange(),
+ NS->getLocation(), UsingLoc, NS,
+ static_cast<NestedNameSpecifier *>(SS.getScopeRep()),
+ IsTypeName);
+ PushOnScopeChains(UsingAlias, S);
+ } else {
+ Diag(IdentLoc, diag::err_using_requires_qualname) << SS.getRange();
+ }
+
+ // FIXME: We ignore attributes for now.
+ delete AttrList;
+ return DeclPtrTy::make(UsingAlias);
+}
+
/// getNamespaceDecl - Returns the namespace a decl represents. If the decl
/// is a namespace alias, returns the namespace it points to.
static inline NamespaceDecl *getNamespaceDecl(NamedDecl *D) {
@@ -1795,7 +1830,7 @@ Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S,
return DeclPtrTy();
}
- NamespaceAliasDecl *AliasDecl =
+ NamespaceAliasDecl *AliasDecl =
NamespaceAliasDecl::Create(Context, CurContext, NamespaceLoc, AliasLoc,
Alias, SS.getRange(),
(NestedNameSpecifier *)SS.getScopeRep(),
@@ -1805,6 +1840,81 @@ Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S,
return DeclPtrTy::make(AliasDecl);
}
+void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
+ CXXConstructorDecl *Constructor) {
+ if (!Constructor->isDefaultConstructor() ||
+ !Constructor->isImplicit() || Constructor->isImplicitMustBeDefined())
+ return;
+
+ CXXRecordDecl *ClassDecl
+ = cast<CXXRecordDecl>(Constructor->getDeclContext());
+ assert(ClassDecl && "InitializeVarWithConstructor - invalid constructor");
+ // Before the implicitly-declared default constructor for a class is
+ // implicitly defined, all the implicitly-declared default constructors
+ // for its base class and its non-static data members shall have been
+ // implicitly defined.
+ bool err = false;
+ for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin();
+ Base != ClassDecl->bases_end(); ++Base) {
+ CXXRecordDecl *BaseClassDecl
+ = cast<CXXRecordDecl>(Base->getType()->getAsRecordType()->getDecl());
+ if (!BaseClassDecl->hasTrivialConstructor()) {
+ if (CXXConstructorDecl *BaseCtor =
+ BaseClassDecl->getDefaultConstructor(Context)) {
+ if (BaseCtor->isImplicit())
+ BaseCtor->setImplicitMustBeDefined();
+ }
+ else {
+ Diag(CurrentLocation, diag::err_defining_default_ctor)
+ << Context.getTagDeclType(ClassDecl) << 1
+ << Context.getTagDeclType(BaseClassDecl);
+ Diag(BaseClassDecl->getLocation(), diag::note_previous_class_decl)
+ << Context.getTagDeclType(BaseClassDecl);
+ err = true;
+ }
+ }
+ }
+ for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(Context);
+ Field != ClassDecl->field_end(Context);
+ ++Field) {
+ QualType FieldType = Context.getCanonicalType((*Field)->getType());
+ if (const ArrayType *Array = Context.getAsArrayType(FieldType))
+ FieldType = Array->getElementType();
+ if (const RecordType *FieldClassType = FieldType->getAsRecordType()) {
+ CXXRecordDecl *FieldClassDecl
+ = cast<CXXRecordDecl>(FieldClassType->getDecl());
+ if (!FieldClassDecl->hasTrivialConstructor())
+ if (CXXConstructorDecl *FieldCtor =
+ FieldClassDecl->getDefaultConstructor(Context)) {
+ if (FieldCtor->isImplicit())
+ FieldCtor->setImplicitMustBeDefined();
+ }
+ else {
+ Diag(CurrentLocation, diag::err_defining_default_ctor)
+ << Context.getTagDeclType(ClassDecl) << 0 <<
+ Context.getTagDeclType(FieldClassDecl);
+ Diag(FieldClassDecl->getLocation(), diag::note_previous_class_decl)
+ << Context.getTagDeclType(FieldClassDecl);
+ err = true;
+ }
+ }
+ else if (FieldType->isReferenceType()) {
+ Diag(CurrentLocation, diag::err_unintialized_member)
+ << Context.getTagDeclType(ClassDecl) << 0 << (*Field)->getNameAsCString();
+ Diag((*Field)->getLocation(), diag::note_declared_at);
+ err = true;
+ }
+ else if (FieldType.isConstQualified()) {
+ Diag(CurrentLocation, diag::err_unintialized_member)
+ << Context.getTagDeclType(ClassDecl) << 1 << (*Field)->getNameAsCString();
+ Diag((*Field)->getLocation(), diag::note_declared_at);
+ err = true;
+ }
+ }
+ if (!err)
+ Constructor->setImplicitMustBeDefined();
+}
+
void Sema::InitializeVarWithConstructor(VarDecl *VD,
CXXConstructorDecl *Constructor,
QualType DeclInitType,
@@ -1880,6 +1990,9 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl,
VDecl->setCXXDirectInitializer(true);
InitializeVarWithConstructor(VDecl, Constructor, DeclInitType,
(Expr**)Exprs.release(), NumExprs);
+ // An implicitly-declared default constructor for a class is implicitly
+ // defined when it is used to creat an object of its class type.
+ DefineImplicitDefaultConstructor(VDecl->getLocation(), Constructor);
}
return;
}
@@ -1956,7 +2069,7 @@ Sema::PerformInitializationByConstructor(QualType ClassType,
// constructors, we'll need to make them appear here.
OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(CandidateSet, Best)) {
+ switch (BestViableFunction(CandidateSet, Loc, Best)) {
case OR_Success:
// We found a constructor. Return it.
return cast<CXXConstructorDecl>(Best->Function);
@@ -2188,7 +2301,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
}
OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(CandidateSet, Best)) {
+ switch (BestViableFunction(CandidateSet, Init->getLocStart(), Best)) {
case OR_Success:
// This is a direct binding.
BindsDirectly = true;
@@ -2668,7 +2781,7 @@ Sema::DeclPtrTy Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) {
else
CurContext->addDecl(Context, ExDecl);
- ProcessDeclAttributes(ExDecl, D);
+ ProcessDeclAttributes(S, ExDecl, D);
return DeclPtrTy::make(ExDecl);
}
@@ -2830,3 +2943,46 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
return false;
}
+
+/// 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.
+void Sema::ActOnCXXEnterDeclInitializer(Scope *S, DeclPtrTy Dcl) {
+ Decl *D = Dcl.getAs<Decl>();
+ // If there is no declaration, there was an error parsing it.
+ if (D == 0)
+ return;
+
+ // Check whether it is a declaration with a nested name specifier like
+ // int foo::bar;
+ if (!D->isOutOfLine())
+ return;
+
+ // C++ [basic.lookup.unqual]p13
+ //
+ // A name used in the definition of a static data member of class X
+ // (after the qualified-id of the static member) is looked up as if the name
+ // was used in a member function of X.
+
+ // Change current context into the context of the initializing declaration.
+ EnterDeclaratorContext(S, D->getDeclContext());
+}
+
+/// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an
+/// initializer for the declaration 'Dcl'.
+void Sema::ActOnCXXExitDeclInitializer(Scope *S, DeclPtrTy Dcl) {
+ Decl *D = Dcl.getAs<Decl>();
+ // If there is no declaration, there was an error parsing it.
+ if (D == 0)
+ return;
+
+ // Check whether it is a declaration with a nested name specifier like
+ // int foo::bar;
+ if (!D->isOutOfLine())
+ return;
+
+ assert(S->getEntity() == D->getDeclContext() && "Context imbalance!");
+ ExitDeclaratorContext(S);
+}
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 5d47516..9013726 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -116,7 +116,7 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc,
ClassName, ClassLoc);
if (AttrList)
- ProcessDeclAttributeList(IDecl, AttrList);
+ ProcessDeclAttributeList(TUScope, IDecl, AttrList);
PushOnScopeChains(IDecl, TUScope);
}
@@ -282,7 +282,7 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,
PDecl->setForwardDecl(false);
}
if (AttrList)
- ProcessDeclAttributeList(PDecl, AttrList);
+ ProcessDeclAttributeList(TUScope, PDecl, AttrList);
if (NumProtoRefs) {
/// Check then save referenced protocols.
PDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs,Context);
@@ -532,7 +532,7 @@ Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc,
PushOnScopeChains(PDecl, TUScope);
}
if (attrList)
- ProcessDeclAttributeList(PDecl, attrList);
+ ProcessDeclAttributeList(TUScope, PDecl, attrList);
Protocols.push_back(PDecl);
}
@@ -1663,7 +1663,7 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
CvtQTToAstBitMask(ArgInfo[i].DeclSpec.getObjCDeclQualifier()));
// Apply the attributes to the parameter.
- ProcessDeclAttributeList(Param, ArgInfo[i].ArgAttrs);
+ ProcessDeclAttributeList(TUScope, Param, ArgInfo[i].ArgAttrs);
Params.push_back(Param);
}
@@ -1674,7 +1674,7 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
const ObjCMethodDecl *PrevMethod = 0;
if (AttrList)
- ProcessDeclAttributeList(ObjCMethod, AttrList);
+ ProcessDeclAttributeList(TUScope, ObjCMethod, AttrList);
// For implementations (which can be very "coarse grain"), we add the
// method now. This allows the AST to implement lookup methods that work
@@ -1877,7 +1877,7 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
PDecl->setInvalidDecl();
}
- ProcessDeclAttributes(PDecl, FD.D);
+ ProcessDeclAttributes(S, PDecl, FD.D);
// Regardless of setter/getter attribute, we save the default getter/setter
// selector names in anticipation of declaration of setter/getter methods.
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index c01c812..692502b 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -39,7 +39,7 @@ using namespace clang;
/// referenced), false otherwise.
bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) {
// See if the decl is deprecated.
- if (D->getAttr<DeprecatedAttr>()) {
+ if (D->getAttr<DeprecatedAttr>(Context)) {
// Implementing deprecated stuff requires referencing deprecated
// stuff. Don't warn if we are implementing a deprecated
// construct.
@@ -48,7 +48,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) {
if (NamedDecl *ND = getCurFunctionOrMethodDecl()) {
// If this reference happens *in* a deprecated function or method, don't
// warn.
- isSilenced = ND->getAttr<DeprecatedAttr>();
+ isSilenced = ND->getAttr<DeprecatedAttr>(Context);
// If this is an Objective-C method implementation, check to see if the
// method was deprecated on the declaration, not the definition.
@@ -61,7 +61,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) {
MD = Impl->getClassInterface()->getMethod(Context,
MD->getSelector(),
MD->isInstanceMethod());
- isSilenced |= MD && MD->getAttr<DeprecatedAttr>();
+ isSilenced |= MD && MD->getAttr<DeprecatedAttr>(Context);
}
}
}
@@ -80,7 +80,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) {
}
// See if the decl is unavailable
- if (D->getAttr<UnavailableAttr>()) {
+ if (D->getAttr<UnavailableAttr>(Context)) {
Diag(Loc, diag::warn_unavailable) << D->getDeclName();
Diag(D->getLocation(), diag::note_unavailable_here) << 0;
}
@@ -95,7 +95,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) {
void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
Expr **Args, unsigned NumArgs)
{
- const SentinelAttr *attr = D->getAttr<SentinelAttr>();
+ const SentinelAttr *attr = D->getAttr<SentinelAttr>(Context);
if (!attr)
return;
int sentinelPos = attr->getSentinel();
@@ -627,6 +627,7 @@ DeclRefExpr *
Sema::BuildDeclRefExpr(NamedDecl *D, QualType Ty, SourceLocation Loc,
bool TypeDependent, bool ValueDependent,
const CXXScopeSpec *SS) {
+ MarkDeclarationReferenced(Loc, D);
if (SS && !SS->isEmpty()) {
return new (Context) QualifiedDeclRefExpr(D, Ty, Loc, TypeDependent,
ValueDependent, SS->getRange(),
@@ -721,6 +722,7 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
// BaseObject is an anonymous struct/union variable (and is,
// therefore, not part of another non-anonymous record).
if (BaseObjectExpr) BaseObjectExpr->Destroy(Context);
+ MarkDeclarationReferenced(Loc, BaseObject);
BaseObjectExpr = new (Context) DeclRefExpr(BaseObject,BaseObject->getType(),
SourceLocation());
ExtraQuals
@@ -777,6 +779,7 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
= MemberType.getCVRQualifiers() | ExtraQuals;
MemberType = MemberType.getQualifiedType(combinedQualifiers);
}
+ MarkDeclarationReferenced(Loc, *FI);
Result = new (Context) MemberExpr(Result, BaseObjectIsPointer, *FI,
OpLoc, MemberType);
BaseObjectIsPointer = false;
@@ -876,6 +879,7 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
// turn this into Self->ivar, just return a BareIVarExpr or something.
IdentifierInfo &II = Context.Idents.get("self");
OwningExprResult SelfExpr = ActOnIdentifierExpr(S, Loc, II, false);
+ MarkDeclarationReferenced(Loc, IV);
return Owned(new (Context)
ObjCIvarRefExpr(IV, IV->getType(), Loc,
SelfExpr.takeAs<Expr>(), true, true));
@@ -1025,6 +1029,7 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
// Build the implicit member access expression.
Expr *This = new (Context) CXXThisExpr(SourceLocation(),
MD->getThisType(Context));
+ MarkDeclarationReferenced(Loc, D);
return Owned(new (Context) MemberExpr(This, true, D,
Loc, MemberType));
}
@@ -1125,14 +1130,18 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
// as they do not get snapshotted.
//
if (CurBlock && ShouldSnapshotBlockValueReference(CurBlock, VD)) {
+ MarkDeclarationReferenced(Loc, VD);
QualType ExprTy = VD->getType().getNonReferenceType();
// The BlocksAttr indicates the variable is bound by-reference.
- if (VD->getAttr<BlocksAttr>())
+ if (VD->getAttr<BlocksAttr>(Context))
return Owned(new (Context) BlockDeclRefExpr(VD, ExprTy, Loc, true));
-
+ // This is to record that a 'const' was actually synthesize and added.
+ bool constAdded = !ExprTy.isConstQualified();
// Variable will be bound by-copy, make it const within the closure.
+
ExprTy.addConst();
- return Owned(new (Context) BlockDeclRefExpr(VD, ExprTy, Loc, false));
+ return Owned(new (Context) BlockDeclRefExpr(VD, ExprTy, Loc, false,
+ constAdded));
}
// If this reference is not in a block or if the referenced variable is
// within the block, create a normal DeclRefExpr.
@@ -1576,7 +1585,7 @@ Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
// Perform overload resolution.
OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(CandidateSet, Best)) {
+ switch (BestViableFunction(CandidateSet, OpLoc, Best)) {
case OR_Success: {
// We found a built-in operator or an overloaded operator.
FunctionDecl *FnDecl = Best->Function;
@@ -1686,7 +1695,7 @@ Sema::ActOnArraySubscriptExpr(Scope *S, ExprArg Base, SourceLocation LLoc,
// Perform overload resolution.
OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(CandidateSet, Best)) {
+ switch (BestViableFunction(CandidateSet, LLoc, Best)) {
case OR_Success: {
// We found a built-in operator or an overloaded operator.
FunctionDecl *FnDecl = Best->Function;
@@ -1969,13 +1978,13 @@ static Decl *FindGetterNameDeclFromProtocolList(const ObjCProtocolDecl*PDecl,
return 0;
}
-static Decl *FindGetterNameDecl(const ObjCQualifiedIdType *QIdTy,
+static Decl *FindGetterNameDecl(const ObjCObjectPointerType *QIdTy,
IdentifierInfo &Member,
const Selector &Sel,
ASTContext &Context) {
// Check protocols on qualified interfaces.
Decl *GDecl = 0;
- for (ObjCQualifiedIdType::qual_iterator I = QIdTy->qual_begin(),
+ for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(),
E = QIdTy->qual_end(); I != E; ++I) {
if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Context, &Member)) {
GDecl = PD;
@@ -1988,7 +1997,7 @@ static Decl *FindGetterNameDecl(const ObjCQualifiedIdType *QIdTy,
}
}
if (!GDecl) {
- for (ObjCQualifiedIdType::qual_iterator I = QIdTy->qual_begin(),
+ for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(),
E = QIdTy->qual_end(); I != E; ++I) {
// Search in the protocol-qualifier list of current protocol.
GDecl = FindGetterNameDeclFromProtocolList(*I, Member, Sel, Context);
@@ -2313,7 +2322,7 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
<< &Member << BaseType);
}
// Handle properties on qualified "id" protocols.
- const ObjCQualifiedIdType *QIdTy;
+ const ObjCObjectPointerType *QIdTy;
if (OpKind == tok::period && (QIdTy = BaseType->getAsObjCQualifiedIdType())) {
// Check protocols on qualified interfaces.
Selector Sel = PP.getSelectorTable().getNullarySelector(&Member);
@@ -2491,8 +2500,21 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
FDecl << cast<CXXRecordDecl>(FDecl->getDeclContext())->getDeclName();
Diag(UnparsedDefaultArgLocs[FDecl->getParamDecl(i)],
diag::note_default_argument_declared_here);
+ } else {
+ Expr *DefaultExpr = FDecl->getParamDecl(i)->getDefaultArg();
+
+ // If the default expression creates temporaries, we need to
+ // push them to the current stack of expression temporaries so they'll
+ // be properly destroyed.
+ if (CXXExprWithTemporaries *E
+ = dyn_cast_or_null<CXXExprWithTemporaries>(DefaultExpr)) {
+ assert(!E->shouldDestroyTemporaries() &&
+ "Can't destroy temporaries in a default argument expr!");
+ for (unsigned I = 0, N = E->getNumTemporaries(); I != N; ++I)
+ ExprTemporaries.push_back(E->getTemporary(I));
+ }
}
-
+
// We already type-checked the argument, so we know it works.
Arg = new (Context) CXXDefaultArgExpr(FDecl->getParamDecl(i));
}
@@ -3395,7 +3417,7 @@ Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType, Expr *&rExpr) {
// If the ArgType is a Union type, we want to handle a potential
// transparent_union GCC extension.
const RecordType *UT = ArgType->getAsUnionType();
- if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>())
+ if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>(Context))
return Incompatible;
// The field to initialize within the transparent union.
@@ -5098,7 +5120,7 @@ void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *BlockScope) {
BSI->PrevBlockInfo = CurBlock;
CurBlock = BSI;
- BSI->ReturnType = 0;
+ BSI->ReturnType = QualType();
BSI->TheScope = BlockScope;
BSI->hasBlockDeclRefExprs = false;
BSI->SavedFunctionNeedsScopeChecking = CurFunctionNeedsScopeChecking;
@@ -5113,7 +5135,7 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {
if (ParamInfo.getNumTypeObjects() == 0
|| ParamInfo.getTypeObject(0).Kind != DeclaratorChunk::Function) {
- ProcessDeclAttributes(CurBlock->TheDecl, ParamInfo);
+ ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo);
QualType T = GetTypeForDeclarator(ParamInfo, CurScope);
if (T->isArrayType()) {
@@ -5129,7 +5151,7 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {
CurBlock->hasPrototype = true;
CurBlock->isVariadic = false;
// Check for a valid sentinel attribute on this block.
- if (CurBlock->TheDecl->getAttr<SentinelAttr>()) {
+ if (CurBlock->TheDecl->getAttr<SentinelAttr>(Context)) {
Diag(ParamInfo.getAttributes()->getLoc(),
diag::warn_attribute_sentinel_not_variadic) << 1;
// FIXME: remove the attribute.
@@ -5169,7 +5191,7 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {
CurBlock->TheDecl->setParams(Context, CurBlock->Params.data(),
CurBlock->Params.size());
CurBlock->TheDecl->setIsVariadic(CurBlock->isVariadic);
- ProcessDeclAttributes(CurBlock->TheDecl, ParamInfo);
+ ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo);
for (BlockDecl::param_iterator AI = CurBlock->TheDecl->param_begin(),
E = CurBlock->TheDecl->param_end(); AI != E; ++AI)
// If this has an identifier, add it to the scope stack.
@@ -5177,7 +5199,8 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {
PushOnScopeChains(*AI, CurBlock->TheScope);
// Check for a valid sentinel attribute on this block.
- if (!CurBlock->isVariadic && CurBlock->TheDecl->getAttr<SentinelAttr>()) {
+ if (!CurBlock->isVariadic &&
+ CurBlock->TheDecl->getAttr<SentinelAttr>(Context)) {
Diag(ParamInfo.getAttributes()->getLoc(),
diag::warn_attribute_sentinel_not_variadic) << 1;
// FIXME: remove the attribute.
@@ -5192,7 +5215,7 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {
Diag(ParamInfo.getSourceRange().getBegin(),
diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy;
} else if (!RetTy->isDependentType())
- CurBlock->ReturnType = RetTy.getTypePtr();
+ CurBlock->ReturnType = RetTy;
}
/// ActOnBlockError - If there is an error parsing a block, this callback
@@ -5226,8 +5249,8 @@ Sema::OwningExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
CurBlock = CurBlock->PrevBlockInfo;
QualType RetTy = Context.VoidTy;
- if (BSI->ReturnType)
- RetTy = QualType(BSI->ReturnType, 0);
+ if (!BSI->ReturnType.isNull())
+ RetTy = BSI->ReturnType;
llvm::SmallVector<QualType, 8> ArgTypes;
for (unsigned i = 0, e = BSI->Params.size(); i != e; ++i)
@@ -5241,7 +5264,7 @@ Sema::OwningExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
BSI->isVariadic, 0);
// FIXME: Check that return/parameter types are complete/non-abstract
-
+ DiagnoseUnusedParameters(BSI->Params.begin(), BSI->Params.end());
BlockTy = Context.getBlockPointerType(BlockTy);
// If needed, diagnose invalid gotos and switches in the block.
@@ -5408,3 +5431,49 @@ bool Sema::VerifyIntegerConstantExpression(const Expr *E, llvm::APSInt *Result){
*Result = EvalResult.Val.getInt();
return false;
}
+
+
+/// \brief Note that the given declaration was referenced in the source code.
+///
+/// This routine should be invoke whenever a given declaration is referenced
+/// in the source code, and where that reference occurred. If this declaration
+/// reference means that the the declaration is used (C++ [basic.def.odr]p2,
+/// C99 6.9p3), then the declaration will be marked as used.
+///
+/// \param Loc the location where the declaration was referenced.
+///
+/// \param D the declaration that has been referenced by the source code.
+void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
+ assert(D && "No declaration?");
+
+ // Mark a parameter declaration "used", regardless of whether we're in a
+ // template or not.
+ if (isa<ParmVarDecl>(D))
+ D->setUsed(true);
+
+ // Do not mark anything as "used" within a dependent context; wait for
+ // an instantiation.
+ if (CurContext->isDependentContext())
+ return;
+
+ // If we are in an unevaluated operand, don't mark any definitions as used.
+ if (InUnevaluatedOperand)
+ return;
+
+ // Note that this declaration has been used.
+ if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
+ // FIXME: implicit template instantiation
+ // FIXME: keep track of references to static functions
+ (void)Function;
+ Function->setUsed(true);
+ return;
+ }
+
+ if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
+ (void)Var;
+ // FIXME: implicit template instantiation
+ // FIXME: keep track of references to static data?
+ D->setUsed(true);
+ }
+}
+
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index ed4ac55..bec595c 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -546,7 +546,7 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
// Do the resolution.
OverloadCandidateSet::iterator Best;
- switch(BestViableFunction(Candidates, Best)) {
+ switch(BestViableFunction(Candidates, StartLoc, Best)) {
case OR_Success: {
// Got one!
FunctionDecl *FnDecl = Best->Function;
@@ -1175,7 +1175,7 @@ static bool FindConditionalOverload(Sema &Self, Expr *&LHS, Expr *&RHS,
Self.AddBuiltinOperatorCandidates(OO_Conditional, Args, 2, CandidateSet);
OverloadCandidateSet::iterator Best;
- switch (Self.BestViableFunction(CandidateSet, Best)) {
+ switch (Self.BestViableFunction(CandidateSet, Loc, Best)) {
case Sema::OR_Success:
// We found a match. Perform the conversions on the arguments and move on.
if (Self.PerformImplicitConversion(LHS, Best->BuiltinTypes.ParamTypes[0],
@@ -1589,7 +1589,7 @@ Expr *Sema::RemoveOutermostTemporaryBinding(Expr *E) {
}
Expr *Sema::MaybeCreateCXXExprWithTemporaries(Expr *SubExpr,
- bool DestroyTemps) {
+ bool ShouldDestroyTemps) {
assert(SubExpr && "sub expression can't be null!");
if (ExprTemporaries.empty())
@@ -1598,7 +1598,7 @@ Expr *Sema::MaybeCreateCXXExprWithTemporaries(Expr *SubExpr,
Expr *E = CXXExprWithTemporaries::Create(Context, SubExpr,
&ExprTemporaries[0],
ExprTemporaries.size(),
- DestroyTemps);
+ ShouldDestroyTemps);
ExprTemporaries.clear();
return E;
@@ -1607,7 +1607,8 @@ Expr *Sema::MaybeCreateCXXExprWithTemporaries(Expr *SubExpr,
Sema::OwningExprResult Sema::ActOnFinishFullExpr(ExprArg Arg) {
Expr *FullExpr = Arg.takeAs<Expr>();
if (FullExpr)
- FullExpr = MaybeCreateCXXExprWithTemporaries(FullExpr);
+ FullExpr = MaybeCreateCXXExprWithTemporaries(FullExpr,
+ /*ShouldDestroyTemps=*/true);
return Owned(FullExpr);
}
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index b6cf9d8..f1869f9 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -130,6 +130,14 @@ Sema::ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
SourceLocation SelLoc,
SourceLocation LParenLoc,
SourceLocation RParenLoc) {
+ ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(Sel,
+ SourceRange(LParenLoc, RParenLoc));
+ if (!Method)
+ Method = LookupFactoryMethodInGlobalPool(Sel,
+ SourceRange(LParenLoc, RParenLoc));
+ if (!Method)
+ Diag(SelLoc, diag::warn_undeclared_selector) << Sel;
+
QualType Ty = Context.getObjCSelType();
return new (Context) ObjCSelectorExpr(Ty, Sel, AtLoc, RParenLoc);
}
@@ -582,9 +590,10 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
// We allow sending a message to a qualified ID ("id<foo>"), which is ok as
// long as one of the protocols implements the selector (if not, warn).
- if (ObjCQualifiedIdType *QIdTy = dyn_cast<ObjCQualifiedIdType>(ReceiverCType)) {
+ if (const ObjCObjectPointerType *QIdTy =
+ ReceiverCType->getAsObjCQualifiedIdType()) {
// Search protocols for instance methods.
- for (ObjCQualifiedIdType::qual_iterator I = QIdTy->qual_begin(),
+ for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(),
E = QIdTy->qual_end(); I != E; ++I) {
ObjCProtocolDecl *PDecl = *I;
if (PDecl && (Method = PDecl->lookupInstanceMethod(Context, Sel)))
@@ -746,8 +755,8 @@ bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
return true;
}
- if (const ObjCQualifiedIdType *lhsQID = lhs->getAsObjCQualifiedIdType()) {
- const ObjCQualifiedIdType *rhsQID = rhs->getAsObjCQualifiedIdType();
+ if (const ObjCObjectPointerType *lhsQID = lhs->getAsObjCQualifiedIdType()) {
+ const ObjCObjectPointerType *rhsQID = rhs->getAsObjCQualifiedIdType();
const ObjCQualifiedInterfaceType *rhsQI = 0;
QualType rtype;
@@ -762,7 +771,7 @@ bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
// make sure we check the class hierarchy.
if (const ObjCInterfaceType *IT = rtype->getAsObjCInterfaceType()) {
ObjCInterfaceDecl *rhsID = IT->getDecl();
- for (ObjCQualifiedIdType::qual_iterator I = lhsQID->qual_begin(),
+ for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(),
E = lhsQID->qual_end(); I != E; ++I) {
// when comparing an id<P> on lhs with a static type on rhs,
// see if static class implements all of id's protocols, directly or
@@ -775,7 +784,7 @@ bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
}
}
- ObjCQualifiedIdType::qual_iterator RHSProtoI, RHSProtoE;
+ ObjCObjectPointerType::qual_iterator RHSProtoI, RHSProtoE;
if (rhsQI) { // We have a qualified interface (e.g. "NSObject<Proto> *").
RHSProtoI = rhsQI->qual_begin();
RHSProtoE = rhsQI->qual_end();
@@ -786,7 +795,7 @@ bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
return false;
}
- for (ObjCQualifiedIdType::qual_iterator I = lhsQID->qual_begin(),
+ for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(),
E = lhsQID->qual_end(); I != E; ++I) {
ObjCProtocolDecl *lhsProto = *I;
bool match = false;
@@ -807,7 +816,7 @@ bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
// make sure we check the class hierarchy.
if (const ObjCInterfaceType *IT = rtype->getAsObjCInterfaceType()) {
ObjCInterfaceDecl *rhsID = IT->getDecl();
- for (ObjCQualifiedIdType::qual_iterator I = lhsQID->qual_begin(),
+ for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(),
E = lhsQID->qual_end(); I != E; ++I) {
// when comparing an id<P> on lhs with a static type on rhs,
// see if static class implements all of id's protocols, directly or
@@ -826,7 +835,7 @@ bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
return true;
}
- const ObjCQualifiedIdType *rhsQID = rhs->getAsObjCQualifiedIdType();
+ const ObjCObjectPointerType *rhsQID = rhs->getAsObjCQualifiedIdType();
assert(rhsQID && "One of the LHS/RHS should be id<x>");
if (!lhs->isPointerType())
@@ -835,12 +844,12 @@ bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
QualType ltype = lhs->getAsPointerType()->getPointeeType();
if (const ObjCQualifiedInterfaceType *lhsQI =
ltype->getAsObjCQualifiedInterfaceType()) {
- ObjCQualifiedIdType::qual_iterator LHSProtoI = lhsQI->qual_begin();
- ObjCQualifiedIdType::qual_iterator LHSProtoE = lhsQI->qual_end();
+ ObjCObjectPointerType::qual_iterator LHSProtoI = lhsQI->qual_begin();
+ ObjCObjectPointerType::qual_iterator LHSProtoE = lhsQI->qual_end();
for (; LHSProtoI != LHSProtoE; ++LHSProtoI) {
bool match = false;
ObjCProtocolDecl *lhsProto = *LHSProtoI;
- for (ObjCQualifiedIdType::qual_iterator I = rhsQID->qual_begin(),
+ for (ObjCObjectPointerType::qual_iterator I = rhsQID->qual_begin(),
E = rhsQID->qual_end(); I != E; ++I) {
ObjCProtocolDecl *rhsProto = *I;
if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) ||
@@ -859,7 +868,7 @@ bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
// for static type vs. qualified 'id' type, check that class implements
// all of 'id's protocols.
ObjCInterfaceDecl *lhsID = IT->getDecl();
- for (ObjCQualifiedIdType::qual_iterator I = rhsQID->qual_begin(),
+ for (ObjCObjectPointerType::qual_iterator I = rhsQID->qual_begin(),
E = rhsQID->qual_end(); I != E; ++I) {
if (!ClassImplementsProtocol(*I, lhsID, compare, true))
return false;
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 1d26845..37e1df3 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -685,7 +685,7 @@ Sema::CppLookupName(Scope *S, DeclarationName Name,
// identifier chain.
if (isa<RecordDecl>(Ctx)) {
R = LookupQualifiedName(Ctx, Name, NameKind, RedeclarationOnly);
- if (R || RedeclarationOnly)
+ if (R)
return std::make_pair(true, R);
}
if (Ctx->getParent() != Ctx->getLexicalParent()
@@ -697,7 +697,7 @@ Sema::CppLookupName(Scope *S, DeclarationName Name,
for (OutOfLineCtx = Ctx; OutOfLineCtx && !OutOfLineCtx->isFileContext();
OutOfLineCtx = OutOfLineCtx->getParent()) {
R = LookupQualifiedName(OutOfLineCtx, Name, NameKind, RedeclarationOnly);
- if (R || RedeclarationOnly)
+ if (R)
return std::make_pair(true, R);
}
}
@@ -894,7 +894,7 @@ Sema::LookupName(Scope *S, DeclarationName Name, LookupNameKind NameKind,
continue;
}
- if ((*I)->getAttr<OverloadableAttr>()) {
+ if ((*I)->getAttr<OverloadableAttr>(Context)) {
// If this declaration has the "overloadable" attribute, we
// might have a set of overloaded functions.
@@ -1151,8 +1151,10 @@ Sema::LookupParsedName(Scope *S, const CXXScopeSpec *SS,
Name, NameKind, RedeclarationOnly);
}
- return LookupName(S, Name, NameKind, RedeclarationOnly,
- AllowBuiltinCreation, Loc);
+ LookupResult result(LookupName(S, Name, NameKind, RedeclarationOnly,
+ AllowBuiltinCreation, Loc));
+
+ return(result);
}
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 98ee13a..11cd510 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -1379,7 +1379,7 @@ bool Sema::IsUserDefinedConversion(Expr *From, QualType ToType,
}
OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(CandidateSet, Best)) {
+ switch (BestViableFunction(CandidateSet, From->getLocStart(), Best)) {
case OR_Success:
// Record the standard conversion we used and the conversion function.
if (CXXConstructorDecl *Constructor
@@ -3445,14 +3445,21 @@ Sema::isBetterOverloadCandidate(const OverloadCandidate& Cand1,
return false;
}
-/// BestViableFunction - Computes the best viable function (C++ 13.3.3)
-/// within an overload candidate set. If overloading is successful,
-/// the result will be OR_Success and Best will be set to point to the
-/// best viable function within the candidate set. Otherwise, one of
-/// several kinds of errors will be returned; see
-/// Sema::OverloadingResult.
+/// \brief Computes the best viable function (C++ 13.3.3)
+/// within an overload candidate set.
+///
+/// \param CandidateSet the set of candidate functions.
+///
+/// \param Loc the location of the function name (or operator symbol) for
+/// which overload resolution occurs.
+///
+/// \param Best f overload resolution was successful or found a deleted
+/// function, Best points to the candidate function found.
+///
+/// \returns The result of overload resolution.
Sema::OverloadingResult
Sema::BestViableFunction(OverloadCandidateSet& CandidateSet,
+ SourceLocation Loc,
OverloadCandidateSet::iterator& Best)
{
// Find the best viable function.
@@ -3484,12 +3491,17 @@ Sema::BestViableFunction(OverloadCandidateSet& CandidateSet,
// Best is the best viable function.
if (Best->Function &&
(Best->Function->isDeleted() ||
- Best->Function->getAttr<UnavailableAttr>()))
+ Best->Function->getAttr<UnavailableAttr>(Context)))
return OR_Deleted;
- // If Best refers to a function that is either deleted (C++0x) or
- // unavailable (Clang extension) report an error.
-
+ // C++ [basic.def.odr]p2:
+ // An overloaded function is used if it is selected by overload resolution
+ // when referred to from a potentially-evaluated expression. [Note: this
+ // covers calls to named functions (5.2.2), operator overloading
+ // (clause 13), user-defined conversions (12.3.2), allocation function for
+ // placement new (5.3.4), as well as non-default initialization (8.5).
+ if (Best->Function)
+ MarkDeclarationReferenced(Loc, Best->Function);
return OR_Success;
}
@@ -3506,7 +3518,7 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet,
if (Cand->Viable || !OnlyViable) {
if (Cand->Function) {
if (Cand->Function->isDeleted() ||
- Cand->Function->getAttr<UnavailableAttr>()) {
+ Cand->Function->getAttr<UnavailableAttr>(Context)) {
// Deleted or "unavailable" function.
Diag(Cand->Function->getLocation(), diag::err_ovl_candidate_deleted)
<< Cand->Function->isDeleted();
@@ -3709,7 +3721,7 @@ FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee,
CandidateSet);
OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(CandidateSet, Best)) {
+ switch (BestViableFunction(CandidateSet, Fn->getLocStart(), Best)) {
case OR_Success:
return Best->Function;
@@ -3815,7 +3827,7 @@ Sema::OwningExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc,
// Perform overload resolution.
OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(CandidateSet, Best)) {
+ switch (BestViableFunction(CandidateSet, OpLoc, Best)) {
case OR_Success: {
// We found a built-in operator or an overloaded operator.
FunctionDecl *FnDecl = Best->Function;
@@ -3968,7 +3980,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// Perform overload resolution.
OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(CandidateSet, Best)) {
+ switch (BestViableFunction(CandidateSet, OpLoc, Best)) {
case OR_Success: {
// We found a built-in operator or an overloaded operator.
FunctionDecl *FnDecl = Best->Function;
@@ -4094,7 +4106,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
}
OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(CandidateSet, Best)) {
+ switch (BestViableFunction(CandidateSet, MemExpr->getLocStart(), Best)) {
case OR_Success:
Method = cast<CXXMethodDecl>(Best->Function);
break;
@@ -4219,7 +4231,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
// Perform overload resolution.
OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(CandidateSet, Best)) {
+ switch (BestViableFunction(CandidateSet, Object->getLocStart(), Best)) {
case OR_Success:
// Overload resolution succeeded; we'll build the appropriate call
// below.
@@ -4388,7 +4400,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc,
// Perform overload resolution.
OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(CandidateSet, Best)) {
+ switch (BestViableFunction(CandidateSet, OpLoc, Best)) {
case OR_Success:
// Overload resolution succeeded; we'll build the call below.
break;
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index aa9b8db..914839c 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -84,7 +84,7 @@ Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R,
SourceLocation Loc;
SourceRange R1, R2;
- if (!E->isUnusedResultAWarning(Loc, R1, R2))
+ if (!E->isUnusedResultAWarning(Loc, R1, R2, Context))
continue;
Diag(Loc, diag::warn_unused_expr) << R1 << R2;
@@ -748,18 +748,25 @@ Action::OwningStmtResult
Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
// If this is the first return we've seen in the block, infer the type of
// the block from it.
- if (CurBlock->ReturnType == 0) {
+ if (CurBlock->ReturnType.isNull()) {
if (RetValExp) {
// Don't call UsualUnaryConversions(), since we don't want to do
// integer promotions here.
DefaultFunctionArrayConversion(RetValExp);
- CurBlock->ReturnType = RetValExp->getType().getTypePtr();
+ CurBlock->ReturnType = RetValExp->getType();
+ if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(RetValExp)) {
+ // We have to remove a 'const' added to copied-in variable which was
+ // part of the implementation spec. and not the actual qualifier for
+ // the variable.
+ if (CDRE->isConstQualAdded())
+ CurBlock->ReturnType.removeConst();
+ }
} else
- CurBlock->ReturnType = Context.VoidTy.getTypePtr();
+ CurBlock->ReturnType = Context.VoidTy;
}
- QualType FnRetType = QualType(CurBlock->ReturnType, 0);
+ QualType FnRetType = CurBlock->ReturnType;
- if (CurBlock->TheDecl->hasAttr<NoReturnAttr>()) {
+ if (CurBlock->TheDecl->hasAttr<NoReturnAttr>(Context)) {
Diag(ReturnLoc, diag::err_noreturn_block_has_return_expr)
<< getCurFunctionOrMethodDecl()->getDeclName();
return StmtError();
@@ -835,7 +842,7 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, FullExprArg rex) {
QualType FnRetType;
if (const FunctionDecl *FD = getCurFunctionDecl()) {
FnRetType = FD->getResultType();
- if (FD->hasAttr<NoReturnAttr>())
+ if (FD->hasAttr<NoReturnAttr>(Context))
Diag(ReturnLoc, diag::warn_noreturn_function_has_return_expr)
<< getCurFunctionOrMethodDecl()->getDeclName();
} else if (ObjCMethodDecl *MD = getCurMethodDecl())
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index b2a82ed..fb41b2b 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -444,6 +444,9 @@ Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK,
if (Previous.begin() != Previous.end())
PrevDecl = *Previous.begin();
+ if (PrevDecl && !isDeclInScope(PrevDecl, CurContext, S))
+ PrevDecl = 0;
+
DeclContext *SemanticContext = CurContext;
if (SS.isNotEmpty() && !SS.isInvalid()) {
SemanticContext = computeDeclContext(SS);
@@ -548,7 +551,7 @@ Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK,
NewClass->startDefinition();
if (Attr)
- ProcessDeclAttributeList(NewClass, Attr);
+ ProcessDeclAttributeList(S, NewClass, Attr);
PushOnScopeChains(NewTemplate, S);
@@ -806,6 +809,10 @@ static void CanonicalizeTemplateArguments(const TemplateArgument *TemplateArgs,
Canonical.push_back(TemplateArgument(SourceLocation(), CanonType));
break;
}
+
+ case TemplateArgument::Pack:
+ assert(0 && "FIXME: Implement!");
+ break;
}
}
}
@@ -846,7 +853,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
ConvertedTemplateArgs))
return QualType();
- assert((ConvertedTemplateArgs.size() ==
+ assert((ConvertedTemplateArgs.structuredSize() ==
Template->getTemplateParameters()->size()) &&
"Converted template argument list is too short!");
@@ -1207,6 +1214,11 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
Diag(Arg.getLocation(), diag::err_template_arg_must_be_expr);
Diag((*Param)->getLocation(), diag::note_template_param_here);
Invalid = true;
+ break;
+
+ case TemplateArgument::Pack:
+ assert(0 && "FIXME: Implement!");
+ break;
}
} else {
// Check template template parameters.
@@ -1251,6 +1263,10 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
case TemplateArgument::Integral:
assert(false && "Integral argument with template template parameter");
break;
+
+ case TemplateArgument::Pack:
+ assert(0 && "FIXME: Implement!");
+ break;
}
}
}
@@ -2288,7 +2304,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
RAngleLoc, ConvertedTemplateArgs))
return true;
- assert((ConvertedTemplateArgs.size() ==
+ assert((ConvertedTemplateArgs.structuredSize() ==
ClassTemplate->getTemplateParameters()->size()) &&
"Converted template argument list is too short!");
@@ -2549,7 +2565,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc,
RAngleLoc, ConvertedTemplateArgs))
return true;
- assert((ConvertedTemplateArgs.size() ==
+ assert((ConvertedTemplateArgs.structuredSize() ==
ClassTemplate->getTemplateParameters()->size()) &&
"Converted template argument list is too short!");
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 84d802d..784e451 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -46,16 +46,22 @@ static NonTypeTemplateParmDecl *getDeducedParameterFromExpr(Expr *E) {
static Sema::TemplateDeductionResult
DeduceNonTypeTemplateArgument(ASTContext &Context,
NonTypeTemplateParmDecl *NTTP,
- llvm::APInt Value,
+ llvm::APSInt Value,
Sema::TemplateDeductionInfo &Info,
llvm::SmallVectorImpl<TemplateArgument> &Deduced) {
assert(NTTP->getDepth() == 0 &&
"Cannot deduce non-type template argument with depth > 0");
if (Deduced[NTTP->getIndex()].isNull()) {
- Deduced[NTTP->getIndex()] = TemplateArgument(SourceLocation(),
- llvm::APSInt(Value),
- NTTP->getType());
+ QualType T = NTTP->getType();
+
+ // FIXME: Make sure we didn't overflow our data type!
+ unsigned AllowedBits = Context.getTypeSize(T);
+ if (Value.getBitWidth() != AllowedBits)
+ Value.extOrTrunc(AllowedBits);
+ Value.setIsSigned(T->isSignedIntegerType());
+
+ Deduced[NTTP->getIndex()] = TemplateArgument(SourceLocation(), Value, T);
return Sema::TDK_Success;
}
@@ -64,18 +70,14 @@ DeduceNonTypeTemplateArgument(ASTContext &Context,
// If the template argument was previously deduced to a negative value,
// then our deduction fails.
const llvm::APSInt *PrevValuePtr = Deduced[NTTP->getIndex()].getAsIntegral();
- if (PrevValuePtr->isSigned() && PrevValuePtr->isNegative()) {
- // FIXME: This is wacky; we should be dealing with APSInts and
- // checking the actual signs.
+ if (PrevValuePtr->isNegative()) {
Info.Param = NTTP;
Info.FirstArg = Deduced[NTTP->getIndex()];
- Info.SecondArg = TemplateArgument(SourceLocation(),
- llvm::APSInt(Value),
- NTTP->getType());
+ Info.SecondArg = TemplateArgument(SourceLocation(), Value, NTTP->getType());
return Sema::TDK_Inconsistent;
}
- llvm::APInt PrevValue = *PrevValuePtr;
+ llvm::APSInt PrevValue = *PrevValuePtr;
if (Value.getBitWidth() > PrevValue.getBitWidth())
PrevValue.zext(Value.getBitWidth());
else if (Value.getBitWidth() < PrevValue.getBitWidth())
@@ -84,9 +86,7 @@ DeduceNonTypeTemplateArgument(ASTContext &Context,
if (Value != PrevValue) {
Info.Param = NTTP;
Info.FirstArg = Deduced[NTTP->getIndex()];
- Info.SecondArg = TemplateArgument(SourceLocation(),
- llvm::APSInt(Value),
- NTTP->getType());
+ Info.SecondArg = TemplateArgument(SourceLocation(), Value, NTTP->getType());
return Sema::TDK_Inconsistent;
}
@@ -329,10 +329,11 @@ DeduceTemplateArguments(ASTContext &Context,
assert(NTTP->getDepth() == 0 &&
"Cannot deduce non-type template argument at depth > 0");
if (const ConstantArrayType *ConstantArrayArg
- = dyn_cast<ConstantArrayType>(ArrayArg))
- return DeduceNonTypeTemplateArgument(Context, NTTP,
- ConstantArrayArg->getSize(),
+ = dyn_cast<ConstantArrayType>(ArrayArg)) {
+ llvm::APSInt Size(ConstantArrayArg->getSize());
+ return DeduceNonTypeTemplateArgument(Context, NTTP, Size,
Info, Deduced);
+ }
if (const DependentSizedArrayType *DependentArrayArg
= dyn_cast<DependentSizedArrayType>(ArrayArg))
return DeduceNonTypeTemplateArgument(Context, NTTP,
@@ -597,6 +598,9 @@ DeduceTemplateArguments(ASTContext &Context,
// Can't deduce anything, but that's okay.
return Sema::TDK_Success;
}
+ case TemplateArgument::Pack:
+ assert(0 && "FIXME: Implement!");
+ break;
}
return Sema::TDK_Success;
@@ -674,35 +678,6 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
/*FlattenArgs=*/true);
Info.reset(DeducedArgumentList);
- // Now that we have all of the deduced template arguments, take
- // another pass through them to convert any integral template
- // arguments to the appropriate type.
- for (unsigned I = 0, N = Deduced.size(); I != N; ++I) {
- TemplateArgument &Arg = Deduced[I];
- if (Arg.getKind() == TemplateArgument::Integral) {
- const NonTypeTemplateParmDecl *Parm
- = cast<NonTypeTemplateParmDecl>(Partial->getTemplateParameters()
- ->getParam(I));
- QualType T = InstantiateType(Parm->getType(), *DeducedArgumentList,
- Parm->getLocation(), Parm->getDeclName());
- if (T.isNull()) {
- Info.Param = const_cast<NonTypeTemplateParmDecl*>(Parm);
- Info.FirstArg = TemplateArgument(Parm->getLocation(), Parm->getType());
- return TDK_SubstitutionFailure;
- }
-
- // FIXME: Make sure we didn't overflow our data type!
- llvm::APSInt &Value = *Arg.getAsIntegral();
- unsigned AllowedBits = Context.getTypeSize(T);
- if (Value.getBitWidth() != AllowedBits)
- Value.extOrTrunc(AllowedBits);
- Value.setIsSigned(T->isSignedIntegerType());
- Arg.setIntegralType(T);
- }
-
- (*DeducedArgumentList)[I] = Arg;
- }
-
// Substitute the deduced template arguments into the template
// arguments of the class template partial specialization, and
// verify that the instantiated template arguments are both valid
@@ -750,12 +725,13 @@ MarkDeducedTemplateParameters(Sema &SemaRef,
/// \brief Mark the template arguments that are deduced by the given
/// expression.
static void
-MarkDeducedTemplateParameters(Expr *E, llvm::SmallVectorImpl<bool> &Deduced) {
- DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E);
+MarkDeducedTemplateParameters(const Expr *E,
+ llvm::SmallVectorImpl<bool> &Deduced) {
+ const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E);
if (!E)
return;
- NonTypeTemplateParmDecl *NTTP
+ const NonTypeTemplateParmDecl *NTTP
= dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl());
if (!NTTP)
return;
@@ -776,26 +752,26 @@ MarkDeducedTemplateParameters(Sema &SemaRef, QualType T,
switch (T->getTypeClass()) {
case Type::ExtQual:
MarkDeducedTemplateParameters(SemaRef,
- QualType(cast<ExtQualType>(T.getTypePtr())->getBaseType(), 0),
+ QualType(cast<ExtQualType>(T)->getBaseType(), 0),
Deduced);
break;
case Type::Pointer:
MarkDeducedTemplateParameters(SemaRef,
- cast<PointerType>(T.getTypePtr())->getPointeeType(),
+ cast<PointerType>(T)->getPointeeType(),
Deduced);
break;
case Type::BlockPointer:
MarkDeducedTemplateParameters(SemaRef,
- cast<BlockPointerType>(T.getTypePtr())->getPointeeType(),
+ cast<BlockPointerType>(T)->getPointeeType(),
Deduced);
break;
case Type::LValueReference:
case Type::RValueReference:
MarkDeducedTemplateParameters(SemaRef,
- cast<ReferenceType>(T.getTypePtr())->getPointeeType(),
+ cast<ReferenceType>(T)->getPointeeType(),
Deduced);
break;
@@ -808,27 +784,34 @@ MarkDeducedTemplateParameters(Sema &SemaRef, QualType T,
}
case Type::DependentSizedArray:
- MarkDeducedTemplateParameters(
- cast<DependentSizedArrayType>(T.getTypePtr())->getSizeExpr(),
+ MarkDeducedTemplateParameters(cast<DependentSizedArrayType>(T)->getSizeExpr(),
Deduced);
// Fall through to check the element type
case Type::ConstantArray:
case Type::IncompleteArray:
MarkDeducedTemplateParameters(SemaRef,
- cast<ArrayType>(T.getTypePtr())->getElementType(),
+ cast<ArrayType>(T)->getElementType(),
Deduced);
break;
case Type::Vector:
case Type::ExtVector:
MarkDeducedTemplateParameters(SemaRef,
- cast<VectorType>(T.getTypePtr())->getElementType(),
+ cast<VectorType>(T)->getElementType(),
Deduced);
break;
+ case Type::DependentSizedExtVector: {
+ const DependentSizedExtVectorType *VecType
+ = cast<DependentSizedExtVectorType>(T);
+ MarkDeducedTemplateParameters(SemaRef, VecType->getElementType(), Deduced);
+ MarkDeducedTemplateParameters(VecType->getSizeExpr(), Deduced);
+ break;
+ }
+
case Type::FunctionProto: {
- const FunctionProtoType *Proto = cast<FunctionProtoType>(T.getTypePtr());
+ const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
MarkDeducedTemplateParameters(SemaRef, Proto->getResultType(), Deduced);
for (unsigned I = 0, N = Proto->getNumArgs(); I != N; ++I)
MarkDeducedTemplateParameters(SemaRef, Proto->getArgType(I), Deduced);
@@ -836,12 +819,12 @@ MarkDeducedTemplateParameters(Sema &SemaRef, QualType T,
}
case Type::TemplateTypeParm:
- Deduced[cast<TemplateTypeParmType>(T.getTypePtr())->getIndex()] = true;
+ Deduced[cast<TemplateTypeParmType>(T)->getIndex()] = true;
break;
case Type::TemplateSpecialization: {
const TemplateSpecializationType *Spec
- = cast<TemplateSpecializationType>(T.getTypePtr());
+ = cast<TemplateSpecializationType>(T);
if (TemplateDecl *Template = Spec->getTemplateName().getAsTemplateDecl())
if (TemplateTemplateParmDecl *TTP
= dyn_cast<TemplateTemplateParmDecl>(Template))
@@ -864,7 +847,7 @@ MarkDeducedTemplateParameters(Sema &SemaRef, QualType T,
case Type::Typename:
case Type::ObjCInterface:
case Type::ObjCQualifiedInterface:
- case Type::ObjCQualifiedId:
+ case Type::ObjCObjectPointer:
#define TYPE(Class, Base)
#define ABSTRACT_TYPE(Class, Base)
#define DEPENDENT_TYPE(Class, Base)
@@ -898,6 +881,9 @@ MarkDeducedTemplateParameters(Sema &SemaRef,
case TemplateArgument::Expression:
MarkDeducedTemplateParameters(TemplateArg.getAsExpr(), Deduced);
break;
+ case TemplateArgument::Pack:
+ assert(0 && "FIXME: Implement!");
+ break;
}
}
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 18b2d75a..3992f8c 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -431,6 +431,32 @@ InstantiateDependentSizedArrayType(const DependentSizedArrayType *T,
}
QualType
+TemplateTypeInstantiator::
+InstantiateDependentSizedExtVectorType(const DependentSizedExtVectorType *T,
+ unsigned Quals) const {
+
+ // Instantiate the element type if needed.
+ QualType ElementType = T->getElementType();
+ if (ElementType->isDependentType()) {
+ ElementType = Instantiate(ElementType);
+ if (ElementType.isNull())
+ return QualType();
+ }
+
+ // Instantiate the size expression.
+ const Expr *SizeExpr = T->getSizeExpr();
+ Sema::OwningExprResult InstantiatedArraySize =
+ SemaRef.InstantiateExpr(const_cast<Expr *>(SizeExpr), TemplateArgs);
+ if (InstantiatedArraySize.isInvalid())
+ return QualType();
+
+ return SemaRef.BuildExtVectorType(ElementType,
+ SemaRef.Owned(
+ InstantiatedArraySize.takeAs<Expr>()),
+ T->getAttributeLoc());
+}
+
+QualType
TemplateTypeInstantiator::InstantiateVectorType(const VectorType *T,
unsigned Quals) const {
// FIXME: Implement this
@@ -564,6 +590,7 @@ InstantiateTemplateTypeParmType(const TemplateTypeParmType *T,
// parameter with the template "level" reduced by one.
return SemaRef.Context.getTemplateTypeParmType(T->getDepth() - 1,
T->getIndex(),
+ T->isParameterPack(),
T->getName())
.getQualifiedType(Quals);
}
@@ -630,24 +657,24 @@ InstantiateTypenameType(const TypenameType *T, unsigned Quals) const {
QualType
TemplateTypeInstantiator::
-InstantiateObjCInterfaceType(const ObjCInterfaceType *T,
- unsigned Quals) const {
+InstantiateObjCObjectPointerType(const ObjCObjectPointerType *T,
+ unsigned Quals) const {
assert(false && "Objective-C types cannot be dependent");
return QualType();
}
-QualType
+QualType
TemplateTypeInstantiator::
-InstantiateObjCQualifiedInterfaceType(const ObjCQualifiedInterfaceType *T,
- unsigned Quals) const {
+InstantiateObjCInterfaceType(const ObjCInterfaceType *T,
+ unsigned Quals) const {
assert(false && "Objective-C types cannot be dependent");
return QualType();
}
QualType
TemplateTypeInstantiator::
-InstantiateObjCQualifiedIdType(const ObjCQualifiedIdType *T,
- unsigned Quals) const {
+InstantiateObjCQualifiedInterfaceType(const ObjCQualifiedInterfaceType *T,
+ unsigned Quals) const {
assert(false && "Objective-C types cannot be dependent");
return QualType();
}
@@ -1153,6 +1180,10 @@ TemplateArgument Sema::Instantiate(TemplateArgument Arg,
return TemplateArgument();
return TemplateArgument(E.takeAs<Expr>());
}
+
+ case TemplateArgument::Pack:
+ assert(0 && "FIXME: Implement!");
+ break;
}
assert(false && "Unhandled template argument kind");
diff --git a/lib/Sema/SemaTemplateInstantiateExpr.cpp b/lib/Sema/SemaTemplateInstantiateExpr.cpp
index 3c67f2a..bf19701 100644
--- a/lib/Sema/SemaTemplateInstantiateExpr.cpp
+++ b/lib/Sema/SemaTemplateInstantiateExpr.cpp
@@ -1165,7 +1165,10 @@ TemplateExprInstantiator::VisitCXXExprWithTemporaries(
if (SubExpr.isInvalid())
return SemaRef.ExprError();
- return SemaRef.ActOnFinishFullExpr(move(SubExpr));
+ Expr *Temp =
+ SemaRef.MaybeCreateCXXExprWithTemporaries(SubExpr.takeAs<Expr>(),
+ E->shouldDestroyTemporaries());
+ return SemaRef.Owned(Temp);
}
Sema::OwningExprResult
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 70a9270..967f650 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -543,6 +543,48 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
return T;
}
+
+/// \brief Build an ext-vector type.
+///
+/// Run the required checks for the extended vector type.
+QualType Sema::BuildExtVectorType(QualType T, ExprArg ArraySize,
+ SourceLocation AttrLoc) {
+
+ Expr *Arg = (Expr *)ArraySize.get();
+
+ // unlike gcc's vector_size attribute, we do not allow vectors to be defined
+ // in conjunction with complex types (pointers, arrays, functions, etc.).
+ if (!T->isDependentType() &&
+ !T->isIntegerType() && !T->isRealFloatingType()) {
+ Diag(AttrLoc, diag::err_attribute_invalid_vector_type) << T;
+ return QualType();
+ }
+
+ if (!Arg->isTypeDependent() && !Arg->isValueDependent()) {
+ llvm::APSInt vecSize(32);
+ if (!Arg->isIntegerConstantExpr(vecSize, Context)) {
+ Diag(AttrLoc, diag::err_attribute_argument_not_int)
+ << "ext_vector_type" << Arg->getSourceRange();
+ return QualType();
+ }
+
+ // unlike gcc's vector_size attribute, the size is specified as the
+ // number of elements, not the number of bytes.
+ unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue());
+
+ if (vectorSize == 0) {
+ Diag(AttrLoc, diag::err_attribute_zero_size)
+ << Arg->getSourceRange();
+ return QualType();
+ }
+
+ if (!T->isDependentType())
+ return Context.getExtVectorType(T, vectorSize);
+ }
+
+ return Context.getDependentSizedExtVectorType(T, ArraySize.takeAs<Expr>(),
+ AttrLoc);
+}
/// \brief Build a function type.
///
diff --git a/test/Analysis/casts.c b/test/Analysis/casts.c
index 94a1eac..5e4222b 100644
--- a/test/Analysis/casts.c
+++ b/test/Analysis/casts.c
@@ -14,3 +14,27 @@ void f(int sock) {
;
}
}
+
+struct s {
+ struct s *value;
+};
+
+int f1(struct s **pval) {
+ int *tbool = ((void*)0);
+ struct s *t = *pval;
+ pval = &(t->value);
+ tbool = (int *)pval; // Should record the cast-to type here.
+ char c = (unsigned char) *tbool; // Should use cast-to type to create symbol.
+ if (*tbool == -1)
+ 3;
+}
+
+void f2(const char *str) {
+ unsigned char ch, cl, *p;
+
+ p = (unsigned char *)str;
+ ch = *p++; // use cast-to type 'unsigned char' to create element region.
+ cl = *p++;
+ if(!cl)
+ cl = 'a';
+}
diff --git a/test/Analysis/elementtype.c b/test/Analysis/elementtype.c
new file mode 100644
index 0000000..10328e6
--- /dev/null
+++ b/test/Analysis/elementtype.c
@@ -0,0 +1,13 @@
+// RUN: clang-cc -analyze -checker-simple -analyzer-store=region %s
+
+typedef struct added_obj_st {
+ int type;
+} ADDED_OBJ;
+
+// Test if we are using the canonical type for ElementRegion.
+void f() {
+ ADDED_OBJ *ao[4]={((void*)0),((void*)0),((void*)0),((void*)0)};
+ if (ao[0] != ((void*)0)) {
+ ao[0]->type=0;
+ }
+}
diff --git a/test/Analysis/fields.c b/test/Analysis/fields.c
index c012a9d..900a6d6 100644
--- a/test/Analysis/fields.c
+++ b/test/Analysis/fields.c
@@ -8,3 +8,12 @@ void bar() {
*(unsigned*)&y = foo();
y.x = 1;
}
+
+struct s {
+ int n;
+};
+
+void f() {
+ struct s a;
+ int *p = &(a.n) + 1;
+}
diff --git a/test/Analysis/func.c b/test/Analysis/func.c
index ac067a9..a018d0a 100644
--- a/test/Analysis/func.c
+++ b/test/Analysis/func.c
@@ -1,4 +1,5 @@
// RUN: clang-cc -analyze -checker-simple -verify %s &&
+// RUN: clang-cc -analyze -checker-simple -analyzer-store=region -verify %s &&
// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -verify %s &&
// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -verify %s
diff --git a/test/Analysis/retain-release.m b/test/Analysis/retain-release.m
index c7c5e24..da0ae80 100644
--- a/test/Analysis/retain-release.m
+++ b/test/Analysis/retain-release.m
@@ -10,19 +10,23 @@
// #include <DiskArbitration/DiskArbitration.h>
// #include <QuartzCore/QuartzCore.h>
// #include <Quartz/Quartz.h>
+// #include <IOKit/IOKitLib.h>
//
// It includes the basic definitions for the test cases below.
//===----------------------------------------------------------------------===//
typedef unsigned int __darwin_natural_t;
+typedef unsigned long uintptr_t;
+typedef unsigned int uint32_t;
+typedef unsigned long long uint64_t;
typedef unsigned int UInt32;
typedef signed long CFIndex;
typedef const void * CFTypeRef;
typedef const struct __CFString * CFStringRef;
typedef const struct __CFAllocator * CFAllocatorRef;
+extern const CFAllocatorRef kCFAllocatorDefault;
extern CFTypeRef CFRetain(CFTypeRef cf);
extern void CFRelease(CFTypeRef cf);
-extern const CFAllocatorRef kCFAllocatorDefault;
typedef struct {
}
CFArrayCallBacks;
@@ -33,6 +37,7 @@ extern CFMutableArrayRef CFArrayCreateMutable(CFAllocatorRef allocator, CFIndex
extern const void *CFArrayGetValueAtIndex(CFArrayRef theArray, CFIndex idx);
extern void CFArrayAppendValue(CFMutableArrayRef theArray, const void *value);
typedef const struct __CFDictionary * CFDictionaryRef;
+typedef struct __CFDictionary * CFMutableDictionaryRef;
typedef UInt32 CFStringEncoding;
enum {
kCFStringEncodingMacRoman = 0, kCFStringEncodingWindowsLatin1 = 0x0500, kCFStringEncodingISOLatin1 = 0x0201, kCFStringEncodingNextStepLatin = 0x0B01, kCFStringEncodingASCII = 0x0600, kCFStringEncodingUnicode = 0x0100, kCFStringEncodingUTF8 = 0x08000100, kCFStringEncodingNonLossyASCII = 0x0BFF , kCFStringEncodingUTF16 = 0x0100, kCFStringEncodingUTF16BE = 0x10000100, kCFStringEncodingUTF16LE = 0x14000100, kCFStringEncodingUTF32 = 0x0c000100, kCFStringEncodingUTF32BE = 0x18000100, kCFStringEncodingUTF32LE = 0x1c000100 };
@@ -42,9 +47,7 @@ typedef CFTimeInterval CFAbsoluteTime;
extern CFAbsoluteTime CFAbsoluteTimeGetCurrent(void);
typedef const struct __CFDate * CFDateRef;
extern CFDateRef CFDateCreate(CFAllocatorRef allocator, CFAbsoluteTime at);
-CFAbsoluteTime CFDateGetAbsoluteTime(CFDateRef theDate);
-enum {
-kCFCalendarComponentsWrap = (1UL << 0) };
+extern CFAbsoluteTime CFDateGetAbsoluteTime(CFDateRef theDate);
typedef __darwin_natural_t natural_t;
typedef natural_t mach_port_name_t;
typedef mach_port_name_t mach_port_t;
@@ -52,6 +55,8 @@ typedef int kern_return_t;
typedef kern_return_t mach_error_t;
typedef signed char BOOL;
typedef unsigned long NSUInteger;
+@class NSString, Protocol;
+extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2)));
typedef struct _NSZone NSZone;
@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator;
@protocol NSObject - (BOOL)isEqual:(id)object;
@@ -71,32 +76,54 @@ typedef struct {
}
NSFastEnumerationState;
@protocol NSFastEnumeration - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len;
-@end @interface NSArray : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration> - (NSUInteger)count;
+@end @class NSString;
+@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration> - (NSUInteger)count;
@end @interface NSArray (NSArrayCreation) + (id)array;
-@end @interface NSAutoreleasePool : NSObject {
+@end @interface NSAutoreleasePool : NSObject {
}
- (void)drain;
-@end typedef double NSTimeInterval;
+@end extern NSString * const NSBundleDidLoadNotification;
+typedef double NSTimeInterval;
@interface NSDate : NSObject <NSCopying, NSCoding> - (NSTimeInterval)timeIntervalSinceReferenceDate;
-@end enum {
-NSWrapCalendarComponents = kCFCalendarComponentsWrap, };
+@end typedef unsigned short unichar;
@interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding> - (NSUInteger)length;
- ( const char *)UTF8String;
- (id)initWithUTF8String:(const char *)nullTerminatedCString;
+ (id)stringWithUTF8String:(const char *)nullTerminatedCString;
-@end @interface NSData : NSObject <NSCopying, NSMutableCopying, NSCoding> - (NSUInteger)length;
+@end @class NSString, NSData;
+@interface NSData : NSObject <NSCopying, NSMutableCopying, NSCoding> - (NSUInteger)length;
+ (id)dataWithBytesNoCopy:(void *)bytes length:(NSUInteger)length;
+ (id)dataWithBytesNoCopy:(void *)bytes length:(NSUInteger)length freeWhenDone:(BOOL)b;
-@end @interface NSDictionary : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration> - (NSUInteger)count;
+@end @class NSString;
+@interface NSDictionary : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration> - (NSUInteger)count;
@end @interface NSMutableDictionary : NSDictionary - (void)removeObjectForKey:(id)aKey;
- (void)setObject:(id)anObject forKey:(id)aKey;
@end @interface NSMutableDictionary (NSMutableDictionaryCreation) + (id)dictionaryWithCapacity:(NSUInteger)numItems;
+@end typedef double CGFloat;
+struct CGSize {
+};
+typedef struct CGSize CGSize;
struct CGRect {
};
typedef struct CGRect CGRect;
+@protocol NSLocking - (void)lock;
- (id)init;
+@end @class NSURLAuthenticationChallenge;
typedef mach_port_t io_object_t;
+typedef char io_name_t[128];
+typedef io_object_t io_iterator_t;
typedef io_object_t io_service_t;
+typedef struct IONotificationPort * IONotificationPortRef;
+typedef void (*IOServiceMatchingCallback)( void * refcon, io_iterator_t iterator );
+io_service_t IOServiceGetMatchingService( mach_port_t masterPort, CFDictionaryRef matching );
+kern_return_t IOServiceGetMatchingServices( mach_port_t masterPort, CFDictionaryRef matching, io_iterator_t * existing );
+kern_return_t IOServiceAddNotification( mach_port_t masterPort, const io_name_t notificationType, CFDictionaryRef matching, mach_port_t wakePort, uintptr_t reference, io_iterator_t * notification ) __attribute__((deprecated));
+kern_return_t IOServiceAddMatchingNotification( IONotificationPortRef notifyPort, const io_name_t notificationType, CFDictionaryRef matching, IOServiceMatchingCallback callback, void * refCon, io_iterator_t * notification );
+CFMutableDictionaryRef IOServiceMatching( const char * name );
+CFMutableDictionaryRef IOServiceNameMatching( const char * name );
+CFMutableDictionaryRef IOBSDNameMatching( mach_port_t masterPort, uint32_t options, const char * bsdName );
+CFMutableDictionaryRef IOOpenFirmwarePathMatching( mach_port_t masterPort, uint32_t options, const char * path );
+CFMutableDictionaryRef IORegistryEntryIDMatching( uint64_t entryID );
typedef struct __DASession * DASessionRef;
extern DASessionRef DASessionCreate( CFAllocatorRef allocator );
typedef struct __DADisk * DADiskRef;
@@ -106,18 +133,26 @@ extern CFDictionaryRef DADiskCopyDescription( DADiskRef disk );
extern DADiskRef DADiskCopyWholeDisk( DADiskRef disk );
typedef struct CGColorSpace *CGColorSpaceRef;
typedef struct CGImage *CGImageRef;
-@end @class CIContext;
-@class NSArray, NSError, NSEvent, NSMenu, NSUndoManager, NSWindow;
+ typedef struct CGLayer *CGLayerRef;
+ @class NSArray, NSError, NSEvent, NSMenu, NSUndoManager, NSWindow;
@interface NSResponder : NSObject <NSCoding> {
}
@end @protocol NSAnimatablePropertyContainer - (id)animator;
@end extern NSString *NSAnimationTriggerOrderIn ;
@interface NSView : NSResponder <NSAnimatablePropertyContainer> {
+struct __VFlags2 {
}
-@end @class NSColor, NSFont, NSNotification;
-@protocol NSValidatedUserInterfaceItem - (SEL)action;
+_vFlags2;
+}
+@end extern NSString * const NSFullScreenModeAllScreens;
+@protocol NSChangeSpelling - (void)changeSpelling:(id)sender;
+@end @protocol NSIgnoreMisspelledWords - (void)ignoreSpelling:(id)sender;
+@end @class NSColor, NSFont, NSNotification;
+@interface NSText : NSView <NSChangeSpelling, NSIgnoreMisspelledWords> {
+}
+@end @protocol NSValidatedUserInterfaceItem - (SEL)action;
@end @protocol NSUserInterfaceValidations - (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)anItem;
-@end typedef struct NSThreadPrivate _NSThreadPrivate;
+@end @class NSArray, NSError, NSImage, NSView, NSNotificationCenter, NSURL, NSScreen, NSRunningApplication;
@interface NSApplication : NSResponder <NSUserInterfaceValidations> {
}
@end enum {
@@ -125,15 +160,12 @@ NSTerminateCancel = 0, NSTerminateNow = 1, NSTerminateLater = 2
typedef NSUInteger NSApplicationTerminateReply;
@protocol NSApplicationDelegate <NSObject> @optional - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
@end enum {
-NSUserInterfaceLayoutDirectionLeftToRight = 0, NSUserInterfaceLayoutDirectionRightToLeft = 1 };
+}
+_CFlags;
@interface CIImage : NSObject <NSCoding, NSCopying> {
}
typedef int CIFormat;
-typedef struct __SFlags {
-}
-_SFlags;
-@end extern NSString * const kCAGravityCenter __attribute__((visibility("default")));
-enum {
+@end enum {
kDAReturnSuccess = 0, kDAReturnError = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x01, kDAReturnBusy = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x02, kDAReturnBadArgument = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x03, kDAReturnExclusiveAccess = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x04, kDAReturnNoResources = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x05, kDAReturnNotFound = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x06, kDAReturnNotMounted = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x07, kDAReturnNotPermitted = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x08, kDAReturnNotPrivileged = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x09, kDAReturnNotReady = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0A, kDAReturnNotWritable = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0B, kDAReturnUnsupported = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0C };
typedef mach_error_t DAReturn;
typedef const struct __DADissenter * DADissenterRef;
@@ -142,15 +174,25 @@ extern DADissenterRef DADissenterCreate( CFAllocatorRef allocator, DAReturn stat
}
- (CGImageRef)createCGImage:(CIImage *)im fromRect:(CGRect)r;
- (CGImageRef)createCGImage:(CIImage *)im fromRect:(CGRect)r format:(CIFormat)f colorSpace:(CGColorSpaceRef)cs;
-@end @protocol QCCompositionRenderer @end @interface QCRenderer : NSObject <QCCompositionRenderer> {
+- (CGLayerRef)createCGLayerWithSize:(CGSize)size info:(CFDictionaryRef)d;
+@end @class NSURL;
+@protocol QCCompositionRenderer - (NSDictionary*) attributes;
+@end @interface QCRenderer : NSObject <QCCompositionRenderer> {
}
- (id) createSnapshotImageOfType:(NSString*)type;
-@end @interface QCView : NSView <QCCompositionRenderer> {
+@end extern NSString* const QCViewDidStartRenderingNotification;
+@interface QCView : NSView <QCCompositionRenderer> {
}
- (id) createSnapshotImageOfType:(NSString*)type;
+@end enum {
+ICEXIFOrientation1 = 1, ICEXIFOrientation2 = 2, ICEXIFOrientation3 = 3, ICEXIFOrientation4 = 4, ICEXIFOrientation5 = 5, ICEXIFOrientation6 = 6, ICEXIFOrientation7 = 7, ICEXIFOrientation8 = 8, };
+@class ICDevice;
+@protocol ICDeviceDelegate <NSObject> @required - (void)didRemoveDevice:(ICDevice*)device;
+@end @class ICCameraDevice;
+@class ICScannerDevice;
+@protocol ICScannerDeviceDelegate <ICDeviceDelegate> @optional - (void)scannerDeviceDidBecomeAvailable:(ICScannerDevice*)scanner;
@end
-extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2)));
-
+
//===----------------------------------------------------------------------===//
// Test cases.
//===----------------------------------------------------------------------===//
@@ -683,6 +725,72 @@ void rdar6902710(QCView *view, QCRenderer *renderer, CIContext *context,
}
//===----------------------------------------------------------------------===//
+// <rdar://problem/6945561> -[CIContext createCGLayerWithSize:info:]
+// misinterpreted by clang scan-build
+//===----------------------------------------------------------------------===//
+
+void rdar6945561(CIContext *context, CGSize size, CFDictionaryRef d) {
+ [context createCGLayerWithSize:size info:d]; // expected-warning{{leak}}
+}
+
+//===----------------------------------------------------------------------===//
+// <rdar://problem/6961230> add knowledge of IOKit functions to retain/release
+// checker
+//===----------------------------------------------------------------------===//
+
+void IOBSDNameMatching_wrapper(mach_port_t masterPort, uint32_t options, const char * bsdName) {
+ IOBSDNameMatching(masterPort, options, bsdName); // expected-warning{{leak}}
+}
+
+void IOServiceMatching_wrapper(const char * name) {
+ IOServiceMatching(name); // expected-warning{{leak}}
+}
+
+void IOServiceNameMatching_wrapper(const char * name) {
+ IOServiceNameMatching(name); // expected-warning{{leak}}
+}
+
+__attribute__((cf_returns_retained)) CFDictionaryRef CreateDict();
+
+void IOServiceAddNotification_wrapper(mach_port_t masterPort, const io_name_t notificationType,
+ mach_port_t wakePort, uintptr_t reference, io_iterator_t * notification ) {
+
+ CFDictionaryRef matching = CreateDict();
+ CFRelease(matching);
+ IOServiceAddNotification(masterPort, notificationType, matching, // expected-warning{{used after it is released}} expected-warning{{deprecated}}
+ wakePort, reference, notification);
+}
+
+void IORegistryEntryIDMatching_wrapper(uint64_t entryID ) {
+ IORegistryEntryIDMatching(entryID); // expected-warning{{leak}}
+}
+
+void IOOpenFirmwarePathMatching_wrapper(mach_port_t masterPort, uint32_t options,
+ const char * path) {
+ IOOpenFirmwarePathMatching(masterPort, options, path); // expected-warning{{leak}}
+}
+
+void IOServiceGetMatchingService_wrapper(mach_port_t masterPort) {
+ CFDictionaryRef matching = CreateDict();
+ IOServiceGetMatchingService(masterPort, matching);
+ CFRelease(matching); // expected-warning{{used after it is released}}
+}
+
+void IOServiceGetMatchingServices_wrapper(mach_port_t masterPort, io_iterator_t *existing) {
+ CFDictionaryRef matching = CreateDict();
+ IOServiceGetMatchingServices(masterPort, matching, existing);
+ CFRelease(matching); // expected-warning{{used after it is released}}
+}
+
+void IOServiceAddMatchingNotification_wrapper(IONotificationPortRef notifyPort, const io_name_t notificationType,
+ IOServiceMatchingCallback callback, void * refCon, io_iterator_t * notification) {
+
+ CFDictionaryRef matching = CreateDict();
+ IOServiceAddMatchingNotification(notifyPort, notificationType, matching, callback, refCon, notification);
+ CFRelease(matching); // expected-warning{{used after it is released}}
+}
+
+//===----------------------------------------------------------------------===//
// Tests of ownership attributes.
//===----------------------------------------------------------------------===//
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index ba5a025..7521a1d 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -1,13 +1,10 @@
-find_file(CLANG_TEST_RUNNER TestRunner.sh PATHS ${CMAKE_CURRENT_SOURCE_DIR}
- DOC "Clang's regression testing script")
-mark_as_advanced(CLANG_TEST_RUNNER)
-
set(CLANG_TEST_DIRECTORIES
"Analysis"
"CodeGen"
"CodeGenCXX"
"CodeGenObjC"
"Coverage"
+ "CXX"
"Driver"
"FixIt"
"Frontend"
@@ -28,14 +25,20 @@ if(PYTHONINTERP_FOUND)
get_target_property(LLVM_TOOLS_PATH clang RUNTIME_OUTPUT_DIRECTORY)
set(TESTING_EXTRA_PATHS
"${LLVM_TOOLS_PATH}/${CMAKE_CFG_INTDIR}:${LLVM_SOURCE_DIR}/test/Scripts")
+ set(CLANG_TEST_EXTRA_ARGS)
+ if (MSVC OR XCODE)
+ set(CLANG_TEST_EXTRA_ARGS "--no-progress-bar")
+ endif()
set(all_testdirs)
- foreach(testdir ${CLANG_TEST_DIRECTORIES})
+ foreach(testdir ${CLANG_TEST_DIRECTORIES})
add_custom_target(clang-test-${testdir}
${PYTHON_EXECUTABLE}
${LLVM_SOURCE_DIR}/tools/clang/utils/test/MultiTestRunner.py
- -s
- "--path=${TESTING_EXTRA_PATHS}"
- ${CMAKE_CURRENT_SOURCE_DIR}/${testdir}/
+ "--path=${TESTING_EXTRA_PATHS}"
+ -s ${CLANG_TEST_EXTRA_ARGS}
+ --clang=${LLVM_TOOLS_PATH}/${CMAKE_CFG_INTDIR}/clang
+ --clang-cc=${LLVM_TOOLS_PATH}/${CMAKE_CFG_INTDIR}/clang-cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/${testdir}/
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Running Clang regression tests in ${testdir}")
@@ -46,6 +49,9 @@ if(PYTHONINTERP_FOUND)
${PYTHON_EXECUTABLE}
${LLVM_SOURCE_DIR}/tools/clang/utils/test/MultiTestRunner.py
"--path=${TESTING_EXTRA_PATHS}"
+ -s ${CLANG_TEST_EXTRA_ARGS}
+ --clang=${LLVM_TOOLS_PATH}/${CMAKE_CFG_INTDIR}/clang
+ --clang-cc=${LLVM_TOOLS_PATH}/${CMAKE_CFG_INTDIR}/clang-cc
${all_testdirs}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS clang clang-cc
diff --git a/test/CXX/basic/basic.lookup/basic.lookup.unqual/p11.cpp b/test/CXX/basic/basic.lookup/basic.lookup.unqual/p11.cpp
new file mode 100644
index 0000000..1b56ecd
--- /dev/null
+++ b/test/CXX/basic/basic.lookup/basic.lookup.unqual/p11.cpp
@@ -0,0 +1,12 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+static const int a = 10;
+
+void f0(int a,
+ int b = a) { // expected-error {{default argument references parameter 'a'}}
+}
+
+template<int a,
+ int b = a>
+class A {
+};
diff --git a/test/CXX/basic/basic.lookup/basic.lookup.unqual/p12.cpp b/test/CXX/basic/basic.lookup/basic.lookup.unqual/p12.cpp
new file mode 100644
index 0000000..aee8acf
--- /dev/null
+++ b/test/CXX/basic/basic.lookup/basic.lookup.unqual/p12.cpp
@@ -0,0 +1,13 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+struct S {};
+S E0;
+
+namespace {
+ enum {
+ E0 = 1,
+ E1 = E0 + 1
+ };
+}
+
+
diff --git a/test/CXX/basic/basic.lookup/basic.lookup.unqual/p13.cpp b/test/CXX/basic/basic.lookup/basic.lookup.unqual/p13.cpp
new file mode 100644
index 0000000..afd6623
--- /dev/null
+++ b/test/CXX/basic/basic.lookup/basic.lookup.unqual/p13.cpp
@@ -0,0 +1,8 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+struct S {
+ static const int f0 = 0;
+ static int f1;
+};
+
+int S::f1 = f0;
diff --git a/test/CXX/basic/basic.lookup/basic.lookup.unqual/p14.cpp b/test/CXX/basic/basic.lookup/basic.lookup.unqual/p14.cpp
new file mode 100644
index 0000000..b9b136c
--- /dev/null
+++ b/test/CXX/basic/basic.lookup/basic.lookup.unqual/p14.cpp
@@ -0,0 +1,11 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+// XFAIL
+
+namespace N {
+ struct S {};
+ S i;
+ extern S j;
+}
+
+int i = 2;
+N::S N::j = i;
diff --git a/test/CXX/basic/basic.lookup/basic.lookup.unqual/p15.cpp b/test/CXX/basic/basic.lookup/basic.lookup.unqual/p15.cpp
new file mode 100644
index 0000000..9572aaa
--- /dev/null
+++ b/test/CXX/basic/basic.lookup/basic.lookup.unqual/p15.cpp
@@ -0,0 +1,17 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+// XFAIL
+
+class C {
+public:
+ C(int a, int b);
+};
+
+C::C(int a, // expected-note {{previous definition}}
+ int b) // expected-note {{previous definition}}
+try {
+ int c;
+
+} catch (int a) { // expected-error {{redefinition of 'a'}}
+ int b; // expected-error {{redefinition of 'b'}}
+ ++c; // expected-error {{use of undeclared identifion 'c'}}
+}
diff --git a/test/CXX/basic/basic.lookup/basic.lookup.unqual/p3.cpp b/test/CXX/basic/basic.lookup/basic.lookup.unqual/p3.cpp
new file mode 100644
index 0000000..1daf0dd
--- /dev/null
+++ b/test/CXX/basic/basic.lookup/basic.lookup.unqual/p3.cpp
@@ -0,0 +1,26 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+// XFAIL
+
+// FIXME: This part is here to demonstrate the failure in looking up 'f', it can
+// be removed once the whole test passes.
+typedef int f;
+namespace N0 {
+ struct A {
+ friend void f();
+ void g() {
+ int i = f(1);
+ }
+ };
+}
+
+namespace N1 {
+ struct A {
+ friend void f(A &);
+ operator int();
+ void g(A a) {
+ // ADL should not apply to the lookup of 'f', it refers to the typedef
+ // above.
+ int i = f(a);
+ }
+ };
+}
diff --git a/test/CodeGen/2009-05-22-callingconv.c b/test/CodeGen/2009-05-22-callingconv.c
index 2b70d84..8afc656 100644
--- a/test/CodeGen/2009-05-22-callingconv.c
+++ b/test/CodeGen/2009-05-22-callingconv.c
@@ -1,4 +1,4 @@
-// RUN: clang-cc %s -emit-llvm -o - | grep call | grep x86_stdcallcc
+// RUN: clang-cc %s -emit-llvm -o - -triple i386-unknown-unknown | grep call | grep x86_stdcallcc
void abort(void) __attribute__((__noreturn__));
typedef void re_string_t;
typedef void re_dfa_t;
diff --git a/test/CodeGen/2009-06-14-anonymous-union-init.c b/test/CodeGen/2009-06-14-anonymous-union-init.c
new file mode 100644
index 0000000..8d1831a
--- /dev/null
+++ b/test/CodeGen/2009-06-14-anonymous-union-init.c
@@ -0,0 +1,7 @@
+// RUN: clang-cc -emit-llvm < %s | grep "zeroinitializer, i16 16877"
+// PR4390
+struct sysfs_dirent {
+ union { struct sysfs_elem_dir {} s_dir; };
+ unsigned short s_mode;
+};
+struct sysfs_dirent sysfs_root = { {}, 16877 };
diff --git a/test/CodeGen/2009-06-16-inc_test.c b/test/CodeGen/2009-06-16-inc_test.c
new file mode 100644
index 0000000..b28f63a
--- /dev/null
+++ b/test/CodeGen/2009-06-16-inc_test.c
@@ -0,0 +1,3 @@
+// RUN: clang -c -g %s -o /dev/null
+// PR 4228
+#include "2009-06-16-test.c"
diff --git a/test/CodeGen/2009-06-16-test.c b/test/CodeGen/2009-06-16-test.c
new file mode 100644
index 0000000..4189d06
--- /dev/null
+++ b/test/CodeGen/2009-06-16-test.c
@@ -0,0 +1,15 @@
+
+#ifndef TEST
+#define TEST
+#define INSIDE_RECURSION
+#include "2009-06-16-test.c"
+#undef INSIDE_RECURSION
+#endif
+
+#ifndef INSIDE_RECURSION
+int i;
+#endif
+
+#ifdef INSIDE_RECURSION
+int j;
+#endif
diff --git a/test/CodeGen/call-knr-indirect.c b/test/CodeGen/call-knr-indirect.c
new file mode 100644
index 0000000..17be015
--- /dev/null
+++ b/test/CodeGen/call-knr-indirect.c
@@ -0,0 +1,11 @@
+// RUN: clang %s -O0 -emit-llvm -S -o - | grep 'call.*rb_define_global_function'
+// This should call rb_define_global_function, not rb_f_chop.
+
+void rb_define_global_function (const char*,void(*)(),int);
+static void rb_f_chop();
+void Init_String() {
+ rb_define_global_function("chop", rb_f_chop, 0);
+}
+static void rb_f_chop() {
+}
+
diff --git a/test/CodeGen/libcalls.c b/test/CodeGen/libcalls.c
index 6953216..ea9e0c3 100644
--- a/test/CodeGen/libcalls.c
+++ b/test/CodeGen/libcalls.c
@@ -1,7 +1,7 @@
-// RUN: clang-cc -fmath-errno=1 -emit-llvm -o %t %s &&
+// RUN: clang-cc -fmath-errno=1 -emit-llvm -o %t %s -triple i386-unknown-unknown &&
// RUN: grep "declare " %t | count 6 &&
// RUN: grep "declare " %t | grep "@llvm." | count 1 &&
-// RUN: clang-cc -fmath-errno=0 -emit-llvm -o %t %s &&
+// RUN: clang-cc -fmath-errno=0 -emit-llvm -o %t %s -triple i386-unknown-unknown &&
// RUN: grep "declare " %t | count 6 &&
// RUN: grep "declare " %t | grep -v "@llvm." | count 0
diff --git a/test/CodeGenCXX/default-arg-temps.cpp b/test/CodeGenCXX/default-arg-temps.cpp
new file mode 100644
index 0000000..2dcf773
--- /dev/null
+++ b/test/CodeGenCXX/default-arg-temps.cpp
@@ -0,0 +1,15 @@
+// RUN: clang-cc -emit-llvm %s -o %t -triple=x86_64-apple-darwin9 &&
+
+struct T {
+ T();
+ ~T();
+};
+
+void f(const T& t = T());
+
+void g() {
+ // RUN: grep "call void @_ZN1TC1Ev" %t | count 2 &&
+ // RUN: grep "call void @_ZN1TD1Ev" %t | count 2
+ f();
+ f();
+}
diff --git a/test/CodeGenObjC/encode-test-5.m b/test/CodeGenObjC/encode-test-5.m
index a76b071..9820b41 100644
--- a/test/CodeGenObjC/encode-test-5.m
+++ b/test/CodeGenObjC/encode-test-5.m
@@ -1,12 +1,12 @@
// RUN: clang-cc -triple=x86_64-apple-darwin9 -fnext-runtime -emit-llvm -o %t %s &&
-// RUN: grep ji %t | count 1 &&
+// RUN: grep ji.00 %t | count 1 &&
char *a = @encode(_Complex int);
-// RUN: grep jf %t | count 1 &&
+// RUN: grep jf.00 %t | count 1 &&
char *b = @encode(_Complex float);
-// RUN: grep jd %t | count 1 &&
+// RUN: grep jd.00 %t | count 1 &&
char *c = @encode(_Complex double);
// RUN: grep "t.00" %t | count 1 &&
diff --git a/test/Driver/analyze.c b/test/Driver/analyze.c
index 338c614..5ca890f 100644
--- a/test/Driver/analyze.c
+++ b/test/Driver/analyze.c
@@ -1,9 +1,9 @@
// Verify that the analyzer gets the same flags as normal compilation
// (at least for a few key ones).
-// RUN: clang -ccc-host-triple i386-apple-darwin9 -### --analyze -o /dev/null %s -msse 2> %t.log &&
+// RUN: env MACOSX_DEPLOYMENT_TARGET=10.5 clang -ccc-host-triple i386-apple-darwin9 -### --analyze -o /dev/null %s -msse 2> %t.log &&
// RUN: grep '"-analyze"' %t.log &&
// RUN: grep '"--fmath-errno=0"' %t.log &&
// RUN: grep '"-target-feature" "+sse"' %t.log &&
-// RUN: grep '"-mmacosx-version-min=10.5.0"' %t.log
+// RUN: grep '"-mmacosx-version-min=10.5"' %t.log
diff --git a/test/Driver/darwin-cc.c b/test/Driver/darwin-cc.c
index 77193cd..ac5d9a9 100644
--- a/test/Driver/darwin-cc.c
+++ b/test/Driver/darwin-cc.c
@@ -1,3 +1,4 @@
+// RUN: unset MACOSX_DEPLOYMENT_TARGET &&
// RUN: clang -ccc-no-clang -ccc-host-triple i386-apple-darwin10 -m32 -### -MD -g -fast -Q -dA -mkernel -ansi -aFOO -S -o /tmp/OUTPUTNAME -g0 -gfull -O2 -Werror -pedantic -Wmost -w -std=c99 -trigraphs -v -pg -fFOO -undef -Qn --param a=b -fmudflap -coverage -save-temps -nostdinc -I ARG0 -F ARG1 -I ARG2 -P -MF ARG3 -MG -MP -remap -g3 -H -D ARG4 -U ARG5 -A ARG6 -D ARG7 -U ARG8 -A ARG9 -include ARG10 -pthread %s 2> %t.log &&
// RUN: grep ' ".*cc1" "-E" "-nostdinc" "-v" "-I" "ARG0" "-F" "ARG1" "-I" "ARG2" "-P" "-MD" "/tmp/OUTPUTNAME.d" "-MF" "ARG3" "-MG" "-MP" "-MQ" "/tmp/OUTPUTNAME" "-remap" "-dD" "-H" "-D__STATIC__" "-D_REENTRANT" "-D" "ARG4" "-U" "ARG5" "-A" "ARG6" "-D" "ARG7" "-U" "ARG8" "-A" "ARG9" "-include" "ARG10" ".*darwin-cc.c" "-D_MUDFLAP" "-include" "mf-runtime.h" "-mmacosx-version-min=10.6.0" "-m32" "-mkernel" "-mtune=core2" "-ansi" "-std=c99" "-trigraphs" "-Werror" "-pedantic" "-Wmost" "-w" "-fast" "-fno-eliminate-unused-debug-symbols" "-fFOO" "-fmudflap" "-O2" "-undef" "-fpch-preprocess" "-o" ".*darwin-cc.i"' %t.log &&
// RUN: grep ' ".*cc1" "-fpreprocessed" ".*darwin-cc.i" "-O3" "-dumpbase" ".*darwin-cc.c" "-dA" "-mmacosx-version-min=10.6.0" "-m32" "-mkernel" "-mtune=core2" "-ansi" "-aFOO" "-auxbase-strip" "/tmp/OUTPUTNAME" "-g" "-g0" "-g" "-g3" "-O2" "-Werror" "-pedantic" "-Wmost" "-w" "-ansi" "-std=c99" "-trigraphs" "-version" "-p" "-fast" "-fno-eliminate-unused-debug-symbols" "-fFOO" "-fmudflap" "-undef" "-fno-ident" "-o" "/tmp/OUTPUTNAME" "--param" "a=b" "-fno-builtin" "-fno-merge-constants" "-fprofile-arcs" "-ftest-coverage"' %t.log &&
diff --git a/test/Driver/darwin-ld.c b/test/Driver/darwin-ld.c
index 5ac5ae3..2e6fc57 100644
--- a/test/Driver/darwin-ld.c
+++ b/test/Driver/darwin-ld.c
@@ -1,5 +1,6 @@
// Check that ld gets arch_multiple.
+// RUN: unset MACOSX_DEPLOYMENT_TARGET &&
// RUN: clang -ccc-host-triple i386-apple-darwin9 -arch i386 -arch x86_64 %s -### -o foo 2> %t.log &&
// RUN: grep '".*ld" .*"-arch_multiple" "-final_output" "foo"' %t.log &&
diff --git a/test/Driver/default-toolchain.c b/test/Driver/default-toolchain.c
new file mode 100644
index 0000000..216394f
--- /dev/null
+++ b/test/Driver/default-toolchain.c
@@ -0,0 +1,8 @@
+// RUN: clang -ccc-host-triple i386-unknown-unknown -m64 -v 2> %t
+// RUN: grep 'Target: x86_64-unknown-unknown' %t &&
+
+// RUN: clang -ccc-host-triple i386-apple-darwin9 -arch ppc -m64 -v 2> %t
+// RUN: grep 'Target: powerpc64-apple-darwin9' %t &&
+
+// RUN: clang -ccc-host-triple i386-apple-darwin9 -arch ppc64 -m32 -v 2> %t
+// RUN: grep 'Target: powerpc-apple-darwin9' %t
diff --git a/test/Lexer/token-concat-2.c b/test/Lexer/token-concat-2.c
new file mode 100644
index 0000000..2891654
--- /dev/null
+++ b/test/Lexer/token-concat-2.c
@@ -0,0 +1,4 @@
+// RUN: clang-cc -E -x c -o - %s | grep '[.][*]'
+// PR4395
+#define X .*
+X
diff --git a/test/Parser/cxx-template-decl.cpp b/test/Parser/cxx-template-decl.cpp
index ae5d8f9..75b26a9 100644
--- a/test/Parser/cxx-template-decl.cpp
+++ b/test/Parser/cxx-template-decl.cpp
@@ -66,6 +66,17 @@ class T { // expected-error{{declaration of 'T' shadows template parameter}}
template<int Size> // expected-note{{template parameter is declared here}}
void shadow3(int Size); // expected-error{{declaration of 'Size' shadows template parameter}}
+// <rdar://problem/6952203>
+template<typename T> // expected-note{{here}}
+struct shadow4 {
+ int T; // expected-error{{shadows}}
+};
+
+template<typename T> // expected-note{{here}}
+struct shadow5 {
+ int T(int, float); // expected-error{{shadows}}
+};
+
// Non-type template parameters in scope
template<int Size>
void f(int& i) {
diff --git a/test/Parser/cxx-using-declaration.cpp b/test/Parser/cxx-using-declaration.cpp
new file mode 100644
index 0000000..de0e6f1
--- /dev/null
+++ b/test/Parser/cxx-using-declaration.cpp
@@ -0,0 +1,45 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+namespace A {
+ int VA;
+ void FA() {}
+ struct SA { int V; };
+}
+
+using A::VA;
+using A::FA;
+using typename A::SA;
+
+void main()
+{
+ VA = 1;
+ FA();
+ SA x; //Still needs handling.
+}
+
+struct B {
+ void f(char){};
+ void g(char){};
+};
+struct D : B {
+ using B::f;
+ void f(int);
+ void g(int);
+};
+void D::f(int) { f('c'); } // calls B::f(char)
+void D::g(int) { g('c'); } // recursively calls D::g(int)
+
+namespace E {
+ template <typename TYPE> int funcE(TYPE arg) { return(arg); }
+}
+
+using E::funcE<int>; // expected-error{{use of template specialization in using directive not allowed}}
+
+namespace F {
+ struct X;
+}
+
+using F::X;
+// Should have some errors here. Waiting for implementation.
+void X(int);
+struct X *x;
diff --git a/test/Parser/cxx-using-directive.cpp b/test/Parser/cxx-using-directive.cpp
index 676f4e6..504d026 100644
--- a/test/Parser/cxx-using-directive.cpp
+++ b/test/Parser/cxx-using-directive.cpp
@@ -13,8 +13,7 @@ namespace D {
class C {
- using namespace B ; // expected-error{{expected member name or ';' after declaration specifiers}}
- //FIXME: this needs better error message
+ using namespace B ; // expected-error{{not allowed}}
};
namespace B {}
diff --git a/test/Parser/namespace-alias-attr.cpp b/test/Parser/namespace-alias-attr.cpp
new file mode 100644
index 0000000..9e4072c
--- /dev/null
+++ b/test/Parser/namespace-alias-attr.cpp
@@ -0,0 +1,8 @@
+// RUN: clang-cc -verify %s
+
+namespace A
+{
+}
+
+namespace B __attribute__ (( static )) = A; // expected-error{{attributes can not be specified on namespace alias}}
+
diff --git a/test/Preprocessor/_Pragma-dependency2.c b/test/Preprocessor/_Pragma-dependency2.c
new file mode 100644
index 0000000..c21c7c8
--- /dev/null
+++ b/test/Preprocessor/_Pragma-dependency2.c
@@ -0,0 +1,5 @@
+// RUN: clang-cc -E %s -verify
+
+#define DO_PRAGMA _Pragma
+DO_PRAGMA ("GCC dependency \"blahblabh\"") // expected-error {{file not found}}
+
diff --git a/test/Preprocessor/_Pragma-syshdr2.c b/test/Preprocessor/_Pragma-syshdr2.c
deleted file mode 100644
index de7f2d3..0000000
--- a/test/Preprocessor/_Pragma-syshdr2.c
+++ /dev/null
@@ -1,5 +0,0 @@
-// RUN: clang-cc -E %s 2>&1 | grep 'file not found'
-
-#define DO_PRAGMA _Pragma
-DO_PRAGMA ("GCC dependency \"blahblabh\"")
-
diff --git a/test/Preprocessor/pragma_sysheader.c b/test/Preprocessor/pragma_sysheader.c
new file mode 100644
index 0000000..49082b8
--- /dev/null
+++ b/test/Preprocessor/pragma_sysheader.c
@@ -0,0 +1,3 @@
+// RUN: clang -verify -pedantic %s -fsyntax-only
+// rdar://6899937
+#include "pragma_sysheader.h"
diff --git a/test/Preprocessor/pragma_sysheader.h b/test/Preprocessor/pragma_sysheader.h
new file mode 100644
index 0000000..b79bde5
--- /dev/null
+++ b/test/Preprocessor/pragma_sysheader.h
@@ -0,0 +1,4 @@
+#pragma GCC system_header
+typedef int x;
+typedef int x;
+
diff --git a/test/Preprocessor/print_line_count.c b/test/Preprocessor/print_line_count.c
new file mode 100644
index 0000000..2eb62df
--- /dev/null
+++ b/test/Preprocessor/print_line_count.c
@@ -0,0 +1,4 @@
+/* RUN: clang -E -C -P %s | wc -l | grep 4
+ PR2741
+ comment */
+y
diff --git a/test/Sema/block-return.c b/test/Sema/block-return.c
index e1a3cfd..87f4040 100644
--- a/test/Sema/block-return.c
+++ b/test/Sema/block-return.c
@@ -102,3 +102,27 @@ void foo6() {
b(1);
int (^c)(void) __attribute__((noreturn)) = ^ __attribute__((noreturn)) { return 100; }; // expected-error {{block declared 'noreturn' should not return}}
}
+
+
+void foo7()
+{
+ const int (^BB) (void) = ^{ const int i = 1; return i; }; // OK
+ const int (^CC) (void) = ^const int{ const int i = 1; return i; }; // OK
+
+ int i;
+ int (^FF) (void) = ^{ return i; }; // OK
+ int (^EE) (void) = ^{ return i+1; }; // OK
+
+ __block int j;
+ int (^JJ) (void) = ^{ return j; }; // OK
+ int (^KK) (void) = ^{ return j+1; }; // OK
+
+ __block const int k;
+ const int cint = 100;
+
+ int (^MM) (void) = ^{ return k; }; // expected-error {{incompatible block pointer types initializing 'int const (^)(void)', expected 'int (^)(void)'}}
+ int (^NN) (void) = ^{ return cint; }; // expected-error {{incompatible block pointer types initializing 'int const (^)(void)', expected 'int (^)(void)'}}
+
+}
+
+
diff --git a/test/Sema/warn-unused-parameters.c b/test/Sema/warn-unused-parameters.c
new file mode 100644
index 0000000..afb9516
--- /dev/null
+++ b/test/Sema/warn-unused-parameters.c
@@ -0,0 +1,13 @@
+// RUN: clang -fblocks -fsyntax-only -Wunused-parameter %s -Xclang -verify
+
+int f0(int x,
+ int y, // expected-warning{{unused}}
+ int z __attribute__((unused))) {
+ return x;
+}
+
+void f1() {
+ (void)^(int x,
+ int y, // expected-warning{{unused}}
+ int z __attribute__((unused))) { return x; };
+}
diff --git a/test/SemaCXX/default-constructor-initializers.cpp b/test/SemaCXX/default-constructor-initializers.cpp
new file mode 100644
index 0000000..c5250f8
--- /dev/null
+++ b/test/SemaCXX/default-constructor-initializers.cpp
@@ -0,0 +1,56 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+struct X1 { // has no implicit default constructor
+ X1(int);
+};
+
+struct X2 : X1 { // expected-note {{'struct X2' declared here}} \
+ // expected-note {{'struct X2' declared here}}
+ X2(int);
+};
+
+struct X3 : public X2 {
+};
+X3 x3; // expected-error {{cannot define the default constructor for 'struct X3', because member 'struct X2' does not have any implicit default constructor}}
+
+
+struct X4 {
+ X2 x2;
+ X2 & rx2; // expected-note {{declared at}}
+};
+
+X4 x4; // expected-error {{cannot define the default constructor for 'struct X4', because base class 'struct X2' does not have any implicit default constructor}} \
+ // expected-error {{cannot define the implicit default constructor for 'struct X4', because reference member rx2 cannot be default-initialized}}
+
+
+struct Y1 { // has no implicit default constructor
+ Y1(int);
+};
+
+struct Y2 : Y1 {
+ Y2(int);
+ Y2();
+};
+
+struct Y3 : public Y2 {
+};
+Y3 y3;
+
+struct Y4 {
+ Y2 y2;
+};
+
+Y4 y4;
+
+// More tests
+
+
+struct Z1 {
+ int& z; // expected-note {{declared at}}
+ const int c1; // expected-note {{declared at}}
+ volatile int v1;
+};
+
+Z1 z1; // expected-error {{cannot define the implicit default constructor for 'struct Z1', because reference member z cannot be default-initialized}} \
+ // expected-error {{cannot define the implicit default constructor for 'struct Z1', because const member c1 cannot be default-initialized}}
+
diff --git a/test/SemaCXX/using-directive.cpp b/test/SemaCXX/using-directive.cpp
index 924cf07..78ad0429 100644
--- a/test/SemaCXX/using-directive.cpp
+++ b/test/SemaCXX/using-directive.cpp
@@ -64,7 +64,7 @@ struct K2 k2; // expected-error{{reference to 'K2' is ambiguous}} \
class X { // expected-note{{candidate found by name lookup is 'X'}}
// FIXME: produce a suitable error message for this
- using namespace A; // expected-error{{expected member name or}}
+ using namespace A; // expected-error{{not allowed}}
};
namespace N {
diff --git a/test/SemaObjC/undeclared-selector.m b/test/SemaObjC/undeclared-selector.m
new file mode 100644
index 0000000..354c316
--- /dev/null
+++ b/test/SemaObjC/undeclared-selector.m
@@ -0,0 +1,45 @@
+// RUN: clang-cc -fsyntax-only -Wundeclared-selector -verify %s
+
+typedef struct objc_selector *SEL;
+
+@interface MyClass
+
++ (void) methodA;
+- (void) methodB;
++ (void) methodD;
+- (void) methodF;
+
+@end
+
+@implementation MyClass
+
++ (void) methodA {}
+- (void) methodB {}
++ (void) methodD
+{
+ SEL d = @selector(methodD); /* Ok */
+ SEL e = @selector(methodE); // expected-warning {{undeclared selector 'methodE'}}
+}
+
+- (void) methodE
+{
+ SEL e = @selector(methodE); /* Ok */
+}
+
+- (void) methodF
+{
+ SEL e = @selector(methodE); /* Ok */
+}
+
+@end
+
+int main (void)
+{
+ SEL a = @selector(methodA); /* Ok */
+ SEL b = @selector(methodB); /* Ok */
+ SEL c = @selector(methodC); // expected-warning {{undeclared selector 'methodC'}}
+ SEL d = @selector(methodD); /* Ok */
+ SEL e = @selector(methodE); /* Ok */
+ return 0;
+
+}
diff --git a/test/SemaObjC/warn-unused-parameters.m b/test/SemaObjC/warn-unused-parameters.m
new file mode 100644
index 0000000..618dc3f
--- /dev/null
+++ b/test/SemaObjC/warn-unused-parameters.m
@@ -0,0 +1,11 @@
+// RUN: clang -fsyntax-only -Wunused -Xclang -verify %s
+
+@interface foo
+- (int)meth: (int)x: (int)y: (int)z ;
+@end
+
+@implementation foo
+- (int) meth: (int)x:
+ (int)y: // expected-warning{{unused}}
+ (int) __attribute__((unused))z { return x; }
+@end
diff --git a/test/SemaTemplate/ext-vector-type.cpp b/test/SemaTemplate/ext-vector-type.cpp
new file mode 100644
index 0000000..d6c02bb
--- /dev/null
+++ b/test/SemaTemplate/ext-vector-type.cpp
@@ -0,0 +1,47 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+template<typename T, unsigned Length>
+struct make1 {
+ typedef T __attribute__((ext_vector_type(Length))) type;
+};
+
+int test_make1() {
+ make1<int, 5>::type x;
+ x.x = 4;
+}
+
+template<typename T, unsigned Length>
+struct make2 {
+ typedef T __attribute__((ext_vector_type(Length))) type; // expected-error{{zero vector size}}
+};
+
+int test_make2() {
+ make2<int, 0> x; // expected-note{{in instantiation of}}
+}
+
+template<typename T, unsigned Length>
+struct make3 {
+ typedef T __attribute__((ext_vector_type(Length))) type; // expected-error{{invalid vector type 'struct s'}}
+};
+
+struct s {};
+
+int test_make3() {
+ make3<s, 3>x; // expected-note{{in instantiation of}}
+}
+
+template<typename T, T Length>
+struct make4 {
+ typedef T __attribute__((ext_vector_type(Length))) type;
+};
+
+int test_make4() {
+ make4<int, 4>::type x;
+ x.w = 7;
+}
+
+typedef int* int_ptr;
+template<unsigned Length>
+struct make5 {
+ typedef int_ptr __attribute__((ext_vector_type(Length))) type; // expected-error{{invalid vector type}}
+};
+
diff --git a/test/SemaTemplate/nested-template.cpp b/test/SemaTemplate/nested-template.cpp
index bd9e89f..84b1d35 100644
--- a/test/SemaTemplate/nested-template.cpp
+++ b/test/SemaTemplate/nested-template.cpp
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fsyntax-only %s
+// RUN: clang-cc -fsyntax-only -verify %s
class A;
diff --git a/tools/clang-cc/clang-cc.cpp b/tools/clang-cc/clang-cc.cpp
index 840f015..39d839e 100644
--- a/tools/clang-cc/clang-cc.cpp
+++ b/tools/clang-cc/clang-cc.cpp
@@ -67,6 +67,7 @@
#include "llvm/System/Process.h"
#include "llvm/System/Program.h"
#include "llvm/System/Signals.h"
+#include "llvm/Target/TargetSelect.h"
#include <cstdlib>
#if HAVE_SYS_TYPES_H
# include <sys/types.h>
@@ -139,7 +140,7 @@ namespace llvm {
}
std::string::size_type FirstColon = ArgValue.rfind(':', SecondColon-1);
- if (SecondColon == std::string::npos) {
+ if (FirstColon == std::string::npos) {
std::fprintf(stderr, "%s\n", ExpectedFormat);
return true;
}
@@ -2142,6 +2143,9 @@ int main(int argc, char **argv) {
llvm::cl::ParseCommandLineOptions(argc, argv,
"LLVM 'Clang' Compiler: http://clang.llvm.org\n");
+ llvm::InitializeAllTargets();
+ llvm::InitializeAllAsmPrinters();
+
if (TimeReport)
ClangFrontendTimer = new llvm::Timer("Clang front-end time");
@@ -2305,7 +2309,6 @@ int main(int argc, char **argv) {
// Initialize builtin info.
PP->getBuiltinInfo().InitializeBuiltins(PP->getIdentifierTable(),
- PP->getTargetInfo(),
PP->getLangOptions().NoBuiltin);
}
diff --git a/tools/driver/CMakeLists.txt b/tools/driver/CMakeLists.txt
index fc7464a..f170aa2 100644
--- a/tools/driver/CMakeLists.txt
+++ b/tools/driver/CMakeLists.txt
@@ -10,3 +10,6 @@ set(LLVM_LINK_COMPONENTS system support bitreader bitwriter)
add_clang_executable(clang
driver.cpp
)
+
+add_dependencies(clang clang-cc)
+
diff --git a/utils/test/MultiTestRunner.py b/utils/test/MultiTestRunner.py
index 5dde1bd..6d0c14a 100755
--- a/utils/test/MultiTestRunner.py
+++ b/utils/test/MultiTestRunner.py
@@ -169,7 +169,7 @@ class Tester(threading.Thread):
code = None
else:
code = TestRunner.runOneTest(path, command, output, testname,
- opts.clang,
+ opts.clang, opts.clangcc,
useValgrind=opts.useValgrind,
useDGCompat=opts.useDGCompat,
useScript=opts.testScript,
@@ -200,7 +200,7 @@ def detectCPUs():
ncpus = int(os.environ["NUMBER_OF_PROCESSORS"]);
if ncpus > 0:
return ncpus
- return 1 # Default
+ return 1 # Default
def main():
global options
@@ -212,7 +212,10 @@ def main():
default=detectCPUs())
parser.add_option("", "--clang", dest="clang",
help="Program to use as \"clang\"",
- action="store", default="clang")
+ action="store", default=None)
+ parser.add_option("", "--clang-cc", dest="clangcc",
+ help="Program to use as \"clang-cc\"",
+ action="store", default=None)
parser.add_option("", "--vg", dest="useValgrind",
help="Run tests under valgrind",
action="store_true", default=False)
@@ -241,7 +244,7 @@ def main():
help="Run tests in random order",
action="store_true", default=False)
parser.add_option("", "--seed", dest="seed",
- help="Seed for random number generator (default: random).",
+ help="Seed for random number generator (default: random)",
action="store", default=None)
parser.add_option("", "--no-progress-bar", dest="useProgressBar",
help="Do not use curses based progress bar",
@@ -258,6 +261,11 @@ def main():
if not args:
parser.error('No inputs specified')
+ if opts.clang is None:
+ opts.clang = TestRunner.inferClang()
+ if opts.clangcc is None:
+ opts.clangcc = TestRunner.inferClangCC(opts.clang)
+
# FIXME: It could be worth loading these in parallel with testing.
allTests = list(getTests(args))
allTests.sort()
@@ -275,12 +283,12 @@ def main():
tests = tests[:opts.maxTests]
if opts.path is not None:
os.environ["PATH"] = opts.path + ":" + os.environ["PATH"];
- print "Current PATH is: ", os.environ["PATH"]
extra = ''
if len(tests) != len(allTests):
extra = ' of %d'%(len(allTests),)
- header = '-- Testing: %d%s tests, %d threads --'%(len(tests),extra,opts.numThreads)
+ header = '-- Testing: %d%s tests, %d threads --'%(len(tests),extra,
+ opts.numThreads)
progressBar = None
if not opts.quiet:
@@ -333,6 +341,7 @@ def main():
numFailures = len(byCode.get(TestStatus.Fail,[]))
if numFailures:
print '\nFailures: %d' % (numFailures,)
-
+ sys.exit(1)
+
if __name__=='__main__':
main()
diff --git a/utils/test/TestRunner.py b/utils/test/TestRunner.py
index 1cb8b9d..f1a1365 100755
--- a/utils/test/TestRunner.py
+++ b/utils/test/TestRunner.py
@@ -15,11 +15,17 @@
# %t - temporary file name (derived from testcase name)
#
-import os
-import sys
-import subprocess
import errno
+import os
import re
+import signal
+import subprocess
+import sys
+
+# Increase determinism for things that use the terminal width.
+#
+# FIXME: Find a better place for this hack.
+os.environ['COLUMNS'] = '0'
class TestStatus:
Pass = 0
@@ -59,7 +65,7 @@ def cat(path, output):
output.writelines(f)
f.close()
-def runOneTest(FILENAME, SUBST, OUTPUT, TESTNAME, CLANG,
+def runOneTest(FILENAME, SUBST, OUTPUT, TESTNAME, CLANG, CLANGCC,
useValgrind=False,
useDGCompat=False,
useScript=None,
@@ -109,7 +115,8 @@ def runOneTest(FILENAME, SUBST, OUTPUT, TESTNAME, CLANG,
('%llvmgxx','llvm-g++ -emit-llvm -w'),
('%prcontext','prcontext.tcl'),
('%t',TEMPOUTPUT),
- ('clang',CLANG)]
+ (' clang ', ' ' + CLANG + ' '),
+ (' clang-cc ', ' ' + CLANGCC + ' ')]
scriptLines = []
xfailLines = []
for ln in open(scriptFile):
@@ -148,9 +155,11 @@ def runOneTest(FILENAME, SUBST, OUTPUT, TESTNAME, CLANG,
outputFile.write(out)
outputFile.write(err)
SCRIPT_STATUS = p.wait()
+
+ # Detect Ctrl-C in subprocess.
+ if SCRIPT_STATUS == -signal.SIGINT:
+ raise KeyboardInterrupt
except KeyboardInterrupt:
- if p is not None:
- os.kill(p.pid)
raise
outputFile.close()
@@ -185,24 +194,100 @@ def runOneTest(FILENAME, SUBST, OUTPUT, TESTNAME, CLANG,
return TestStatus.XFail
else:
return TestStatus.Pass
+
+def capture(args):
+ p = subprocess.Popen(args, stdout=subprocess.PIPE)
+ out,_ = p.communicate()
+ return out
+
+def which(command):
+ # Would be nice if Python had a lib function for this.
+ res = capture(['which',command])
+ res = res.strip()
+ if res and os.path.exists(res):
+ return res
+ return None
+
+def inferClang():
+ # Determine which clang to use.
+ clang = os.getenv('CLANG')
+
+ # If the user set clang in the environment, definitely use that and don't
+ # try to validate.
+ if clang:
+ return clang
+
+ # Otherwise look in the path.
+ clang = which('clang')
+
+ if not clang:
+ print >>sys.stderr, "error: couldn't find 'clang' program, try setting CLANG in your environment"
+ sys.exit(1)
+
+ return clang
+
+def inferClangCC(clang):
+ clangcc = os.getenv('CLANGCC')
+
+ # If the user set clang in the environment, definitely use that and don't
+ # try to validate.
+ if clangcc:
+ return clangcc
+
+ # Otherwise try adding -cc since we expect to be looking in a build
+ # directory.
+ clangcc = which(clang + '-cc')
+ if not clangcc:
+ # Otherwise ask clang.
+ res = capture([clang, '-print-prog-name=clang-cc'])
+ res = res.strip()
+ if res and os.path.exists(res):
+ clangcc = res
+
+ if not clangcc:
+ print >>sys.stderr, "error: couldn't find 'clang-cc' program, try setting CLANGCC in your environment"
+ sys.exit(1)
+
+ return clangcc
def main():
- _,path = sys.argv
- command = path
- # Use hand concatentation here because we want to override
- # absolute paths.
- output = 'Output/' + path + '.out'
- testname = path
+ global options
+ from optparse import OptionParser
+ parser = OptionParser("usage: %prog [options] {tests}")
+ parser.add_option("", "--clang", dest="clang",
+ help="Program to use as \"clang\"",
+ action="store", default=None)
+ parser.add_option("", "--clang-cc", dest="clangcc",
+ help="Program to use as \"clang-cc\"",
+ action="store", default=None)
+ parser.add_option("", "--vg", dest="useValgrind",
+ help="Run tests under valgrind",
+ action="store_true", default=False)
+ parser.add_option("", "--dg", dest="useDGCompat",
+ help="Use llvm dejagnu compatibility mode",
+ action="store_true", default=False)
+ (opts, args) = parser.parse_args()
- # Determine which clang to use.
- CLANG = os.getenv('CLANG')
- if not CLANG:
- CLANG = 'clang'
-
- res = runOneTest(path, command, output, testname, CLANG,
- useValgrind=bool(os.getenv('VG')),
- useDGCompat=bool(os.getenv('DG_COMPAT')),
- useScript=os.getenv("TEST_SCRIPT"))
+ if not args:
+ parser.error('No tests specified')
+
+ if opts.clang is None:
+ opts.clang = inferClang()
+ if opts.clangcc is None:
+ opts.clangcc = inferClangCC(opts.clang)
+
+ for path in args:
+ command = path
+ # Use hand concatentation here because we want to override
+ # absolute paths.
+ output = 'Output/' + path + '.out'
+ testname = path
+
+ res = runOneTest(path, command, output, testname,
+ opts.clang, opts.clangcc,
+ useValgrind=opts.useValgrind,
+ useDGCompat=opts.useDGCompat,
+ useScript=os.getenv("TEST_SCRIPT"))
sys.exit(res == TestStatus.Fail or res == TestStatus.XPass)
diff --git a/www/OpenProjects.html b/www/OpenProjects.html
index 4ed6614..c0ee998 100644
--- a/www/OpenProjects.html
+++ b/www/OpenProjects.html
@@ -80,10 +80,11 @@ improve the quality of clang by self-testing. Some examples:
<li><b>Continue work on C++ support</b>: Implementing all of C++ is a very big
job, but there are lots of little pieces that can be picked off and implemented. Here are some small- to mid-sized C++ implementation projects:
<ul>
+ <li>Fix bugs: there are a number of XFAIL'd test cases in Clang's repository (particularly in the CXX subdirectory). Pick a test case and fix Clang to make it work!</li>
+ <li>Write tests: the CXX test subdirectory in Clang's repository has placeholders for tests of every paragraph in the C++ standard. Pick a paragraph, write a few tests, and see if they work! Even if they don't we'd still like the new tests (with XFAIL'd) so that we know what to fix.</li>
<li>Type-checking for explicit conversions: currently follows C semantics, not C++ semantics.</li>
<li>Qualified member references: C++ supports qualified member references such as <code>x-&gt;Base::foo</code>, but Clang has no parsing or semantic analysis for them.</li>
- <li>Implicit definitions of special member functions: Clang implicitly declares the various special member functions (default constructor, copy constructor, copy assignment operator, destructor) when necessary, but is not yet able to provide definitions for these functions.</li>
- <li>Parsing and AST representations of friend classes and functions</li>
+ <li>Parsing and AST representations of friend classes and functions</li>
<li>Explicit calls to destructors and pseudo-destructor expressions (<code>x.~X()</code>).</li>
<li>AST representation for implicit C++ conversions: implicit conversions that involve non-trivial operations (e.g., invoking a user-defined conversion function, performing a base-to-derived or derived-to-base conversion) need explicit representation in Clang's AST.</li>
<li>Improved diagnostics for overload resolution failures: after an overload resolution failure, we currently print out the overload resolution candidates. We should also print out the reason that each candidate failed, e.g., "too few arguments", "too many arguments", "cannot initialize parameter with an lvalue of type 'foo'", etc.</li>
diff --git a/www/analyzer/index.html b/www/analyzer/index.html
index d180e83..2cb3186 100644
--- a/www/analyzer/index.html
+++ b/www/analyzer/index.html
@@ -175,10 +175,11 @@ them.</p>
<h3>More Checks</h3>
-<p>Static analysis not magic; a static analyzer can only find bugs that it has
-been specifically engineered to find. If there are specific kinds of bugs you
-would like the Clang Static Analyzer to find, please feel free to file <a
-href="filing_bugs.html">feature requests</a> or contribute your own patches.</p>
+<p>Static analysis is not magic; a static analyzer can only find bugs that it
+has been specifically engineered to find. If there are specific kinds of bugs
+you would like the Clang Static Analyzer to find, please feel free to
+file <a href="filing_bugs.html">feature requests</a> or contribute your own
+patches.</p>
</div>
</body>
diff --git a/www/analyzer/latest_checker.html.incl b/www/analyzer/latest_checker.html.incl
index c465cac..62b9c54 100644
--- a/www/analyzer/latest_checker.html.incl
+++ b/www/analyzer/latest_checker.html.incl
@@ -1 +1 @@
-<b><a href="http://checker.minormatter.com/checker-0.210.tar.bz2">checker-0.210.tar.bz2</a></b> (built June 6, 2009)
+<b><a href="http://checker.minormatter.com/checker-0.211.tar.bz2">checker-0.211.tar.bz2</a></b> (built June 15, 2009)
diff --git a/www/cxx_status.html b/www/cxx_status.html
index d5ff8ac..5f924fc 100644
--- a/www/cxx_status.html
+++ b/www/cxx_status.html
@@ -2312,7 +2312,14 @@ welcome!</p>
<td class="broken"></td>
<td></td>
</tr>
-
+<tr>
+ <td>Right angle brackets (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1757.html">N1757</a>)</td>
+ <td class="complete" align="center"></td>
+ <td class="na" align="center">N/A</td>
+ <td class="na" align="center">N/A</td>
+ <td class="na">N/A</td>
+ <td></td>
+</tr>
</table>
<br />
</div>
OpenPOWER on IntegriCloud