summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2011-02-27 01:32:10 +0000
committerdim <dim@FreeBSD.org>2011-02-27 01:32:10 +0000
commitb951d621be1d00a520871c689c1cd687b6aa3ae6 (patch)
tree5c342f2374324ffec4626f558d9aa49f323f90b4 /contrib/llvm/tools
parent4004d6a3076e94bd23e681411c43682267a202fe (diff)
parenta0fb00f9837bd0d2e5948f16f6a6b82a7a628f51 (diff)
downloadFreeBSD-src-b951d621be1d00a520871c689c1cd687b6aa3ae6.zip
FreeBSD-src-b951d621be1d00a520871c689c1cd687b6aa3ae6.tar.gz
Update llvm/clang to trunk r126547.
There are several bugfixes in this update, but the most important one is to ensure __start_ and __stop_ symbols for linker sets and kernel module metadata are always emitted in object files: http://llvm.org/bugs/show_bug.cgi?id=9292 Before this fix, if you compiled kernel modules with clang, they would not be properly processed by kldxref, and if they had any dependencies, the kernel would fail to load those. Another problem occurred when attempting to mount a tmpfs filesystem, which would result in 'operation not supported by device'.
Diffstat (limited to 'contrib/llvm/tools')
-rw-r--r--contrib/llvm/tools/clang/include/clang-c/Index.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTContext.h7
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTImporter.h9
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Decl.h84
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclBase.h11
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h218
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h17
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Expr.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h77
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h163
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h48
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Stmt.h3
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h49
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h12
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Builtins.def5
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Builtins.h5
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h5
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td9
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td6
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td9
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td55
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h7
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h8
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td16
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Options.td1
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/AnalyzerOptions.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/DeclXML.def2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/HeaderSearchOptions.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/Utils.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h3
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/AnalysisBasedWarnings.h11
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h151
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h12
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Initialization.h17
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h17
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Sema.h168
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h10
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h7
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h1
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h14
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h10
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h352
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerProvider.h5
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerV2.h191
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Checker.h160
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h187
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h14
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h4
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h16
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h5
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h2
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ASTContext.cpp106
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp48
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Decl.cpp73
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclBase.cpp16
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp32
-rw-r--r--contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Expr.cpp13
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp42
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp10
-rw-r--r--contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp182
-rw-r--r--contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp93
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Stmt.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/AST/StmtDumper.cpp4
-rw-r--r--contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp18
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/AnalysisContext.cpp28
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/CFG.cpp53
-rw-r--r--contrib/llvm/tools/clang/lib/Analysis/CFGReachabilityAnalysis.cpp76
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp11
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp17
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets.cpp1
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp36
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.h1
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp11
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp465
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h12
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp386
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp16
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp82
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp25
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp15
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp11
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp26
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h50
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h11
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp11
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp14
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Tools.cpp10
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp52
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/DocumentXML.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp107
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp37
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticPrinter.cpp14
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticsClient.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp9
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/Pragma.cpp68
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp49
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp55
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/Parser.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/Rewrite/RewriteObjC.cpp27
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp78
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp236
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/Sema.cpp29
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp257
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp74
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp75
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp48
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp54
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp70
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp406
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp52
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp304
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp7
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp77
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp104
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp36
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp14
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp11
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp158
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaType.cpp187
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/TreeTransform.h323
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h13
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp128
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp32
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp20
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp71
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp15
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp32
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp116
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp261
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp31
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp32
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Checkers.td32
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp43
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp56
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExperimentalChecks.cpp11
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp105
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp31
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp148
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/InternalChecks.h3
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp35
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp43
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp42
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp123
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp31
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp31
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp39
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp34
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp (renamed from contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrLeakChecker.cpp)63
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp148
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp50
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp58
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp70
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp397
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp7
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp18
173 files changed, 6496 insertions, 3194 deletions
diff --git a/contrib/llvm/tools/clang/include/clang-c/Index.h b/contrib/llvm/tools/clang/include/clang-c/Index.h
index b3b49c7..722f6be 100644
--- a/contrib/llvm/tools/clang/include/clang-c/Index.h
+++ b/contrib/llvm/tools/clang/include/clang-c/Index.h
@@ -35,7 +35,7 @@ extern "C" {
#define CINDEX_LINKAGE
#endif
-/** \defgroup CINDEX C Interface to Clang
+/** \defgroup CINDEX libclang: C Interface to Clang
*
* The C Interface to Clang provides a relatively small API that exposes
* facilities for parsing source code into an abstract syntax tree (AST),
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h b/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h
index 0e88713..c0eeb5a 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h
@@ -115,6 +115,7 @@ class ASTContext {
llvm::FoldingSet<PackExpansionType> PackExpansionTypes;
mutable llvm::FoldingSet<ObjCObjectTypeImpl> ObjCObjectTypes;
mutable llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes;
+ mutable llvm::FoldingSet<AutoType> AutoTypes;
llvm::FoldingSet<AttributedType> AttributedTypes;
mutable llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;
@@ -551,11 +552,6 @@ public:
return cudaConfigureCallDecl;
}
- /// This gets the struct used to keep track of pointer to blocks, complete
- /// with captured variables.
- QualType getBlockParmType(bool BlockHasCopyDispose,
- llvm::SmallVectorImpl<const Expr *> &Layout) const;
-
/// This builds the struct used for __block variables.
QualType BuildByRefType(llvm::StringRef DeclName, QualType Ty) const;
@@ -1525,7 +1521,6 @@ private:
/// \brief A counter used to uniquely identify "blocks".
mutable unsigned int UniqueBlockByRefTypeID;
- mutable unsigned int UniqueBlockParmTypeID;
friend class DeclContext;
friend class DeclarationNameTable;
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTImporter.h b/contrib/llvm/tools/clang/include/clang/AST/ASTImporter.h
index b659ce7..e153596 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ASTImporter.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ASTImporter.h
@@ -145,7 +145,14 @@ namespace clang {
/// \returns the equivalent nested-name-specifier in the "to"
/// context, or NULL if an error occurred.
NestedNameSpecifier *Import(NestedNameSpecifier *FromNNS);
-
+
+ /// \brief Import the given nested-name-specifier from the "from"
+ /// context into the "to" context.
+ ///
+ /// \returns the equivalent nested-name-specifier in the "to"
+ /// context.
+ NestedNameSpecifierLoc Import(NestedNameSpecifierLoc FromNNS);
+
/// \brief Import the goven template name from the "from" context into the
/// "to" context.
TemplateName Import(TemplateName From);
diff --git a/contrib/llvm/tools/clang/include/clang/AST/Decl.h b/contrib/llvm/tools/clang/include/clang/AST/Decl.h
index ee515da..31cee24 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/Decl.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/Decl.h
@@ -119,6 +119,14 @@ public:
return getIdentifier() ? getIdentifier()->getName() : "";
}
+ llvm::StringRef getMessageUnavailableAttr(bool unavailable) const {
+ if (!unavailable)
+ return "";
+ if (const UnavailableAttr *UA = getAttr<UnavailableAttr>())
+ return UA->getMessage();
+ return "";
+ }
+
/// getNameAsString - Get a human-readable name for the declaration, even if
/// it is one of the special kinds of names (C++ constructor, Objective-C
/// selector, etc). Creating this name requires expensive string
@@ -475,10 +483,7 @@ public:
/// QualifierInfo - A struct with extended info about a syntactic
/// name qualifier, to be used for the case of out-of-line declarations.
struct QualifierInfo {
- /// NNS - The syntactic name qualifier.
- NestedNameSpecifier *NNS;
- /// NNSRange - The source range for the qualifier.
- SourceRange NNSRange;
+ NestedNameSpecifierLoc QualifierLoc;
/// NumTemplParamLists - The number of template parameter lists
/// that were matched against the template-ids occurring into the NNS.
unsigned NumTemplParamLists;
@@ -487,8 +492,7 @@ struct QualifierInfo {
TemplateParameterList** TemplParamLists;
/// Default constructor.
- QualifierInfo()
- : NNS(0), NNSRange(), NumTemplParamLists(0), TemplParamLists(0) {}
+ QualifierInfo() : QualifierLoc(), NumTemplParamLists(0), TemplParamLists(0) {}
/// setTemplateParameterListsInfo - Sets info about matched template
/// parameter lists.
void setTemplateParameterListsInfo(ASTContext &Context,
@@ -545,14 +549,22 @@ public:
return SourceRange(getOuterLocStart(), getLocation());
}
+ /// \brief Retrieve the nested-name-specifier that qualifies the name of this
+ /// declaration, if it was present in the source.
NestedNameSpecifier *getQualifier() const {
- return hasExtInfo() ? getExtInfo()->NNS : 0;
+ return hasExtInfo() ? getExtInfo()->QualifierLoc.getNestedNameSpecifier()
+ : 0;
}
- SourceRange getQualifierRange() const {
- return hasExtInfo() ? getExtInfo()->NNSRange : SourceRange();
+
+ /// \brief Retrieve the nested-name-specifier (with source-location
+ /// information) that qualifies the name of this declaration, if it was
+ /// present in the source.
+ NestedNameSpecifierLoc getQualifierLoc() const {
+ return hasExtInfo() ? getExtInfo()->QualifierLoc
+ : NestedNameSpecifierLoc();
}
- void setQualifierInfo(NestedNameSpecifier *Qualifier,
- SourceRange QualifierRange);
+
+ void setQualifierInfo(NestedNameSpecifierLoc QualifierLoc);
unsigned getNumTemplateParameterLists() const {
return hasExtInfo() ? getExtInfo()->NumTemplParamLists : 0;
@@ -652,10 +664,6 @@ private:
/// slot of its function, enabling the named return value optimization (NRVO).
bool NRVOVariable : 1;
- /// \brief Whether this variable has a deduced C++0x auto type for which we're
- /// currently parsing the initializer.
- bool ParsingAutoInit : 1;
-
friend class StmtIteratorBase;
friend class ASTDeclReader;
@@ -665,7 +673,7 @@ protected:
StorageClass SCAsWritten)
: DeclaratorDecl(DK, DC, L, Id, T, TInfo), Init(),
ThreadSpecified(false), HasCXXDirectInit(false),
- ExceptionVar(false), NRVOVariable(false), ParsingAutoInit(false) {
+ ExceptionVar(false), NRVOVariable(false) {
SClass = SC;
SClassAsWritten = SCAsWritten;
}
@@ -889,18 +897,6 @@ public:
void setInit(Expr *I);
- /// \brief Check whether we are in the process of parsing an initializer
- /// needed to deduce the type of this variable.
- bool isParsingAutoInit() const {
- return ParsingAutoInit;
- }
-
- /// \brief Note whether we are currently parsing an initializer needed to
- /// deduce the type of this variable.
- void setParsingAutoInit(bool P) {
- ParsingAutoInit = P;
- }
-
EvaluatedStmt *EnsureEvaluatedStmt() const {
EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>();
if (!Eval) {
@@ -1050,16 +1046,18 @@ public:
};
class ImplicitParamDecl : public VarDecl {
-protected:
- ImplicitParamDecl(Kind DK, DeclContext *DC, SourceLocation L,
- IdentifierInfo *Id, QualType Tw)
- : VarDecl(DK, DC, L, Id, Tw, /*TInfo=*/0, SC_None, SC_None) {
- setImplicit();
- }
public:
static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
QualType T);
+
+ ImplicitParamDecl(DeclContext *DC, SourceLocation loc,
+ IdentifierInfo *name, QualType type)
+ : VarDecl(ImplicitParam, DC, loc, name, type,
+ /*tinfo*/ 0, SC_None, SC_None) {
+ setImplicit();
+ }
+
// Implement isa/cast/dyncast/etc.
static bool classof(const ImplicitParamDecl *D) { return true; }
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
@@ -2154,14 +2152,22 @@ public:
void setTypedefForAnonDecl(TypedefDecl *TDD);
+ /// \brief Retrieve the nested-name-specifier that qualifies the name of this
+ /// declaration, if it was present in the source.
NestedNameSpecifier *getQualifier() const {
- return hasExtInfo() ? getExtInfo()->NNS : 0;
+ return hasExtInfo() ? getExtInfo()->QualifierLoc.getNestedNameSpecifier()
+ : 0;
}
- SourceRange getQualifierRange() const {
- return hasExtInfo() ? getExtInfo()->NNSRange : SourceRange();
+
+ /// \brief Retrieve the nested-name-specifier (with source-location
+ /// information) that qualifies the name of this declaration, if it was
+ /// present in the source.
+ NestedNameSpecifierLoc getQualifierLoc() const {
+ return hasExtInfo() ? getExtInfo()->QualifierLoc
+ : NestedNameSpecifierLoc();
}
- void setQualifierInfo(NestedNameSpecifier *Qualifier,
- SourceRange QualifierRange);
+
+ void setQualifierInfo(NestedNameSpecifierLoc QualifierLoc);
unsigned getNumTemplateParameterLists() const {
return hasExtInfo() ? getExtInfo()->NumTemplParamLists : 0;
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h b/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h
index bf249ce..b35d134 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h
@@ -299,6 +299,13 @@ public:
return const_cast<Decl*>(this)->getDeclContext();
}
+ /// Finds the innermost non-closure context of this declaration.
+ /// That is, walk out the DeclContext chain, skipping any blocks.
+ DeclContext *getNonClosureContext();
+ const DeclContext *getNonClosureContext() const {
+ return const_cast<Decl*>(this)->getNonClosureContext();
+ }
+
TranslationUnitDecl *getTranslationUnitDecl();
const TranslationUnitDecl *getTranslationUnitDecl() const {
return const_cast<Decl*>(this)->getTranslationUnitDecl();
@@ -787,6 +794,10 @@ public:
return cast<Decl>(this)->getASTContext();
}
+ bool isClosure() const {
+ return DeclKind == Decl::Block;
+ }
+
bool isFunctionOrMethod() const {
switch (DeclKind) {
case Decl::Block:
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h b/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h
index d11ee8f..1656a7e 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h
@@ -1741,13 +1741,8 @@ class UsingDirectiveDecl : public NamedDecl {
/// SourceLocation - Location of 'namespace' token.
SourceLocation NamespaceLoc;
- /// \brief The source range that covers the nested-name-specifier
- /// preceding the namespace name.
- SourceRange QualifierRange;
-
- /// \brief The nested-name-specifier that precedes the namespace
- /// name, if any.
- NestedNameSpecifier *Qualifier;
+ /// \brief The nested-name-specifier that precedes the namespace.
+ NestedNameSpecifierLoc QualifierLoc;
/// NominatedNamespace - Namespace nominated by using-directive.
NamedDecl *NominatedNamespace;
@@ -1765,25 +1760,24 @@ class UsingDirectiveDecl : public NamedDecl {
UsingDirectiveDecl(DeclContext *DC, SourceLocation UsingLoc,
SourceLocation NamespcLoc,
- SourceRange QualifierRange,
- NestedNameSpecifier *Qualifier,
+ NestedNameSpecifierLoc QualifierLoc,
SourceLocation IdentLoc,
NamedDecl *Nominated,
DeclContext *CommonAncestor)
: NamedDecl(UsingDirective, DC, IdentLoc, getName()), UsingLoc(UsingLoc),
- NamespaceLoc(NamespcLoc), QualifierRange(QualifierRange),
- Qualifier(Qualifier), NominatedNamespace(Nominated),
- CommonAncestor(CommonAncestor) {
- }
+ NamespaceLoc(NamespcLoc), QualifierLoc(QualifierLoc),
+ NominatedNamespace(Nominated), CommonAncestor(CommonAncestor) { }
public:
- /// \brief Retrieve the source range of the nested-name-specifier
- /// that qualifies the namespace name.
- SourceRange getQualifierRange() const { return QualifierRange; }
-
+ /// \brief Retrieve the nested-name-specifier that qualifies the
+ /// name of the namespace, with source-location information.
+ NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
+
/// \brief Retrieve the nested-name-specifier that qualifies the
/// name of the namespace.
- NestedNameSpecifier *getQualifier() const { return Qualifier; }
+ NestedNameSpecifier *getQualifier() const {
+ return QualifierLoc.getNestedNameSpecifier();
+ }
NamedDecl *getNominatedNamespaceAsWritten() { return NominatedNamespace; }
const NamedDecl *getNominatedNamespaceAsWritten() const {
@@ -1815,8 +1809,7 @@ public:
static UsingDirectiveDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation UsingLoc,
SourceLocation NamespaceLoc,
- SourceRange QualifierRange,
- NestedNameSpecifier *Qualifier,
+ NestedNameSpecifierLoc QualifierLoc,
SourceLocation IdentLoc,
NamedDecl *Nominated,
DeclContext *CommonAncestor);
@@ -1844,49 +1837,37 @@ class NamespaceAliasDecl : public NamedDecl {
/// \brief The location of the "namespace" keyword.
SourceLocation NamespaceLoc;
- /// \brief The source range that covers the nested-name-specifier
- /// preceding the namespace name.
- SourceRange QualifierRange;
-
- /// \brief The nested-name-specifier that precedes the namespace
- /// name, if any.
- NestedNameSpecifier *Qualifier;
-
/// IdentLoc - Location of namespace identifier. Accessed by TargetNameLoc.
SourceLocation IdentLoc;
-
+
+ /// \brief The nested-name-specifier that precedes the namespace.
+ NestedNameSpecifierLoc QualifierLoc;
+
/// Namespace - The Decl that this alias points to. Can either be a
/// NamespaceDecl or a NamespaceAliasDecl.
NamedDecl *Namespace;
NamespaceAliasDecl(DeclContext *DC, SourceLocation NamespaceLoc,
SourceLocation AliasLoc, IdentifierInfo *Alias,
- SourceRange QualifierRange,
- NestedNameSpecifier *Qualifier,
+ NestedNameSpecifierLoc QualifierLoc,
SourceLocation IdentLoc, NamedDecl *Namespace)
: NamedDecl(NamespaceAlias, DC, AliasLoc, Alias),
- NamespaceLoc(NamespaceLoc), QualifierRange(QualifierRange),
- Qualifier(Qualifier), IdentLoc(IdentLoc), Namespace(Namespace) { }
+ NamespaceLoc(NamespaceLoc), IdentLoc(IdentLoc),
+ QualifierLoc(QualifierLoc), Namespace(Namespace) { }
friend class ASTDeclReader;
public:
- /// \brief Retrieve the source range of the nested-name-specifier
- /// that qualifiers the namespace name.
- SourceRange getQualifierRange() const { return QualifierRange; }
-
- /// \brief Set the source range of the nested-name-specifier that qualifies
- /// the namespace name.
- void setQualifierRange(SourceRange R) { QualifierRange = R; }
-
+ /// \brief Retrieve the nested-name-specifier that qualifies the
+ /// name of the namespace, with source-location information.
+ NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
+
/// \brief Retrieve the nested-name-specifier that qualifies the
/// name of the namespace.
- NestedNameSpecifier *getQualifier() const { return Qualifier; }
-
- /// \brief Set the nested-name-specifier that qualifies the name of the
- /// namespace.
- void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; }
-
+ NestedNameSpecifier *getQualifier() const {
+ return QualifierLoc.getNestedNameSpecifier();
+ }
+
/// \brief Retrieve the namespace declaration aliased by this directive.
NamespaceDecl *getNamespace() {
if (NamespaceAliasDecl *AD = dyn_cast<NamespaceAliasDecl>(Namespace))
@@ -1917,8 +1898,7 @@ public:
SourceLocation NamespaceLoc,
SourceLocation AliasLoc,
IdentifierInfo *Alias,
- SourceRange QualifierRange,
- NestedNameSpecifier *Qualifier,
+ NestedNameSpecifierLoc QualifierLoc,
SourceLocation IdentLoc,
NamedDecl *Namespace);
@@ -2002,15 +1982,11 @@ public:
/// 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 "using" location itself.
SourceLocation UsingLocation;
- /// \brief Target nested name specifier.
- NestedNameSpecifier* TargetNestedName;
+ /// \brief The nested-name-specifier that precedes the name.
+ NestedNameSpecifierLoc QualifierLoc;
/// DNLoc - Provides source/type location info for the
/// declaration name embedded in the ValueDecl base class.
@@ -2023,37 +1999,34 @@ class UsingDecl : public NamedDecl {
// \brief Has 'typename' keyword.
bool IsTypeName;
- UsingDecl(DeclContext *DC, SourceRange NNR,
- SourceLocation UL, NestedNameSpecifier* TargetNNS,
+ UsingDecl(DeclContext *DC, SourceLocation UL,
+ NestedNameSpecifierLoc QualifierLoc,
const DeclarationNameInfo &NameInfo, bool IsTypeNameArg)
: NamedDecl(Using, DC, NameInfo.getLoc(), NameInfo.getName()),
- NestedNameRange(NNR), UsingLocation(UL), TargetNestedName(TargetNNS),
+ UsingLocation(UL), QualifierLoc(QualifierLoc),
DNLoc(NameInfo.getInfo()), FirstUsingShadow(0),IsTypeName(IsTypeNameArg) {
}
public:
- /// \brief Returns the source range that covers the nested-name-specifier
- /// preceding the namespace name.
- SourceRange getNestedNameRange() const { return NestedNameRange; }
-
- /// \brief Set the source range of the nested-name-specifier.
- void setNestedNameRange(SourceRange R) { NestedNameRange = R; }
-
- // FIXME: Naming is inconsistent with other get*Loc functions.
/// \brief Returns the source location of the "using" keyword.
SourceLocation getUsingLocation() const { return UsingLocation; }
/// \brief Set the source location of the 'using' keyword.
void setUsingLocation(SourceLocation L) { UsingLocation = L; }
- /// \brief Get the target nested name declaration.
- NestedNameSpecifier* getTargetNestedNameDecl() const {
- return TargetNestedName;
+ /// \brief Retrieve the nested-name-specifier that qualifies the name,
+ /// with source-location information.
+ NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
+
+ /// \brief Retrieve the nested-name-specifier that qualifies the name.
+ NestedNameSpecifier *getQualifier() const {
+ return QualifierLoc.getNestedNameSpecifier();
}
- /// \brief Set the target nested name declaration.
- void setTargetNestedNameDecl(NestedNameSpecifier *NNS) {
- TargetNestedName = NNS;
+ /// \brief Retrieve the source range of the nested-name-specifier
+ /// that qualifies the name.
+ SourceRange getQualifierRange() const {
+ return QualifierLoc.getSourceRange();
}
DeclarationNameInfo getNameInfo() const {
@@ -2119,8 +2092,8 @@ public:
void removeShadowDecl(UsingShadowDecl *S);
static UsingDecl *Create(ASTContext &C, DeclContext *DC,
- SourceRange NNR, SourceLocation UsingL,
- NestedNameSpecifier* TargetNNS,
+ SourceLocation UsingL,
+ NestedNameSpecifierLoc QualifierLoc,
const DeclarationNameInfo &NameInfo,
bool IsTypeNameArg);
@@ -2145,61 +2118,55 @@ public:
/// using Base<T>::foo;
/// };
class UnresolvedUsingValueDecl : public ValueDecl {
- /// \brief The source range that covers the nested-name-specifier
- /// preceding the declaration name.
- SourceRange TargetNestedNameRange;
-
/// \brief The source location of the 'using' keyword
SourceLocation UsingLocation;
- NestedNameSpecifier *TargetNestedNameSpecifier;
+ /// \brief The nested-name-specifier that precedes the name.
+ NestedNameSpecifierLoc QualifierLoc;
/// DNLoc - Provides source/type location info for the
/// declaration name embedded in the ValueDecl base class.
DeclarationNameLoc DNLoc;
UnresolvedUsingValueDecl(DeclContext *DC, QualType Ty,
- SourceLocation UsingLoc, SourceRange TargetNNR,
- NestedNameSpecifier *TargetNNS,
+ SourceLocation UsingLoc,
+ NestedNameSpecifierLoc QualifierLoc,
const DeclarationNameInfo &NameInfo)
: ValueDecl(UnresolvedUsingValue, DC,
NameInfo.getLoc(), NameInfo.getName(), Ty),
- TargetNestedNameRange(TargetNNR), UsingLocation(UsingLoc),
- TargetNestedNameSpecifier(TargetNNS), DNLoc(NameInfo.getInfo())
+ UsingLocation(UsingLoc), QualifierLoc(QualifierLoc),
+ DNLoc(NameInfo.getInfo())
{ }
public:
- /// \brief Returns the source range that covers the nested-name-specifier
- /// preceding the namespace name.
- SourceRange getTargetNestedNameRange() const { return TargetNestedNameRange; }
-
- /// \brief Set the source range coverting the nested-name-specifier preceding
- /// the namespace name.
- void setTargetNestedNameRange(SourceRange R) { TargetNestedNameRange = R; }
-
- /// \brief Get target nested name declaration.
- NestedNameSpecifier* getTargetNestedNameSpecifier() const {
- return TargetNestedNameSpecifier;
- }
-
- /// \brief Set the nested name declaration.
- void setTargetNestedNameSpecifier(NestedNameSpecifier* NNS) {
- TargetNestedNameSpecifier = NNS;
- }
-
/// \brief Returns the source location of the 'using' keyword.
SourceLocation getUsingLoc() const { return UsingLocation; }
/// \brief Set the source location of the 'using' keyword.
void setUsingLoc(SourceLocation L) { UsingLocation = L; }
+ /// \brief Retrieve the nested-name-specifier that qualifies the name,
+ /// with source-location information.
+ NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
+
+ /// \brief Retrieve the nested-name-specifier that qualifies the name.
+ NestedNameSpecifier *getQualifier() const {
+ return QualifierLoc.getNestedNameSpecifier();
+ }
+
+ /// \brief Retrieve the source range of the nested-name-specifier
+ /// that qualifies the name.
+ SourceRange getQualifierRange() const {
+ return QualifierLoc.getSourceRange();
+ }
+
DeclarationNameInfo getNameInfo() const {
return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc);
}
static UnresolvedUsingValueDecl *
Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc,
- SourceRange TargetNNR, NestedNameSpecifier *TargetNNS,
+ NestedNameSpecifierLoc QualifierLoc,
const DeclarationNameInfo &NameInfo);
SourceRange getSourceRange() const {
@@ -2224,49 +2191,52 @@ public:
/// The type associated with a unresolved using typename decl is
/// currently always a typename type.
class UnresolvedUsingTypenameDecl : public TypeDecl {
- /// \brief The source range that covers the nested-name-specifier
- /// preceding the declaration name.
- SourceRange TargetNestedNameRange;
-
/// \brief The source location of the 'using' keyword
SourceLocation UsingLocation;
/// \brief The source location of the 'typename' keyword
SourceLocation TypenameLocation;
- NestedNameSpecifier *TargetNestedNameSpecifier;
+ /// \brief The nested-name-specifier that precedes the name.
+ NestedNameSpecifierLoc QualifierLoc;
UnresolvedUsingTypenameDecl(DeclContext *DC, SourceLocation UsingLoc,
- SourceLocation TypenameLoc,
- SourceRange TargetNNR, NestedNameSpecifier *TargetNNS,
- SourceLocation TargetNameLoc, IdentifierInfo *TargetName)
+ SourceLocation TypenameLoc,
+ NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TargetNameLoc,
+ IdentifierInfo *TargetName)
: TypeDecl(UnresolvedUsingTypename, DC, TargetNameLoc, TargetName),
- TargetNestedNameRange(TargetNNR), UsingLocation(UsingLoc),
- TypenameLocation(TypenameLoc), TargetNestedNameSpecifier(TargetNNS)
- { }
+ UsingLocation(UsingLoc), TypenameLocation(TypenameLoc),
+ QualifierLoc(QualifierLoc) { }
friend class ASTDeclReader;
public:
- /// \brief Returns the source range that covers the nested-name-specifier
- /// preceding the namespace name.
- SourceRange getTargetNestedNameRange() const { return TargetNestedNameRange; }
-
- /// \brief Get target nested name declaration.
- NestedNameSpecifier* getTargetNestedNameSpecifier() {
- return TargetNestedNameSpecifier;
- }
-
/// \brief Returns the source location of the 'using' keyword.
SourceLocation getUsingLoc() const { return UsingLocation; }
/// \brief Returns the source location of the 'typename' keyword.
SourceLocation getTypenameLoc() const { return TypenameLocation; }
+ /// \brief Retrieve the nested-name-specifier that qualifies the name,
+ /// with source-location information.
+ NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
+
+ /// \brief Retrieve the nested-name-specifier that qualifies the name.
+ NestedNameSpecifier *getQualifier() const {
+ return QualifierLoc.getNestedNameSpecifier();
+ }
+
+ /// \brief Retrieve the source range of the nested-name-specifier
+ /// that qualifies the name.
+ SourceRange getQualifierRange() const {
+ return QualifierLoc.getSourceRange();
+ }
+
+ // FIXME: DeclarationNameInfo
static UnresolvedUsingTypenameDecl *
Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc,
- SourceLocation TypenameLoc,
- SourceRange TargetNNR, NestedNameSpecifier *TargetNNS,
+ SourceLocation TypenameLoc, NestedNameSpecifierLoc QualifierLoc,
SourceLocation TargetNameLoc, DeclarationName TargetName);
SourceRange getSourceRange() const {
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h b/contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h
index cb9e168..63cdac5 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h
@@ -39,12 +39,12 @@ public:
Decl*& operator[](unsigned i) {
assert (i < NumDecls && "Out-of-bounds access.");
- return *((Decl**) (this+1));
+ return ((Decl**) (this+1))[i];
}
Decl* const& operator[](unsigned i) const {
assert (i < NumDecls && "Out-of-bounds access.");
- return *((Decl* const*) (this+1));
+ return ((Decl* const*) (this+1))[i];
}
};
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h b/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h
index 176c6ba..f41859c 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h
@@ -48,6 +48,7 @@ class TemplateParameterList {
/// parameter list.
unsigned NumParams;
+protected:
TemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc,
NamedDecl **Params, unsigned NumParams,
SourceLocation RAngleLoc);
@@ -107,6 +108,19 @@ public:
}
};
+/// FixedSizeTemplateParameterList - Stores a list of template parameters for a
+/// TemplateDecl and its derived classes. Suitable for creating on the stack.
+template<size_t N>
+class FixedSizeTemplateParameterList : public TemplateParameterList {
+ NamedDecl *Params[N];
+
+public:
+ FixedSizeTemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc,
+ NamedDecl **Params, SourceLocation RAngleLoc) :
+ TemplateParameterList(TemplateLoc, LAngleLoc, Params, N, RAngleLoc) {
+ }
+};
+
/// \brief A template argument list.
class TemplateArgumentList {
/// \brief The template argument list.
@@ -914,6 +928,9 @@ class TemplateTypeParmDecl : public TypeDecl {
TypeForDecl = Type.getTypePtrOrNull();
}
+ /// Sema creates these on the stack during auto type deduction.
+ friend class Sema;
+
public:
static TemplateTypeParmDecl *Create(const ASTContext &C, DeclContext *DC,
SourceLocation L, unsigned D, unsigned P,
diff --git a/contrib/llvm/tools/clang/include/clang/AST/Expr.h b/contrib/llvm/tools/clang/include/clang/AST/Expr.h
index a17205c..95bfad5 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/Expr.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/Expr.h
@@ -1843,9 +1843,7 @@ public:
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- SourceRange getSourceRange() const {
- return SourceRange(getCallee()->getLocStart(), RParenLoc);
- }
+ SourceRange getSourceRange() const;
static bool classof(const Stmt *T) {
return T->getStmtClass() >= firstCallExprConstant &&
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h b/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h
index 85ce962..225db3c 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h
@@ -108,8 +108,6 @@ public:
/// FIXME: Returns 0 for member pointer call exprs.
CXXRecordDecl *getRecordDecl();
- SourceRange getSourceRange() const;
-
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXMemberCallExprClass;
}
@@ -1333,13 +1331,9 @@ class CXXPseudoDestructorExpr : public Expr {
/// \brief The location of the '.' or '->' operator.
SourceLocation OperatorLoc;
-
+
/// \brief The nested-name-specifier that follows the operator, if present.
- NestedNameSpecifier *Qualifier;
-
- /// \brief The source range that covers the nested-name-specifier, if
- /// present.
- SourceRange QualifierRange;
+ NestedNameSpecifierLoc QualifierLoc;
/// \brief The type that precedes the '::' in a qualified pseudo-destructor
/// expression.
@@ -1356,11 +1350,12 @@ class CXXPseudoDestructorExpr : public Expr {
/// resolve the name.
PseudoDestructorTypeStorage DestroyedType;
+ friend class ASTStmtReader;
+
public:
CXXPseudoDestructorExpr(ASTContext &Context,
Expr *Base, bool isArrow, SourceLocation OperatorLoc,
- NestedNameSpecifier *Qualifier,
- SourceRange QualifierRange,
+ NestedNameSpecifierLoc QualifierLoc,
TypeSourceInfo *ScopeType,
SourceLocation ColonColonLoc,
SourceLocation TildeLoc,
@@ -1368,36 +1363,32 @@ public:
explicit CXXPseudoDestructorExpr(EmptyShell Shell)
: Expr(CXXPseudoDestructorExprClass, Shell),
- Base(0), IsArrow(false), Qualifier(0), ScopeType(0) { }
+ Base(0), IsArrow(false), QualifierLoc(), ScopeType(0) { }
- void setBase(Expr *E) { Base = E; }
Expr *getBase() const { return cast<Expr>(Base); }
/// \brief Determines whether this member expression actually had
/// a C++ nested-name-specifier prior to the name of the member, e.g.,
/// x->Base::foo.
- bool hasQualifier() const { return Qualifier != 0; }
-
- /// \brief If the member name was qualified, retrieves the source range of
- /// the nested-name-specifier that precedes the member name. Otherwise,
- /// returns an empty source range.
- SourceRange getQualifierRange() const { return QualifierRange; }
- void setQualifierRange(SourceRange R) { QualifierRange = R; }
+ bool hasQualifier() const { return QualifierLoc; }
+ /// \brief Retrieves the nested-name-specifier that qualifies the type name,
+ /// with source-location information.
+ NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
+
/// \brief If the member name was qualified, retrieves the
/// nested-name-specifier that precedes the member name. Otherwise, returns
/// NULL.
- NestedNameSpecifier *getQualifier() const { return Qualifier; }
- void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; }
+ NestedNameSpecifier *getQualifier() const {
+ return QualifierLoc.getNestedNameSpecifier();
+ }
/// \brief Determine whether this pseudo-destructor expression was written
/// using an '->' (otherwise, it used a '.').
bool isArrow() const { return IsArrow; }
- void setArrow(bool A) { IsArrow = A; }
/// \brief Retrieve the location of the '.' or '->' operator.
SourceLocation getOperatorLoc() const { return OperatorLoc; }
- void setOperatorLoc(SourceLocation L) { OperatorLoc = L; }
/// \brief Retrieve the scope type in a qualified pseudo-destructor
/// expression.
@@ -1409,16 +1400,13 @@ public:
/// nested-name-specifier. It is stored as the "scope type" of the pseudo-
/// destructor expression.
TypeSourceInfo *getScopeTypeInfo() const { return ScopeType; }
- void setScopeTypeInfo(TypeSourceInfo *Info) { ScopeType = Info; }
/// \brief Retrieve the location of the '::' in a qualified pseudo-destructor
/// expression.
SourceLocation getColonColonLoc() const { return ColonColonLoc; }
- void setColonColonLoc(SourceLocation L) { ColonColonLoc = L; }
/// \brief Retrieve the location of the '~'.
SourceLocation getTildeLoc() const { return TildeLoc; }
- void setTildeLoc(SourceLocation L) { TildeLoc = L; }
/// \brief Retrieve the source location information for the type
/// being destroyed.
@@ -1885,30 +1873,24 @@ public:
/// ("value"). Such expressions will instantiate to a DeclRefExpr once the
/// declaration can be found.
class DependentScopeDeclRefExpr : public Expr {
- /// The name of the entity we will be referencing.
- DeclarationNameInfo NameInfo;
-
- /// QualifierRange - The source range that covers the
- /// nested-name-specifier.
- SourceRange QualifierRange;
-
/// \brief The nested-name-specifier that qualifies this unresolved
/// declaration name.
- NestedNameSpecifier *Qualifier;
+ NestedNameSpecifierLoc QualifierLoc;
+
+ /// The name of the entity we will be referencing.
+ DeclarationNameInfo NameInfo;
/// \brief Whether the name includes explicit template arguments.
bool HasExplicitTemplateArgs;
DependentScopeDeclRefExpr(QualType T,
- NestedNameSpecifier *Qualifier,
- SourceRange QualifierRange,
+ NestedNameSpecifierLoc QualifierLoc,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *Args);
public:
static DependentScopeDeclRefExpr *Create(ASTContext &C,
- NestedNameSpecifier *Qualifier,
- SourceRange QualifierRange,
+ NestedNameSpecifierLoc QualifierLoc,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs = 0);
@@ -1918,24 +1900,23 @@ public:
/// \brief Retrieve the name that this expression refers to.
const DeclarationNameInfo &getNameInfo() const { return NameInfo; }
- void setNameInfo(const DeclarationNameInfo &N) { NameInfo = N; }
/// \brief Retrieve the name that this expression refers to.
DeclarationName getDeclName() const { return NameInfo.getName(); }
- void setDeclName(DeclarationName N) { NameInfo.setName(N); }
/// \brief Retrieve the location of the name within the expression.
SourceLocation getLocation() const { return NameInfo.getLoc(); }
- void setLocation(SourceLocation L) { NameInfo.setLoc(L); }
-
- /// \brief Retrieve the source range of the nested-name-specifier.
- SourceRange getQualifierRange() const { return QualifierRange; }
- void setQualifierRange(SourceRange R) { QualifierRange = R; }
+ /// \brief Retrieve the nested-name-specifier that qualifies the
+ /// name, with source location information.
+ NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
+
+
/// \brief Retrieve the nested-name-specifier that qualifies this
/// declaration.
- NestedNameSpecifier *getQualifier() const { return Qualifier; }
- void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; }
+ NestedNameSpecifier *getQualifier() const {
+ return QualifierLoc.getNestedNameSpecifier();
+ }
/// Determines whether this lookup had explicit template arguments.
bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgs; }
@@ -1986,7 +1967,7 @@ public:
}
SourceRange getSourceRange() const {
- SourceRange Range(QualifierRange.getBegin(), getLocation());
+ SourceRange Range(QualifierLoc.getBeginLoc(), getLocation());
if (hasExplicitTemplateArgs())
Range.setEnd(getRAngleLoc());
return Range;
diff --git a/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h b/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h
index 99cc1f2..024bf40 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h
@@ -25,10 +25,12 @@ namespace llvm {
namespace clang {
class ASTContext;
+class NamespaceAliasDecl;
class NamespaceDecl;
class IdentifierInfo;
struct PrintingPolicy;
class Type;
+class TypeLoc;
class LangOptions;
/// \brief Represents a C++ nested name specifier, such as
@@ -41,13 +43,22 @@ class LangOptions;
/// (for dependent names), or the global specifier ('::', must be the
/// first specifier).
class NestedNameSpecifier : public llvm::FoldingSetNode {
+
+ /// \brief Enumeration describing
+ enum StoredSpecifierKind {
+ StoredIdentifier = 0,
+ StoredNamespaceOrAlias = 1,
+ StoredTypeSpec = 2,
+ StoredTypeSpecWithTemplate = 3
+ };
+
/// \brief The nested name specifier that precedes this nested name
/// specifier.
///
/// The pointer is the nested-name-specifier that precedes this
/// one. The integer stores one of the first four values of type
/// SpecifierKind.
- llvm::PointerIntPair<NestedNameSpecifier *, 2> Prefix;
+ llvm::PointerIntPair<NestedNameSpecifier *, 2, StoredSpecifierKind> Prefix;
/// \brief The last component in the nested name specifier, which
/// can be an identifier, a declaration, or a type.
@@ -63,21 +74,23 @@ public:
/// specifier.
enum SpecifierKind {
/// \brief An identifier, stored as an IdentifierInfo*.
- Identifier = 0,
- /// \brief A namespace, stored as a Namespace*.
- Namespace = 1,
+ Identifier,
+ /// \brief A namespace, stored as a NamespaceDecl*.
+ Namespace,
+ /// \brief A namespace alias, stored as a NamespaceAliasDecl*.
+ NamespaceAlias,
/// \brief A type, stored as a Type*.
- TypeSpec = 2,
+ TypeSpec,
/// \brief A type that was preceded by the 'template' keyword,
/// stored as a Type*.
- TypeSpecWithTemplate = 3,
+ TypeSpecWithTemplate,
/// \brief The global specifier '::'. There is no stored value.
- Global = 4
+ Global
};
private:
/// \brief Builds the global specifier.
- NestedNameSpecifier() : Prefix(0, 0), Specifier(0) { }
+ NestedNameSpecifier() : Prefix(0, StoredIdentifier), Specifier(0) { }
/// \brief Copy constructor used internally to clone nested name
/// specifiers.
@@ -108,6 +121,11 @@ public:
NestedNameSpecifier *Prefix,
NamespaceDecl *NS);
+ /// \brief Builds a nested name specifier that names a namespace alias.
+ static NestedNameSpecifier *Create(const ASTContext &Context,
+ NestedNameSpecifier *Prefix,
+ NamespaceAliasDecl *Alias);
+
/// \brief Builds a nested name specifier that names a type.
static NestedNameSpecifier *Create(const ASTContext &Context,
NestedNameSpecifier *Prefix,
@@ -136,16 +154,12 @@ public:
NestedNameSpecifier *getPrefix() const { return Prefix.getPointer(); }
/// \brief Determine what kind of nested name specifier is stored.
- SpecifierKind getKind() const {
- if (Specifier == 0)
- return Global;
- return (SpecifierKind)Prefix.getInt();
- }
+ SpecifierKind getKind() const;
/// \brief Retrieve the identifier stored in this nested name
/// specifier.
IdentifierInfo *getAsIdentifier() const {
- if (Prefix.getInt() == Identifier)
+ if (Prefix.getInt() == StoredIdentifier)
return (IdentifierInfo *)Specifier;
return 0;
@@ -153,17 +167,16 @@ public:
/// \brief Retrieve the namespace stored in this nested name
/// specifier.
- NamespaceDecl *getAsNamespace() const {
- if (Prefix.getInt() == Namespace)
- return (NamespaceDecl *)Specifier;
+ NamespaceDecl *getAsNamespace() const;
- return 0;
- }
+ /// \brief Retrieve the namespace alias stored in this nested name
+ /// specifier.
+ NamespaceAliasDecl *getAsNamespaceAlias() const;
/// \brief Retrieve the type stored in this nested name specifier.
const Type *getAsType() const {
- if (Prefix.getInt() == TypeSpec ||
- Prefix.getInt() == TypeSpecWithTemplate)
+ if (Prefix.getInt() == StoredTypeSpec ||
+ Prefix.getInt() == StoredTypeSpecWithTemplate)
return (const Type *)Specifier;
return 0;
@@ -191,6 +204,114 @@ public:
void dump(const LangOptions &LO);
};
+/// \brief A C++ nested-name-specifier augmented with source location
+/// information.
+class NestedNameSpecifierLoc {
+ NestedNameSpecifier *Qualifier;
+ void *Data;
+
+ /// \brief Determines the data length for the last component in the
+ /// given nested-name-specifier.
+ static unsigned getLocalDataLength(NestedNameSpecifier *Qualifier);
+
+ /// \brief Determines the data length for the entire
+ /// nested-name-specifier.
+ static unsigned getDataLength(NestedNameSpecifier *Qualifier);
+
+public:
+ /// \brief Construct an empty nested-name-specifier.
+ NestedNameSpecifierLoc() : Qualifier(0), Data(0) { }
+
+ /// \brief Construct a nested-name-specifier with source location information
+ /// from
+ NestedNameSpecifierLoc(NestedNameSpecifier *Qualifier, void *Data)
+ : Qualifier(Qualifier), Data(Data) { }
+
+ /// \brief Evalutes true when this nested-name-specifier location is
+ /// non-empty.
+ operator bool() const { return Qualifier; }
+
+ /// \brief Retrieve the nested-name-specifier to which this instance
+ /// refers.
+ NestedNameSpecifier *getNestedNameSpecifier() const {
+ return Qualifier;
+ }
+
+ /// \brief Retrieve the opaque pointer that refers to source-location data.
+ void *getOpaqueData() const { return Data; }
+
+ /// \brief Retrieve the source range covering the entirety of this
+ /// nested-name-specifier.
+ ///
+ /// For example, if this instance refers to a nested-name-specifier
+ /// \c ::std::vector<int>::, the returned source range would cover
+ /// from the initial '::' to the last '::'.
+ SourceRange getSourceRange() const;
+
+ /// \brief Retrieve the source range covering just the last part of
+ /// this nested-name-specifier, not including the prefix.
+ ///
+ /// For example, if this instance refers to a nested-name-specifier
+ /// \c ::std::vector<int>::, the returned source range would cover
+ /// from "vector" to the last '::'.
+ SourceRange getLocalSourceRange() const;
+
+ /// \brief Retrieve the location of the beginning of this
+ /// nested-name-specifier.
+ SourceLocation getBeginLoc() const {
+ return getSourceRange().getBegin();
+ }
+
+ /// \brief Retrieve the location of the end of this
+ /// nested-name-specifier.
+ SourceLocation getEndLoc() const {
+ return getSourceRange().getEnd();
+ }
+
+ /// \brief Retrieve the location of the beginning of this
+ /// component of the nested-name-specifier.
+ SourceLocation getLocalBeginLoc() const {
+ return getLocalSourceRange().getBegin();
+ }
+
+ /// \brief Retrieve the location of the end of this component of the
+ /// nested-name-specifier.
+ SourceLocation getLocalEndLoc() const {
+ return getLocalSourceRange().getEnd();
+ }
+
+ /// \brief Return the prefix of this nested-name-specifier.
+ ///
+ /// For example, if this instance refers to a nested-name-specifier
+ /// \c ::std::vector<int>::, the prefix is \c ::std::. Note that the
+ /// returned prefix may be empty, if this is the first component of
+ /// the nested-name-specifier.
+ NestedNameSpecifierLoc getPrefix() const {
+ if (!Qualifier)
+ return *this;
+
+ return NestedNameSpecifierLoc(Qualifier->getPrefix(), Data);
+ }
+
+ /// \brief For a nested-name-specifier that refers to a type,
+ /// retrieve the type with source-location information.
+ TypeLoc getTypeLoc() const;
+
+ /// \brief Determines the data length for the entire
+ /// nested-name-specifier.
+ unsigned getDataLength() const { return getDataLength(Qualifier); }
+
+ friend bool operator==(NestedNameSpecifierLoc X,
+ NestedNameSpecifierLoc Y) {
+ return X.Qualifier == Y.Qualifier && X.Data == Y.Data;
+ }
+
+ friend bool operator!=(NestedNameSpecifierLoc X,
+ NestedNameSpecifierLoc Y) {
+ return !(X == Y);
+ }
+};
+
/// Insertion operator for diagnostics. This allows sending NestedNameSpecifiers
/// into a diagnostic with <<.
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
diff --git a/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h
index 921b799..e85b6dc 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -181,6 +181,12 @@ public:
/// \returns false if the visitation was terminated early, true otherwise.
bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS);
+ /// \brief Recursively visit a C++ nested-name-specifier with location
+ /// information.
+ ///
+ /// \returns false if the visitation was terminated early, true otherwise.
+ bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
+
/// \brief Recursively visit a template name and dispatch to the
/// appropriate method.
///
@@ -502,6 +508,7 @@ bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifier(
switch (NNS->getKind()) {
case NestedNameSpecifier::Identifier:
case NestedNameSpecifier::Namespace:
+ case NestedNameSpecifier::NamespaceAlias:
case NestedNameSpecifier::Global:
return true;
@@ -514,6 +521,31 @@ bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifier(
}
template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifierLoc(
+ NestedNameSpecifierLoc NNS) {
+ if (!NNS)
+ return true;
+
+ if (NestedNameSpecifierLoc Prefix = NNS.getPrefix())
+ TRY_TO(TraverseNestedNameSpecifierLoc(Prefix));
+
+ switch (NNS.getNestedNameSpecifier()->getKind()) {
+ case NestedNameSpecifier::Identifier:
+ case NestedNameSpecifier::Namespace:
+ case NestedNameSpecifier::NamespaceAlias:
+ case NestedNameSpecifier::Global:
+ return true;
+
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ TRY_TO(TraverseTypeLoc(NNS.getTypeLoc()));
+ break;
+ }
+
+ return true;
+}
+
+template<typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseTemplateName(TemplateName Template) {
if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
TRY_TO(TraverseNestedNameSpecifier(DTN->getQualifier()));
@@ -1142,11 +1174,11 @@ DEF_TRAVERSE_DECL(ObjCPropertyDecl, {
})
DEF_TRAVERSE_DECL(UsingDecl, {
- TRY_TO(TraverseNestedNameSpecifier(D->getTargetNestedNameDecl()));
+ TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
})
DEF_TRAVERSE_DECL(UsingDirectiveDecl, {
- TRY_TO(TraverseNestedNameSpecifier(D->getQualifier()));
+ TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
})
DEF_TRAVERSE_DECL(UsingShadowDecl, { })
@@ -1312,7 +1344,7 @@ DEF_TRAVERSE_DECL(TypedefDecl, {
DEF_TRAVERSE_DECL(UnresolvedUsingTypenameDecl, {
// A dependent using declaration which was marked with 'typename'.
// template<class T> class A : public B<T> { using typename B<T>::foo; };
- TRY_TO(TraverseNestedNameSpecifier(D->getTargetNestedNameSpecifier()));
+ TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
// We shouldn't traverse D->getTypeForDecl(); it's a result of
// declaring the type, not something that was written in the
// source.
@@ -1425,7 +1457,7 @@ DEF_TRAVERSE_DECL(EnumConstantDecl, {
DEF_TRAVERSE_DECL(UnresolvedUsingValueDecl, {
// Like UnresolvedUsingTypenameDecl, but without the 'typename':
// template <class T> Class A : public Base<T> { using Base<T>::foo; };
- TRY_TO(TraverseNestedNameSpecifier(D->getTargetNestedNameSpecifier()));
+ TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
})
DEF_TRAVERSE_DECL(IndirectFieldDecl, {})
@@ -1660,20 +1692,18 @@ DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, {
})
DEF_TRAVERSE_STMT(DeclRefExpr, {
+ TRY_TO(TraverseNestedNameSpecifier(S->getQualifier()));
TRY_TO(TraverseTemplateArgumentLocsHelper(
S->getTemplateArgs(), S->getNumTemplateArgs()));
- // FIXME: Should we be recursing on the qualifier?
- TRY_TO(TraverseNestedNameSpecifier(S->getQualifier()));
})
DEF_TRAVERSE_STMT(DependentScopeDeclRefExpr, {
- // FIXME: Should we be recursing on these two things?
+ TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
if (S->hasExplicitTemplateArgs()) {
TRY_TO(TraverseTemplateArgumentLocsHelper(
S->getExplicitTemplateArgs().getTemplateArgs(),
S->getNumTemplateArgs()));
}
- TRY_TO(TraverseNestedNameSpecifier(S->getQualifier()));
})
DEF_TRAVERSE_STMT(MemberExpr, {
@@ -1814,7 +1844,7 @@ DEF_TRAVERSE_STMT(CXXDeleteExpr, { })
DEF_TRAVERSE_STMT(ExprWithCleanups, { })
DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, { })
DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, {
- TRY_TO(TraverseNestedNameSpecifier(S->getQualifier()));
+ TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
if (TypeSourceInfo *ScopeInfo = S->getScopeTypeInfo())
TRY_TO(TraverseTypeLoc(ScopeInfo->getTypeLoc()));
if (TypeSourceInfo *DestroyedTypeInfo = S->getDestroyedTypeInfo())
diff --git a/contrib/llvm/tools/clang/include/clang/AST/Stmt.h b/contrib/llvm/tools/clang/include/clang/AST/Stmt.h
index 7ede9ce..d1f7d66 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/Stmt.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/Stmt.h
@@ -1328,7 +1328,8 @@ public:
}
Expr *getInputExpr(unsigned i);
-
+ void setInputExpr(unsigned i, Expr *E);
+
const Expr *getInputExpr(unsigned i) const {
return const_cast<AsmStmt*>(this)->getInputExpr(i);
}
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h
new file mode 100644
index 0000000..72f644a
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h
@@ -0,0 +1,49 @@
+//==- CFGReachabilityAnalysis.h - Basic reachability analysis ----*- 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 a flow-sensitive, (mostly) path-insensitive reachability
+// analysis based on Clang's CFGs. Clients can query if a given basic block
+// is reachable within the CFG.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_ANALYSIS_CFG_REACHABILITY
+#define CLANG_ANALYSIS_CFG_REACHABILITY
+
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseMap.h"
+
+namespace clang {
+
+class CFG;
+class CFGBlock;
+
+// A class that performs reachability queries for CFGBlocks. Several internal
+// checks in this checker require reachability information. The requests all
+// tend to have a common destination, so we lazily do a predecessor search
+// from the destination node and cache the results to prevent work
+// duplication.
+class CFGReachabilityAnalysis {
+ typedef llvm::BitVector ReachableSet;
+ typedef llvm::DenseMap<unsigned, ReachableSet> ReachableMap;
+ ReachableSet analyzed;
+ ReachableMap reachable;
+public:
+ CFGReachabilityAnalysis(const CFG &cfg);
+
+ /// Returns true if the block 'Dst' can be reached from block 'Src'.
+ bool isReachable(const CFGBlock *Src, const CFGBlock *Dst);
+
+private:
+ void mapReachability(const CFGBlock *Dst);
+};
+
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h b/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h
index 2ecbfdc..8514514 100644
--- a/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h
@@ -29,6 +29,8 @@ class Decl;
class Stmt;
class CFG;
class CFGBlock;
+class CFGReachabilityAnalysis;
+class CFGStmtMap;
class LiveVariables;
class ParentMap;
class PseudoConstantAnalysis;
@@ -48,11 +50,13 @@ class AnalysisContext {
// AnalysisContext owns the following data.
CFG *cfg, *completeCFG;
+ CFGStmtMap *cfgStmtMap;
bool builtCFG, builtCompleteCFG;
LiveVariables *liveness;
LiveVariables *relaxedLiveness;
ParentMap *PM;
PseudoConstantAnalysis *PCA;
+ CFGReachabilityAnalysis *CFA;
llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
llvm::BumpPtrAllocator A;
bool UseUnoptimizedCFG;
@@ -65,9 +69,9 @@ public:
bool addehedges = false,
bool addImplicitDtors = false,
bool addInitializers = false)
- : D(d), TU(tu), cfg(0), completeCFG(0),
+ : D(d), TU(tu), cfg(0), completeCFG(0), cfgStmtMap(0),
builtCFG(false), builtCompleteCFG(false),
- liveness(0), relaxedLiveness(0), PM(0), PCA(0),
+ liveness(0), relaxedLiveness(0), PM(0), PCA(0), CFA(0),
ReferencedBlockVars(0), UseUnoptimizedCFG(useUnoptimizedCFG),
AddEHEdges(addehedges), AddImplicitDtors(addImplicitDtors),
AddInitializers(addInitializers) {}
@@ -91,7 +95,11 @@ public:
Stmt *getBody();
CFG *getCFG();
+
+ CFGStmtMap *getCFGStmtMap();
+ CFGReachabilityAnalysis *getCFGReachablityAnalysis();
+
/// Return a version of the CFG without any edges pruned.
CFG *getUnoptimizedCFG();
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def
index 7d270ad..b73ac1f 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def
@@ -60,6 +60,7 @@
// n -> nothrow
// r -> noreturn
// c -> const
+// t -> signature is meaningless, use custom typechecking
// F -> this is a libc/libm function with a '__builtin_' prefix added.
// f -> this is a libc/libm function without the '__builtin_' prefix. It can
// be followed by ':headername:' to state which header this function
@@ -383,8 +384,8 @@ BUILTIN(__builtin_bswap32, "UiUi", "nc")
BUILTIN(__builtin_bswap64, "ULLiULLi", "nc")
// Random GCC builtins
-BUILTIN(__builtin_constant_p, "i.", "nc")
-BUILTIN(__builtin_classify_type, "i.", "nc")
+BUILTIN(__builtin_constant_p, "i.", "nct")
+BUILTIN(__builtin_classify_type, "i.", "nct")
BUILTIN(__builtin___CFStringMakeConstantString, "FC*cC*", "nc")
BUILTIN(__builtin___NSStringMakeConstantString, "FC*cC*", "nc")
BUILTIN(__builtin_va_start, "vA.", "n")
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Builtins.h b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.h
index 4df4c8f..0d17e03 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Builtins.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.h
@@ -117,6 +117,11 @@ public:
return strchr(GetRecord(ID).Attributes, 'f') != 0;
}
+ /// \brief Determines whether this builtin has custom typechecking.
+ bool hasCustomTypechecking(unsigned ID) const {
+ return strchr(GetRecord(ID).Attributes, 't') != 0;
+ }
+
/// \brief Completely forget that the given ID was ever considered a builtin,
/// e.g., because the user provided a conflicting signature.
void ForgetBuiltin(unsigned ID, IdentifierTable &Table);
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h
index 19e7c91..3fc60d1 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h
@@ -474,8 +474,9 @@ public:
///
/// \param Loc The source location we are interested in finding out the
/// diagnostic state. Can be null in order to query the latest state.
- Level getDiagnosticLevel(unsigned DiagID, SourceLocation Loc) const {
- return (Level)Diags->getDiagnosticLevel(DiagID, Loc, *this);
+ Level getDiagnosticLevel(unsigned DiagID, SourceLocation Loc,
+ diag::Mapping *mapping = 0) const {
+ return (Level)Diags->getDiagnosticLevel(DiagID, Loc, *this, mapping);
}
/// Report - Issue the message to the client. @c DiagID is a member of the
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index 5f9f4a7..3070676 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -177,12 +177,15 @@ def warn_pch_elide_constructors : Error<
def warn_pch_exceptions : Error<
"exceptions were %select{disabled|enabled}0 in PCH file but "
"are currently %select{disabled|enabled}1">;
-def warn_pch_sjlj_exceptions : Error<
- "sjlj-exceptions were %select{disabled|enabled}0 in PCH file but "
- "are currently %select{disabled|enabled}1">;
def warn_pch_objc_exceptions : Error<
"Objective-C exceptions were %select{disabled|enabled}0 in PCH file but "
"are currently %select{disabled|enabled}1">;
+def warn_pch_cxx_exceptions : Error<
+ "C++ exceptions were %select{disabled|enabled}0 in PCH file but "
+ "are currently %select{disabled|enabled}1">;
+def warn_pch_sjlj_exceptions : Error<
+ "sjlj-exceptions were %select{disabled|enabled}0 in PCH file but "
+ "are currently %select{disabled|enabled}1">;
def warn_pch_objc_runtime : Error<
"PCH file was compiled with the %select{NeXT|GNU}0 runtime but the "
"%select{NeXT|GNU}1 runtime is selected">;
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td
index d4377c9..412fb58 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td
@@ -198,9 +198,11 @@ def Unused : DiagGroup<"unused",
DiagCategory<"Unused Entity Issue">;
// Format settings.
-def Format : DiagGroup<"format", [FormatExtraArgs, FormatZeroLength, NonNull]>,
+def FormatSecurity : DiagGroup<"format-security">;
+def Format : DiagGroup<"format",
+ [FormatExtraArgs, FormatZeroLength, NonNull,
+ FormatSecurity]>,
DiagCategory<"Format String Issue">;
-def FormatSecurity : DiagGroup<"format-security", [Format]>;
def FormatNonLiteral : DiagGroup<"format-nonliteral", [FormatSecurity]>;
def FormatY2K : DiagGroup<"format-y2k", [Format]>;
def Format2 : DiagGroup<"format=2",
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h
index b463805..2b03cae 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h
@@ -188,14 +188,16 @@ private:
/// \param Loc The source location we are interested in finding out the
/// diagnostic state. Can be null in order to query the latest state.
DiagnosticIDs::Level getDiagnosticLevel(unsigned DiagID, SourceLocation Loc,
- const Diagnostic &Diag) const;
+ const Diagnostic &Diag,
+ diag::Mapping *mapping = 0) const;
/// getDiagnosticLevel - This is an internal implementation helper used when
/// DiagClass is already known.
DiagnosticIDs::Level getDiagnosticLevel(unsigned DiagID,
unsigned DiagClass,
SourceLocation Loc,
- const Diagnostic &Diag) const;
+ const Diagnostic &Diag,
+ diag::Mapping *mapping = 0) const;
/// ProcessDiag - This is the method used to report a diagnostic that is
/// finally fully formed.
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td
index 9d7ec9d..9a68af9 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -28,6 +28,10 @@ def ext_extra_struct_semi : Extension<
def ext_extra_ivar_semi : Extension<
"extra ';' inside instance variable list">;
+def auto_storage_class : ExtWarn<
+ "'auto' storage class specifier is redundant and will be "
+ "removed in future releases">;
+
def ext_duplicate_declspec : Extension<"duplicate '%0' declaration specifier">;
def ext_plain_complex : ExtWarn<
"plain '_Complex' requires a type specifier; assuming '_Complex double'">;
@@ -57,6 +61,11 @@ def ext_enumerator_list_comma : Extension<
"feature">;
def err_enumerator_list_missing_comma : Error<
"missing ',' between enumerators">;
+def err_enumerator_unnamed_no_def : Error<
+ "unnamed enumeration must be a definition">;
+def ext_ms_enum_fixed_underlying_type : Extension<
+ "enumeration types with a fixed underlying type are a Microsoft extension">,
+ InGroup<Microsoft>;
def ext_gnu_indirect_goto : Extension<
"use of GNU indirect-goto extension">, InGroup<GNU>;
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 2e7f274..a9fb2da 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -351,12 +351,18 @@ def note_required_for_protocol_at :
def warn_conflicting_ret_types : Warning<
"conflicting return type in implementation of %0: %1 vs %2">;
+def warn_conflicting_ret_type_modifiers : Warning<
+ "conflicting distributed object modifiers on return type "
+ "in implementation of %0">;
def warn_non_covariant_ret_types : Warning<
"conflicting return type in implementation of %0: %1 vs %2">,
InGroup<DiagGroup<"method-signatures">>, DefaultIgnore;
def warn_conflicting_param_types : Warning<
"conflicting parameter types in implementation of %0: %1 vs %2">;
+def warn_conflicting_param_modifiers : Warning<
+ "conflicting distributed object modifiers on parameter type "
+ "in implementation of %0">;
def warn_non_contravariant_param_types : Warning<
"conflicting parameter types in implementation of %0: %1 vs %2">,
InGroup<DiagGroup<"method-signatures">>, DefaultIgnore;
@@ -898,7 +904,8 @@ def err_new_array_of_auto : Error<
def err_auto_not_allowed : Error<
"'auto' not allowed %select{in function prototype|in struct member"
"|in union member|in class member|in exception declaration"
- "|in template parameter|in block literal|in template argument|here}0">;
+ "|in template parameter|in block literal|in template argument"
+ "|in typedef|in function return type|here}0">;
def err_auto_var_requires_init : Error<
"declaration of variable %0 with type %1 requires an initializer">;
def err_auto_new_requires_ctor_arg : Error<
@@ -911,6 +918,8 @@ def err_auto_missing_trailing_return : Error<
"'auto' return without trailing return type">;
def err_trailing_return_without_auto : Error<
"function with trailing return type must specify return type 'auto', not %0">;
+def err_trailing_return_in_parens : Error<
+ "trailing return type may not be nested within parentheses">;
def err_auto_var_deduction_failure : Error<
"variable %0 with type %1 has incompatible initializer of type %2">;
def err_auto_new_deduction_failure : Error<
@@ -1145,6 +1154,9 @@ def warn_impcast_literal_float_to_integer : Warning<
"implicit conversion turns literal floating-point number into integer: "
"%0 to %1">,
InGroup<DiagGroup<"literal-conversion">>, DefaultIgnore;
+def warn_impcast_different_enum_types : Warning<
+ "implicit conversion from enumeration type %0 to different enumeration type "
+ "%1">, InGroup<DiagGroup<"conversion">>;
def warn_cast_align : Warning<
"cast from %0 to %1 increases required alignment from %2 to %3">,
@@ -1299,11 +1311,11 @@ def err_ovl_no_viable_member_function_in_call : Error<
def err_ovl_ambiguous_call : Error<
"call to %0 is ambiguous">;
def err_ovl_deleted_call : Error<
- "call to %select{unavailable|deleted}0 function %1">;
+ "call to %select{unavailable|deleted}0 function %1 %2">;
def err_ovl_ambiguous_member_call : Error<
"call to member function %0 is ambiguous">;
def err_ovl_deleted_member_call : Error<
- "call to %select{unavailable|deleted}0 member function %1">;
+ "call to %select{unavailable|deleted}0 member function %1 %2">;
def note_ovl_too_many_candidates : Note<
"remaining %0 candidate%s0 omitted; "
"pass -fshow-overloads=all to show them">;
@@ -1455,7 +1467,7 @@ def err_ovl_ambiguous_oper_binary : Error<
"use of overloaded operator '%0' is ambiguous (with operand types %1 and %2)">;
def err_ovl_no_viable_oper : Error<"no viable overloaded '%0'">;
def err_ovl_deleted_oper : Error<
- "overload resolution selected %select{unavailable|deleted}0 operator '%1'">;
+ "overload resolution selected %select{unavailable|deleted}0 operator '%1' %2">;
def err_ovl_no_viable_subscript :
Error<"no viable overloaded operator[] for type %0">;
def err_ovl_no_oper :
@@ -1469,7 +1481,7 @@ def err_ovl_no_viable_object_call : Error<
def err_ovl_ambiguous_object_call : Error<
"call to object of type %0 is ambiguous">;
def err_ovl_deleted_object_call : Error<
- "call to %select{unavailable|deleted}0 function call operator in type %1">;
+ "call to %select{unavailable|deleted}0 function call operator in type %1 %2">;
def note_ovl_surrogate_cand : Note<"conversion candidate of type %0">;
def err_member_call_without_object : Error<
"call to non-static member function without an object argument">;
@@ -2015,9 +2027,10 @@ def err_redefinition_extern_inline : Error<
// This should eventually be an error.
def warn_undefined_internal : Warning<
- "%select{function|variable}0 %q1 has internal linkage but is not defined">;
+ "%select{function|variable}0 %q1 has internal linkage but is not defined">,
+ DiagGroup<"undefined-internal">;
def note_used_here : Note<"used here">;
-
+
def warn_redefinition_of_typedef : Warning<
"redefinition of typedef %0 is invalid in C">,
InGroup<DiagGroup<"typedef-redefinition"> >, DefaultError;
@@ -2328,6 +2341,13 @@ def warn_division_by_zero : Warning<"division by zero is undefined">;
def warn_remainder_by_zero : Warning<"remainder by zero is undefined">;
def warn_shift_negative : Warning<"shift count is negative">;
def warn_shift_gt_typewidth : Warning<"shift count >= width of type">;
+def warn_shift_result_gt_typewidth : Warning<
+ "shift result (%0) requires %1 bits to represent, but %2 only has %3 bits">,
+ InGroup<DiagGroup<"shift-overflow">>;
+def warn_shift_result_overrides_sign_bit : Warning<
+ "shift result (%0) overrides the sign bit of the shift expression's type "
+ "(%1) and becomes negative">,
+ InGroup<DiagGroup<"shift-sign-overflow">>, DefaultIgnore;
def warn_precedence_bitwise_rel : Warning<
"%0 has lower precedence than %1; %1 will be evaluated first">,
@@ -2387,13 +2407,10 @@ def err_typecheck_member_reference_type : Error<
def err_typecheck_member_reference_unknown : Error<
"cannot refer to member %0 in %1 with '%select{.|->}2'">;
def err_member_reference_needs_call : Error<
- "base of member reference is an overloaded function; perhaps you meant "
- "to call %select{it|the 0-argument overload}0?">;
+ "base of member reference is %select{a function|an overloaded function}0; "
+ "perhaps you meant to call it%select{| with no arguments}1?">;
def note_member_ref_possible_intended_overload : Note<
"possibly valid overload here">;
-def err_member_reference_needs_call_zero_arg : Error<
- "base of member reference has function type %0; perhaps you meant to call "
- "this function with '()'?">;
def warn_subscript_is_char : Warning<"array subscript is of type 'char'">,
InGroup<CharSubscript>, DefaultIgnore;
@@ -2452,6 +2469,13 @@ def err_typecheck_incomplete_array_needs_initializer : Error<
def err_array_init_not_init_list : Error<
"array initializer must be an initializer "
"list%select{| or string literal}0">;
+def err_array_init_different_type : Error<
+ "cannot initialize array of type %0 with array of type %1">;
+def err_array_init_non_constant_array : Error<
+ "cannot initialize array of type %0 with non-constant array of type %1">;
+def ext_array_init_copy : Extension<
+ "initialization of an array of type %0 from a compound literal of type %1 is "
+ "a GNU extension">;
def warn_deprecated_string_literal_conversion : Warning<
"conversion from string literal to %0 is deprecated">, InGroup<DeprecatedWritableStr>;
def err_realimag_invalid_type : Error<"invalid type %0 to %1 operator">;
@@ -2950,10 +2974,7 @@ def note_equality_comparison_silence : Note<
def warn_synthesized_ivar_access : Warning<
"direct access of synthesized ivar by using property access %0">,
InGroup<NonfragileAbi2>, DefaultIgnore;
-def warn_ivar_variable_conflict : Warning<
- "when default property synthesis is on, "
- "%0 lookup will access property ivar instead of global variable">,
- InGroup<NonfragileAbi2>;
+
def note_global_declared_at : Note<"global variable declared here">;
// assignment related diagnostics (also for argument passing, returning, etc).
@@ -3108,6 +3129,8 @@ def err_kern_type_not_void_return : Error<
"kernel function type %0 must have void return type">;
def err_config_scalar_return : Error<
"CUDA special function 'cudaConfigureCall' must have scalar return type">;
+def err_kern_call_not_global_function : Error<
+ "kernel call to non-global function %0">;
def err_cannot_pass_objc_interface_to_vararg : Error<
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h b/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h
index b148943..a9fd25c 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h
@@ -53,8 +53,9 @@ public:
unsigned LaxVectorConversions : 1;
unsigned AltiVec : 1; // Support AltiVec-style vector initializers.
unsigned Exceptions : 1; // Support exception handling.
- unsigned SjLjExceptions : 1; // Use setjmp-longjump exception handling.
unsigned ObjCExceptions : 1; // Support Objective-C exceptions.
+ unsigned CXXExceptions : 1; // Support C++ exceptions.
+ unsigned SjLjExceptions : 1; // Use setjmp-longjump exception handling.
unsigned RTTI : 1; // Support RTTI information.
unsigned MSBitfields : 1; // MS-compatible structure layout
@@ -166,8 +167,8 @@ public:
NoConstantCFStrings = 0; InlineVisibilityHidden = 0;
C99 = Microsoft = Borland = CPlusPlus = CPlusPlus0x = 0;
CXXOperatorNames = PascalStrings = WritableStrings = ConstStrings = 0;
- Exceptions = SjLjExceptions = Freestanding = NoBuiltin = 0;
- ObjCExceptions = 1;
+ Exceptions = ObjCExceptions = CXXExceptions = SjLjExceptions = 0;
+ Freestanding = NoBuiltin = 0;
MSBitfields = 0;
NeXTRuntime = 1;
RTTI = 1;
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h
index d00195b..c636194 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h
@@ -75,7 +75,7 @@ public:
/// \brief An allocator for Storage objects, which uses a small cache to
/// objects, used to reduce malloc()/free() traffic for partial diagnostics.
class StorageAllocator {
- static const unsigned NumCached = 4;
+ static const unsigned NumCached = 16;
Storage Cached[NumCached];
Storage *FreeList[NumCached];
unsigned NumFreeListEntries;
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h b/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h
index c0fbd08..b1443da 100644
--- a/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h
+++ b/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h
@@ -684,10 +684,10 @@ public:
/// before calling this method.
unsigned getColumnNumber(FileID FID, unsigned FilePos,
bool *Invalid = 0) const;
- unsigned getSpellingColumnNumber(SourceLocation Loc,
- bool *Invalid = 0) const;
+ unsigned getSpellingColumnNumber(SourceLocation Loc, bool *Invalid = 0) const;
unsigned getInstantiationColumnNumber(SourceLocation Loc,
bool *Invalid = 0) const;
+ unsigned getPresumedColumnNumber(SourceLocation Loc, bool *Invalid = 0) const;
/// getLineNumber - Given a SourceLocation, return the spelling line number
@@ -695,10 +695,10 @@ public:
/// line offsets for the MemoryBuffer, so this is not cheap: use only when
/// about to emit a diagnostic.
unsigned getLineNumber(FileID FID, unsigned FilePos, bool *Invalid = 0) const;
-
+ unsigned getSpellingLineNumber(SourceLocation Loc, bool *Invalid = 0) const;
unsigned getInstantiationLineNumber(SourceLocation Loc,
bool *Invalid = 0) const;
- unsigned getSpellingLineNumber(SourceLocation Loc, bool *Invalid = 0) const;
+ unsigned getPresumedLineNumber(SourceLocation Loc, bool *Invalid = 0) const;
/// Return the filename or buffer identifier of the buffer the location is in.
/// Note that this name does not respect #line directives. Use getPresumedLoc
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td b/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td
index 57107ba..186ba9b 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td
+++ b/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td
@@ -73,9 +73,6 @@ def analyzer_display_progress : Flag<"-analyzer-display-progress">,
HelpText<"Emit verbose output about the analyzer's progress">;
def analyzer_experimental_checks : Flag<"-analyzer-experimental-checks">,
HelpText<"Use experimental path-sensitive checks">;
-def analyzer_experimental_internal_checks :
- Flag<"-analyzer-experimental-internal-checks">,
- HelpText<"Use new default path-sensitive checks currently in testing">;
def analyze_function : Separate<"-analyze-function">,
HelpText<"Run analysis on specific function">;
def analyze_function_EQ : Joined<"-analyze-function=">, Alias<analyze_function>;
@@ -108,6 +105,9 @@ def analyzer_disable_checker : Separate<"-analyzer-disable-checker">,
def analyzer_disable_checker_EQ : Joined<"-analyzer-disable-checker=">,
Alias<analyzer_disable_checker>;
+def analyzer_checker_help : Flag<"-analyzer-checker-help">,
+ HelpText<"Display the list of analyzer checkers that are available">;
+
//===----------------------------------------------------------------------===//
// CodeGen Options
//===----------------------------------------------------------------------===//
@@ -418,10 +418,12 @@ def fblocks : Flag<"-fblocks">,
def fheinous_gnu_extensions : Flag<"-fheinous-gnu-extensions">;
def fexceptions : Flag<"-fexceptions">,
HelpText<"Enable support for exception handling">;
+def fobjc_exceptions : Flag<"-fobjc-exceptions">,
+ HelpText<"Enable Objective-C exceptions">;
+def fcxx_exceptions : Flag<"-fcxx-exceptions">,
+ HelpText<"Enable C++ exceptions">;
def fsjlj_exceptions : Flag<"-fsjlj-exceptions">,
HelpText<"Use SjLj style exceptions">;
-def fno_objc_exceptions : Flag<"-fno-objc-exceptions">,
- HelpText<"Disable Objective-C exceptions">;
def ffreestanding : Flag<"-ffreestanding">,
HelpText<"Assert that the compilation takes place in a freestanding environment">;
def fformat_extensions : Flag<"-fformat-extensions">,
@@ -538,6 +540,8 @@ def idirafter : JoinedOrSeparate<"-idirafter">, MetaVarName<"<directory>">,
HelpText<"Add directory to AFTER include search path">;
def iquote : JoinedOrSeparate<"-iquote">, MetaVarName<"<directory>">,
HelpText<"Add directory to QUOTE include search path">;
+def cxx_isystem : JoinedOrSeparate<"-cxx-isystem">, MetaVarName<"<directory>">,
+ HelpText<"Add directory to the C++ SYSTEM include search path">;
def isystem : JoinedOrSeparate<"-isystem">, MetaVarName<"<directory>">,
HelpText<"Add directory to SYSTEM include search path">;
def iwithsysroot : JoinedOrSeparate<"-iwithsysroot">,MetaVarName<"<directory>">,
@@ -552,8 +556,6 @@ def iwithprefixbefore : JoinedOrSeparate<"-iwithprefixbefore">,
HelpText<"Set directory to include search path with prefix">;
def isysroot : JoinedOrSeparate<"-isysroot">, MetaVarName<"<dir>">,
HelpText<"Set the system root directory (usually /)">;
-def cxx_system_include : Separate<"-cxx-system-include">,
- HelpText<"Add a system #include directory for the C++ standard library">;
def v : Flag<"-v">, HelpText<"Enable verbose output">;
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Options.td b/contrib/llvm/tools/clang/include/clang/Driver/Options.td
index 1a8a150..0faab3b 100644
--- a/contrib/llvm/tools/clang/include/clang/Driver/Options.td
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Options.td
@@ -208,6 +208,7 @@ def compatibility__version : JoinedOrSeparate<"-compatibility_version">;
def coverage : Flag<"-coverage">;
def cpp_precomp : Flag<"-cpp-precomp">;
def current__version : JoinedOrSeparate<"-current_version">;
+def cxx_isystem : JoinedOrSeparate<"-cxx-isystem">, Group<clang_i_Group>;
def c : Flag<"-c">, Flags<[DriverOption]>,
HelpText<"Only run preprocess, compile, and assemble steps">;
def dA : Flag<"-dA">, Group<d_Group>;
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/AnalyzerOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/AnalyzerOptions.h
index 5806928..64263c1 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/AnalyzerOptions.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/AnalyzerOptions.h
@@ -64,6 +64,7 @@ public:
std::string AnalyzeSpecificFunction;
unsigned MaxNodes;
unsigned MaxLoop;
+ unsigned ShowCheckerHelp : 1;
unsigned AnalyzeAll : 1;
unsigned AnalyzerDisplayProgress : 1;
unsigned AnalyzeNestedBlocks : 1;
@@ -75,7 +76,6 @@ public:
unsigned VisualizeEGDot : 1;
unsigned VisualizeEGUbi : 1;
unsigned EnableExperimentalChecks : 1;
- unsigned EnableExperimentalInternalChecks : 1;
unsigned InlineCall : 1;
unsigned UnoptimizedCFG : 1;
unsigned CFGAddImplicitDtors : 1;
@@ -87,6 +87,7 @@ public:
AnalysisStoreOpt = BasicStoreModel;
AnalysisConstraintsOpt = RangeConstraintsModel;
AnalysisDiagOpt = PD_HTML;
+ ShowCheckerHelp = 0;
AnalyzeAll = 0;
AnalyzerDisplayProgress = 0;
AnalyzeNestedBlocks = 0;
@@ -98,7 +99,6 @@ public:
VisualizeEGDot = 0;
VisualizeEGUbi = 0;
EnableExperimentalChecks = 0;
- EnableExperimentalInternalChecks = 0;
InlineCall = 0;
UnoptimizedCFG = 0;
CFGAddImplicitDtors = 0;
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/DeclXML.def b/contrib/llvm/tools/clang/include/clang/Frontend/DeclXML.def
index 1b158fd..58f7e55 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/DeclXML.def
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/DeclXML.def
@@ -349,7 +349,7 @@ NODE_XML(UsingDecl, "Using")
ID_ATTRIBUTE_XML
ATTRIBUTE_FILE_LOCATION_XML
ATTRIBUTE_XML(getDeclContext(), "context")
- ATTRIBUTE_XML(getTargetNestedNameDecl(), "target_nested_namespace_decl")
+ ATTRIBUTE_XML(getQualifier(), "target_nested_namespace_decl")
ATTRIBUTE_XML(isTypeName(), "is_typename")
END_NODE_XML
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/HeaderSearchOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/HeaderSearchOptions.h
index cbb4a57..b0669eb 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/HeaderSearchOptions.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/HeaderSearchOptions.h
@@ -22,6 +22,7 @@ namespace frontend {
Quoted = 0, ///< `#include ""` paths. Thing `gcc -iquote`.
Angled, ///< Paths for both `#include ""` and `#include <>`. (`-I`)
System, ///< Like Angled, but marks system directories.
+ CXXSystem, ///< Like System, but only used for C++.
After ///< Like System, but searched after the system directories.
};
}
@@ -54,9 +55,6 @@ public:
/// User specified include entries.
std::vector<Entry> UserEntries;
- /// If non-empty, the list of C++ standard include paths to use.
- std::vector<std::string> CXXSystemIncludes;
-
/// A (system-path) delimited list of include paths to be added from the
/// environment following the user specified includes (but prior to builtin
/// and standard includes). This is parsed in the same manner as the CPATH
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h b/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h
index 485161b..02342c1 100644
--- a/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h
@@ -28,6 +28,7 @@ class Decl;
class DependencyOutputOptions;
class Diagnostic;
class DiagnosticOptions;
+class FileManager;
class HeaderSearch;
class HeaderSearchOptions;
class IdentifierTable;
@@ -42,7 +43,8 @@ class FrontendOptions;
/// Normalize \arg File for use in a user defined #include directive (in the
/// predefines buffer).
-std::string NormalizeDashIncludePath(llvm::StringRef File);
+std::string NormalizeDashIncludePath(llvm::StringRef File,
+ FileManager &FileMgr);
/// Apply the header search options to get given HeaderSearch object.
void ApplyHeaderSearchOptions(HeaderSearch &HS,
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h b/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h
index 018f7e9..9005adc 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h
@@ -942,9 +942,6 @@ private:
/// is not enclosed within a string literal.
void HandleMicrosoft__pragma(Token &Tok);
- void Handle_Pragma(unsigned Introducer, const std::string &StrVal,
- SourceLocation PragmaLoc, SourceLocation RParenLoc);
-
/// EnterSourceFileWithLexer - Add a lexer to the top of the include stack and
/// start lexing tokens from it instead of the current buffer.
void EnterSourceFileWithLexer(Lexer *TheLexer, const DirectoryLookup *Dir);
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h b/contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h
index 3f13e9c..6ae00cd 100644
--- a/contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h
+++ b/contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h
@@ -121,6 +121,10 @@ public:
/// Lex - Lex and return a token from this macro stream.
void Lex(Token &Tok);
+ /// isParsingPreprocessorDirective - Return true if we are in the middle of a
+ /// preprocessor directive.
+ bool isParsingPreprocessorDirective() const;
+
private:
void destroy();
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/AnalysisBasedWarnings.h b/contrib/llvm/tools/clang/include/clang/Sema/AnalysisBasedWarnings.h
index 0a6656e..8b389b1 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/AnalysisBasedWarnings.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/AnalysisBasedWarnings.h
@@ -25,6 +25,9 @@ class FunctionDecl;
class ObjCMethodDecl;
class QualType;
class Sema;
+namespace sema {
+ class FunctionScopeInfo;
+}
namespace sema {
@@ -47,16 +50,14 @@ private:
enum VisitFlag { NotVisited = 0, Visited = 1, Pending = 2 };
llvm::DenseMap<const FunctionDecl*, VisitFlag> VisitedFD;
- void IssueWarnings(Policy P, const Decl *D, QualType BlockTy);
public:
AnalysisBasedWarnings(Sema &s);
- Policy getDefaultPolicy() { return DefaultPolicy; }
+ void IssueWarnings(Policy P, FunctionScopeInfo *fscope,
+ const Decl *D, const BlockExpr *blkExpr);
- void IssueWarnings(Policy P, const BlockExpr *E);
- void IssueWarnings(Policy P, const FunctionDecl *D);
- void IssueWarnings(Policy P, const ObjCMethodDecl *D);
+ Policy getDefaultPolicy() { return DefaultPolicy; }
};
}} // end namespace clang::sema
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h b/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h
index 9c4bb64..64126bd 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h
@@ -29,10 +29,15 @@
#include "llvm/Support/ErrorHandling.h"
namespace clang {
+ class ASTContext;
+ class TypeLoc;
class LangOptions;
class Diagnostic;
class IdentifierInfo;
+ class NamespaceAliasDecl;
+ class NamespaceDecl;
class NestedNameSpecifier;
+ class NestedNameSpecifierLoc;
class Preprocessor;
class Declarator;
struct TemplateIdAnnotation;
@@ -52,9 +57,29 @@ class CXXScopeSpec {
SourceRange Range;
NestedNameSpecifier *ScopeRep;
-public:
- CXXScopeSpec() : Range(), ScopeRep() { }
+ /// \brief Buffer used to store source-location information for the
+ /// nested-name-specifier.
+ ///
+ /// Note that we explicitly manage the buffer (rather than using a
+ /// SmallVector) because \c Declarator expects it to be possible to memcpy()
+ /// a \c CXXScopeSpec.
+ char *Buffer;
+
+ /// \brief The size of the buffer used to store source-location information
+ /// for the nested-name-specifier.
+ unsigned BufferSize;
+
+ /// \brief The capacity of the buffer used to store source-location
+ /// information for the nested-name-specifier.
+ unsigned BufferCapacity;
+public:
+ CXXScopeSpec() : Range(), ScopeRep(), Buffer(0), BufferSize(0),
+ BufferCapacity(0) { }
+ CXXScopeSpec(const CXXScopeSpec &Other);
+ CXXScopeSpec &operator=(const CXXScopeSpec &Other);
+ ~CXXScopeSpec();
+
const SourceRange &getRange() const { return Range; }
void setRange(const SourceRange &R) { Range = R; }
void setBeginLoc(SourceLocation Loc) { Range.setBegin(Loc); }
@@ -63,7 +88,87 @@ public:
SourceLocation getEndLoc() const { return Range.getEnd(); }
NestedNameSpecifier *getScopeRep() const { return ScopeRep; }
- void setScopeRep(NestedNameSpecifier *S) { ScopeRep = S; }
+
+ /// \brief Extend the current nested-name-specifier by another
+ /// nested-name-specifier component of the form 'type::'.
+ ///
+ /// \param Context The AST context in which this nested-name-specifier
+ /// resides.
+ ///
+ /// \param TemplateKWLoc The location of the 'template' keyword, if present.
+ ///
+ /// \param TL The TypeLoc that describes the type preceding the '::'.
+ ///
+ /// \param ColonColonLoc The location of the trailing '::'.
+ void Extend(ASTContext &Context, SourceLocation TemplateKWLoc, TypeLoc TL,
+ SourceLocation ColonColonLoc);
+
+ /// \brief Extend the current nested-name-specifier by another
+ /// nested-name-specifier component of the form 'identifier::'.
+ ///
+ /// \param Context The AST context in which this nested-name-specifier
+ /// resides.
+ ///
+ /// \param Identifier The identifier.
+ ///
+ /// \param IdentifierLoc The location of the identifier.
+ ///
+ /// \param ColonColonLoc The location of the trailing '::'.
+ void Extend(ASTContext &Context, IdentifierInfo *Identifier,
+ SourceLocation IdentifierLoc, SourceLocation ColonColonLoc);
+
+ /// \brief Extend the current nested-name-specifier by another
+ /// nested-name-specifier component of the form 'namespace::'.
+ ///
+ /// \param Context The AST context in which this nested-name-specifier
+ /// resides.
+ ///
+ /// \param Namespace The namespace.
+ ///
+ /// \param NamespaceLoc The location of the namespace name.
+ ///
+ /// \param ColonColonLoc The location of the trailing '::'.
+ void Extend(ASTContext &Context, NamespaceDecl *Namespace,
+ SourceLocation NamespaceLoc, SourceLocation ColonColonLoc);
+
+ /// \brief Extend the current nested-name-specifier by another
+ /// nested-name-specifier component of the form 'namespace-alias::'.
+ ///
+ /// \param Context The AST context in which this nested-name-specifier
+ /// resides.
+ ///
+ /// \param Alias The namespace alias.
+ ///
+ /// \param AliasLoc The location of the namespace alias
+ /// name.
+ ///
+ /// \param ColonColonLoc The location of the trailing '::'.
+ void Extend(ASTContext &Context, NamespaceAliasDecl *Alias,
+ SourceLocation AliasLoc, SourceLocation ColonColonLoc);
+
+ /// \brief Turn this (empty) nested-name-specifier into the global
+ /// nested-name-specifier '::'.
+ void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc);
+
+ /// \brief Make a new nested-name-specifier from incomplete source-location
+ /// information.
+ ///
+ /// FIXME: This routine should be used very, very rarely, in cases where we
+ /// need to synthesize a nested-name-specifier. Most code should instead use
+ /// \c Adopt() with a proper \c NestedNameSpecifierLoc.
+ void MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier,
+ SourceRange R);
+
+ /// \brief Adopt an existing nested-name-specifier (with source-range
+ /// information).
+ void Adopt(NestedNameSpecifierLoc Other);
+
+ /// \brief Retrieve a nested-name-specifier with location information, copied
+ /// into the given AST context.
+ ///
+ /// \param Context The context into which this nested-name-specifier will be
+ /// copied.
+ NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const;
/// No scope specifier.
bool isEmpty() const { return !Range.isValid(); }
@@ -75,6 +180,15 @@ public:
/// A scope specifier is present, and it refers to a real scope.
bool isValid() const { return isNotEmpty() && ScopeRep != 0; }
+ /// \brief Indicate that this nested-name-specifier is invalid.
+ void SetInvalid(SourceRange R) {
+ assert(R.isValid() && "Must have a valid source range");
+ if (Range.getBegin().isInvalid())
+ Range.setBegin(R.getBegin());
+ Range.setEnd(R.getEnd());
+ ScopeRep = 0;
+ }
+
/// Deprecated. Some call sites intend isNotEmpty() while others intend
/// isValid().
bool isSet() const { return ScopeRep != 0; }
@@ -83,6 +197,13 @@ public:
Range = SourceRange();
ScopeRep = 0;
}
+
+ /// \brief Retrieve the data associated with the source-location information.
+ char *location_data() const { return Buffer; }
+
+ /// \brief Retrieve the size of the data associated with source-location
+ /// information.
+ unsigned location_size() const { return BufferSize; }
};
/// DeclSpec - This class captures information about "declaration specifiers",
@@ -825,6 +946,16 @@ struct DeclaratorChunk {
struct PointerTypeInfo : TypeInfoCommon {
/// The type qualifiers: const/volatile/restrict.
unsigned TypeQuals : 3;
+
+ /// The location of the const-qualifier, if any.
+ unsigned ConstQualLoc;
+
+ /// The location of the volatile-qualifier, if any.
+ unsigned VolatileQualLoc;
+
+ /// The location of the restrict-qualifier, if any.
+ unsigned RestrictQualLoc;
+
void destroy() {
}
};
@@ -1055,12 +1186,18 @@ struct DeclaratorChunk {
/// getPointer - Return a DeclaratorChunk for a pointer.
///
static DeclaratorChunk getPointer(unsigned TypeQuals, SourceLocation Loc,
+ SourceLocation ConstQualLoc,
+ SourceLocation VolatileQualLoc,
+ SourceLocation RestrictQualLoc,
const ParsedAttributes &attrs) {
DeclaratorChunk I;
- I.Kind = Pointer;
- I.Loc = Loc;
- I.Ptr.TypeQuals = TypeQuals;
- I.Ptr.AttrList = attrs.getList();
+ I.Kind = Pointer;
+ I.Loc = Loc;
+ I.Ptr.TypeQuals = TypeQuals;
+ I.Ptr.ConstQualLoc = ConstQualLoc.getRawEncoding();
+ I.Ptr.VolatileQualLoc = VolatileQualLoc.getRawEncoding();
+ I.Ptr.RestrictQualLoc = RestrictQualLoc.getRawEncoding();
+ I.Ptr.AttrList = attrs.getList();
return I;
}
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h b/contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h
index 6d7bc63..e2b083e 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h
@@ -20,6 +20,8 @@ namespace clang {
struct ObjCMethodList;
class Sema;
+class Scope;
+class LookupResult;
/// \brief An abstract interface that should be implemented by
/// external AST sources that also provide information for semantic
@@ -47,6 +49,16 @@ public:
/// instance and factory methods, respectively, with this selector.
virtual std::pair<ObjCMethodList,ObjCMethodList> ReadMethodPool(Selector Sel);
+ /// \brief Do last resort, unqualified lookup on a LookupResult that
+ /// Sema cannot find.
+ ///
+ /// \param R a LookupResult that is being recovered.
+ ///
+ /// \param S the Scope of the identifier occurrence.
+ ///
+ /// \return true to tell Sema to recover using the LookupResult.
+ virtual bool LookupUnqualified(LookupResult &R, Scope *S) { return false; }
+
// isa/cast/dyn_cast support
static bool classof(const ExternalASTSource *Source) {
return Source->SemaSource;
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Initialization.h b/contrib/llvm/tools/clang/include/clang/Sema/Initialization.h
index c191565..bdf0d8e 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/Initialization.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Initialization.h
@@ -467,7 +467,10 @@ public:
CAssignment,
/// \brief String initialization
- StringInit
+ StringInit,
+
+ /// \brief Array initialization from another array (GNU C extension).
+ ArrayInit
};
/// \brief Describes the kind of a particular step in an initialization
@@ -513,7 +516,10 @@ public:
SK_StringInit,
/// \brief An initialization that "converts" an Objective-C object
/// (not a point to an object) to another Objective-C object type.
- SK_ObjCObjectConversion
+ SK_ObjCObjectConversion,
+ /// \brief Array initialization (from an array rvalue).
+ /// This is a GNU C extension.
+ SK_ArrayInit
};
/// \brief A single step in the initialization sequence.
@@ -563,6 +569,10 @@ public:
/// \brief Array must be initialized with an initializer list or a
/// string literal.
FK_ArrayNeedsInitListOrStringLiteral,
+ /// \brief Array type mismatch.
+ FK_ArrayTypeMismatch,
+ /// \brief Non-constant array initializer
+ FK_NonConstantArrayInit,
/// \brief Cannot resolve the address of an overloaded function.
FK_AddressOfOverloadFailed,
/// \brief Overloading due to reference initialization failed.
@@ -775,6 +785,9 @@ public:
/// always a no-op.
void AddObjCObjectConversionStep(QualType T);
+ /// \brief Add an array initialization step.
+ void AddArrayInitStep(QualType T);
+
/// \brief Note that this initialization sequence failed.
void SetFailed(FailureKind Failure) {
SequenceKind = FailedSequence;
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h b/contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h
index 5aa6f47..9e1a616 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h
@@ -177,6 +177,12 @@ namespace clang {
= (TemplateIdAnnotation *)std::malloc(sizeof(TemplateIdAnnotation) +
sizeof(ParsedTemplateArgument) * NumArgs);
TemplateId->NumArgs = NumArgs;
+
+ // Default-construct parsed template arguments.
+ ParsedTemplateArgument *TemplateArgs = TemplateId->getTemplateArgs();
+ for (unsigned I = 0; I != NumArgs; ++I)
+ new (TemplateArgs + I) ParsedTemplateArgument();
+
return TemplateId;
}
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h b/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h
index b0bb955..51297ae 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h
@@ -15,6 +15,7 @@
#define LLVM_CLANG_SEMA_SCOPE_INFO_H
#include "clang/AST/Type.h"
+#include "clang/Basic/PartialDiagnostic.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/SetVector.h"
@@ -30,6 +31,17 @@ class SwitchStmt;
namespace sema {
+class PossiblyUnreachableDiag {
+public:
+ PartialDiagnostic PD;
+ SourceLocation Loc;
+ const Stmt *stmt;
+
+ PossiblyUnreachableDiag(const PartialDiagnostic &PD, SourceLocation Loc,
+ const Stmt *stmt)
+ : PD(PD), Loc(Loc), stmt(stmt) {}
+};
+
/// \brief Retains information about a function, method, or block that is
/// currently being parsed.
class FunctionScopeInfo {
@@ -60,6 +72,11 @@ public:
/// block, if there is any chance of applying the named return value
/// optimization.
llvm::SmallVector<ReturnStmt*, 4> Returns;
+
+ /// \brief A list of PartialDiagnostics created but delayed within the
+ /// current function scope. These diagnostics are vetted for reachability
+ /// prior to being emitted.
+ llvm::SmallVector<PossiblyUnreachableDiag, 4> PossiblyUnreachableDiags;
void setHasBranchIntoScope() {
HasBranchIntoScope = true;
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Sema.h b/contrib/llvm/tools/clang/include/clang/Sema/Sema.h
index 91d6914..a937398 100644
--- a/contrib/llvm/tools/clang/include/clang/Sema/Sema.h
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Sema.h
@@ -267,6 +267,10 @@ public:
/// same list more than once.
llvm::OwningPtr<RecordDeclSetTy> PureVirtualClassDiagSet;
+ /// ParsingInitForAutoVars - a set of declarations with auto types for which
+ /// we are currently parsing the initializer.
+ llvm::SmallPtrSet<const Decl*, 4> ParsingInitForAutoVars;
+
/// \brief A mapping from external names to the most recent
/// locally-scoped external declaration with that name.
///
@@ -684,7 +688,8 @@ public:
void PushFunctionScope();
void PushBlockScope(Scope *BlockScope, BlockDecl *Block);
- void PopFunctionOrBlockScope();
+ void PopFunctionOrBlockScope(const sema::AnalysisBasedWarnings::Policy *WP =0,
+ const Decl *D = 0, const BlockExpr *blkExpr = 0);
sema::FunctionScopeInfo *getCurFunction() const {
return FunctionScopes.back();
@@ -856,9 +861,12 @@ public:
void ActOnUninitializedDecl(Decl *dcl, bool TypeMayContainAuto);
void ActOnInitializerError(Decl *Dcl);
void SetDeclDeleted(Decl *dcl, SourceLocation DelLoc);
+ void FinalizeDeclaration(Decl *D);
DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
Decl **Group,
unsigned NumDecls);
+ DeclGroupPtrTy BuildDeclaratorGroup(Decl **Group, unsigned NumDecls,
+ bool TypeMayContainAuto = true);
void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
SourceLocation LocAfterDecls);
Decl *ActOnStartOfFunctionDef(Scope *S, Declarator &D);
@@ -1518,7 +1526,8 @@ public:
void WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method,
bool &IncompleteImpl, unsigned DiagID);
void WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethod,
- ObjCMethodDecl *IntfMethod);
+ ObjCMethodDecl *MethodDecl,
+ bool IsProtocolMethodDecl);
bool isPropertyReadonly(ObjCPropertyDecl *PropertyDecl,
ObjCInterfaceDecl *IDecl);
@@ -1883,7 +1892,16 @@ public:
void MarkDeclarationReferenced(SourceLocation Loc, Decl *D);
void MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T);
void MarkDeclarationsReferencedInExpr(Expr *E);
- bool DiagRuntimeBehavior(SourceLocation Loc, const PartialDiagnostic &PD);
+
+ /// \brief Conditionally issue a diagnostic based on the current
+ /// evaluation context.
+ ///
+ /// \param stmt - If stmt is non-null, delay reporting the diagnostic until
+ /// the function body is parsed, and then do a basic reachability analysis to
+ /// determine if the statement is reachable. If it is unreachable, the
+ /// diagnostic will not be emitted.
+ bool DiagRuntimeBehavior(SourceLocation Loc, const Stmt *stmt,
+ const PartialDiagnostic &PD);
// Primary Expressions.
SourceRange getExprRange(Expr *E) const;
@@ -2573,11 +2591,19 @@ public:
CXXRecordDecl *getCurrentInstantiationOf(NestedNameSpecifier *NNS);
bool isUnknownSpecialization(const CXXScopeSpec &SS);
- /// ActOnCXXGlobalScopeSpecifier - Return the object that represents the
- /// global scope ('::').
- NestedNameSpecifier *
- ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc);
-
+ /// \brief The parser has parsed a global nested-name-specifier '::'.
+ ///
+ /// \param S The scope in which this nested-name-specifier occurs.
+ ///
+ /// \param CCLoc The location of the '::'.
+ ///
+ /// \param SS The nested-name-specifier, which will be updated in-place
+ /// to reflect the parsed nested-name-specifier.
+ ///
+ /// \returns true if an error occurred, false otherwise.
+ bool ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc,
+ CXXScopeSpec &SS);
+
bool isAcceptableNestedNameSpecifier(NamedDecl *SD);
NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS);
@@ -2586,43 +2612,97 @@ public:
IdentifierInfo &II,
ParsedType ObjectType);
- NestedNameSpecifier *BuildCXXNestedNameSpecifier(Scope *S,
- CXXScopeSpec &SS,
- SourceLocation IdLoc,
- SourceLocation CCLoc,
- IdentifierInfo &II,
- QualType ObjectType,
- NamedDecl *ScopeLookupResult,
- bool EnteringContext,
- bool ErrorRecoveryLookup);
-
- NestedNameSpecifier *ActOnCXXNestedNameSpecifier(Scope *S,
- CXXScopeSpec &SS,
- SourceLocation IdLoc,
- SourceLocation CCLoc,
- IdentifierInfo &II,
- ParsedType ObjectType,
- bool EnteringContext);
+ bool BuildCXXNestedNameSpecifier(Scope *S,
+ IdentifierInfo &Identifier,
+ SourceLocation IdentifierLoc,
+ SourceLocation CCLoc,
+ QualType ObjectType,
+ bool EnteringContext,
+ CXXScopeSpec &SS,
+ NamedDecl *ScopeLookupResult,
+ bool ErrorRecoveryLookup);
+
+ /// \brief The parser has parsed a nested-name-specifier 'identifier::'.
+ ///
+ /// \param S The scope in which this nested-name-specifier occurs.
+ ///
+ /// \param Identifier The identifier preceding the '::'.
+ ///
+ /// \param IdentifierLoc The location of the identifier.
+ ///
+ /// \param CCLoc The location of the '::'.
+ ///
+ /// \param ObjectType The type of the object, if we're parsing
+ /// nested-name-specifier in a member access expression.
+ ///
+ /// \param EnteringContext Whether we're entering the context nominated by
+ /// this nested-name-specifier.
+ ///
+ /// \param SS The nested-name-specifier, which is both an input
+ /// parameter (the nested-name-specifier before this type) and an
+ /// output parameter (containing the full nested-name-specifier,
+ /// including this new type).
+ ///
+ /// \returns true if an error occurred, false otherwise.
+ bool ActOnCXXNestedNameSpecifier(Scope *S,
+ IdentifierInfo &Identifier,
+ SourceLocation IdentifierLoc,
+ SourceLocation CCLoc,
+ ParsedType ObjectType,
+ bool EnteringContext,
+ CXXScopeSpec &SS);
bool IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS,
- IdentifierInfo &II,
+ IdentifierInfo &Identifier,
+ SourceLocation IdentifierLoc,
+ SourceLocation ColonLoc,
ParsedType ObjectType,
bool EnteringContext);
- /// ActOnCXXNestedNameSpecifier - Called during parsing of a
- /// nested-name-specifier that involves a template-id, e.g.,
- /// "foo::bar<int, float>::", and now we need to build a scope
- /// specifier. \p SS is empty or the previously parsed nested-name
- /// part ("foo::"), \p Type is the already-parsed class template
- /// specialization (or other template-id that names a type), \p
- /// TypeRange is the source range where the type is located, and \p
- /// CCLoc is the location of the trailing '::'.
- CXXScopeTy *ActOnCXXNestedNameSpecifier(Scope *S,
- const CXXScopeSpec &SS,
- ParsedType Type,
- SourceRange TypeRange,
- SourceLocation CCLoc);
-
+ /// \brief The parser has parsed a nested-name-specifier 'type::'.
+ ///
+ /// \param S The scope in which this nested-name-specifier occurs.
+ ///
+ /// \param Type The type, which will be a template specialization
+ /// type, preceding the '::'.
+ ///
+ /// \param CCLoc The location of the '::'.
+ ///
+ /// \param SS The nested-name-specifier, which is both an input
+ /// parameter (the nested-name-specifier before this type) and an
+ /// output parameter (containing the full nested-name-specifier,
+ /// including this new type).
+ ///
+ /// \returns true if an error occurred, false otherwise.
+ bool ActOnCXXNestedNameSpecifier(Scope *S,
+ ParsedType Type,
+ SourceLocation CCLoc,
+ CXXScopeSpec &SS);
+
+ /// \brief Given a C++ nested-name-specifier, produce an annotation value
+ /// that the parser can use later to reconstruct the given
+ /// nested-name-specifier.
+ ///
+ /// \param SS A nested-name-specifier.
+ ///
+ /// \returns A pointer containing all of the information in the
+ /// nested-name-specifier \p SS.
+ void *SaveNestedNameSpecifierAnnotation(CXXScopeSpec &SS);
+
+ /// \brief Given an annotation pointer for a nested-name-specifier, restore
+ /// the nested-name-specifier structure.
+ ///
+ /// \param Annotation The annotation pointer, produced by
+ /// \c SaveNestedNameSpecifierAnnotation().
+ ///
+ /// \param AnnotationRange The source range corresponding to the annotation.
+ ///
+ /// \param SS The nested-name-specifier that will be updated with the contents
+ /// of the annotation pointer.
+ void RestoreNestedNameSpecifierAnnotation(void *Annotation,
+ SourceRange AnnotationRange,
+ CXXScopeSpec &SS);
+
bool ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS);
/// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global
@@ -4213,6 +4293,11 @@ public:
SubstNestedNameSpecifier(NestedNameSpecifier *NNS,
SourceRange Range,
const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ NestedNameSpecifierLoc
+ SubstNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
DeclarationNameInfo
SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo,
const MultiLevelTemplateArgumentList &TemplateArgs);
@@ -4772,7 +4857,8 @@ public:
QualType CheckSubtractionOperands( // C99 6.5.6
Expr *&lex, Expr *&rex, SourceLocation OpLoc, QualType* CompLHSTy = 0);
QualType CheckShiftOperands( // C99 6.5.7
- Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false);
+ Expr *&lex, Expr *&rex, SourceLocation OpLoc, unsigned Opc,
+ bool isCompAssign = false);
QualType CheckCompareOperands( // C99 6.5.8/9
Expr *&lex, Expr *&rex, SourceLocation OpLoc, unsigned Opc,
bool isRelational);
diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h b/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h
index 9799b8d..424e78c 100644
--- a/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h
@@ -116,7 +116,8 @@ public:
/// \returns true to indicate the predefines are invalid or false otherwise.
virtual bool ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers,
llvm::StringRef OriginalFileName,
- std::string &SuggestedPredefines) {
+ std::string &SuggestedPredefines,
+ FileManager &FileMgr) {
return false;
}
@@ -143,7 +144,8 @@ public:
virtual bool ReadTargetTriple(llvm::StringRef Triple);
virtual bool ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers,
llvm::StringRef OriginalFileName,
- std::string &SuggestedPredefines);
+ std::string &SuggestedPredefines,
+ FileManager &FileMgr);
virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI, unsigned ID);
virtual void ReadCounter(unsigned Value);
@@ -1131,6 +1133,10 @@ public:
NestedNameSpecifier *ReadNestedNameSpecifier(const RecordData &Record,
unsigned &Idx);
+ NestedNameSpecifierLoc ReadNestedNameSpecifierLoc(PerFileData &F,
+ const RecordData &Record,
+ unsigned &Idx);
+
/// \brief Read a template name.
TemplateName ReadTemplateName(PerFileData &F, const RecordData &Record,
unsigned &Idx);
diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h b/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h
index beb4936..04ad93f 100644
--- a/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h
@@ -443,6 +443,9 @@ public:
/// \brief Emits a reference to a declarator info.
void AddTypeSourceInfo(TypeSourceInfo *TInfo, RecordDataImpl &Record);
+ /// \brief Emits a type with source-location information.
+ void AddTypeLoc(TypeLoc TL, RecordDataImpl &Record);
+
/// \brief Emits a template argument location info.
void AddTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
const TemplateArgumentLocInfo &Arg,
@@ -474,6 +477,10 @@ public:
/// \brief Emit a nested name specifier.
void AddNestedNameSpecifier(NestedNameSpecifier *NNS, RecordDataImpl &Record);
+
+ /// \brief Emit a nested name specifier with source-location information.
+ void AddNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
+ RecordDataImpl &Record);
/// \brief Emit a template name.
void AddTemplateName(TemplateName Name, RecordDataImpl &Record);
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h
index 42feb78..afba12d 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h
@@ -40,7 +40,6 @@ TransferFuncs* MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled,
const LangOptions& lopts);
void RegisterExperimentalChecks(ExprEngine &Eng);
-void RegisterExperimentalInternalChecks(ExprEngine &Eng);
void RegisterCallInliner(ExprEngine &Eng);
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
index 1786fe6..93d7958 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
@@ -72,6 +72,7 @@ protected:
friend class BugReportEquivClass;
virtual void Profile(llvm::FoldingSetNodeID& hash) const {
+ hash.AddPointer(&BT);
hash.AddInteger(getLocation().getRawEncoding());
hash.AddString(Description);
}
@@ -277,6 +278,8 @@ private:
void FlushReport(BugReportEquivClass& EQ);
+ llvm::FoldingSet<BugReportEquivClass> EQClasses;
+
protected:
BugReporter(BugReporterData& d, Kind k) : BugTypes(F.getEmptySet()), kind(k),
D(d) {}
@@ -302,6 +305,10 @@ public:
iterator begin() { return BugTypes.begin(); }
iterator end() { return BugTypes.end(); }
+ typedef llvm::FoldingSet<BugReportEquivClass>::iterator EQClasses_iterator;
+ EQClasses_iterator EQClasses_begin() { return EQClasses.begin(); }
+ EQClasses_iterator EQClasses_end() { return EQClasses.end(); }
+
ASTContext& getContext() { return D.getASTContext(); }
SourceManager& getSourceManager() { return D.getSourceManager(); }
@@ -344,6 +351,13 @@ public:
}
static bool classof(const BugReporter* R) { return true; }
+
+private:
+ llvm::StringMap<BugType *> StrBugTypes;
+
+ /// \brief Returns a BugType that is associated with the given name and
+ /// category.
+ BugType *getBugTypeForName(llvm::StringRef name, llvm::StringRef category);
};
// FIXME: Get rid of GRBugReporter. It's the wrong abstraction.
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
index 2793284..7b9bb03 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
@@ -29,8 +29,6 @@ class BugType {
private:
const std::string Name;
const std::string Category;
- llvm::FoldingSet<BugReportEquivClass> EQClasses;
- friend class BugReporter;
bool SuppressonSink;
public:
BugType(llvm::StringRef name, llvm::StringRef cat)
@@ -48,14 +46,6 @@ public:
void setSuppressOnSink(bool x) { SuppressonSink = x; }
virtual void FlushReports(BugReporter& BR);
-
- typedef llvm::FoldingSet<BugReportEquivClass>::iterator iterator;
- iterator begin() { return EQClasses.begin(); }
- iterator end() { return EQClasses.end(); }
-
- typedef llvm::FoldingSet<BugReportEquivClass>::const_iterator const_iterator;
- const_iterator begin() const { return EQClasses.begin(); }
- const_iterator end() const { return EQClasses.end(); }
};
class BuiltinBug : public BugType {
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
index 65c8b80..2768195 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
@@ -14,23 +14,92 @@
#ifndef LLVM_CLANG_SA_CORE_CHECKERMANAGER_H
#define LLVM_CLANG_SA_CORE_CHECKERMANAGER_H
+#include "clang/Basic/LangOptions.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/FoldingSet.h"
#include <vector>
namespace clang {
class Decl;
+ class Stmt;
+ class CallExpr;
namespace ento {
class ExprEngine;
class AnalysisManager;
class BugReporter;
+ class CheckerContext;
+ class ObjCMessage;
+ class SVal;
+ class ExplodedNode;
+ class ExplodedNodeSet;
+ class ExplodedGraph;
+ class GRState;
+ class EndOfFunctionNodeBuilder;
+ class MemRegion;
+ class SymbolReaper;
+
+class GraphExpander {
+public:
+ virtual ~GraphExpander();
+ virtual void expandGraph(ExplodedNodeSet &Dst, ExplodedNode *Pred) = 0;
+};
+
+struct VoidCheckerFnParm {};
+template <typename P1=VoidCheckerFnParm, typename P2=VoidCheckerFnParm,
+ typename P3=VoidCheckerFnParm, typename P4=VoidCheckerFnParm>
+class CheckerFn {
+ typedef void (*Func)(void *, P1, P2, P3, P4);
+ Func Fn;
+public:
+ void *Checker;
+ CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { }
+ void operator()(P1 p1, P2 p2, P3 p3, P4 p4) { Fn(Checker, p1, p2, p3, p4); }
+};
+
+template <typename P1, typename P2, typename P3>
+class CheckerFn<P1, P2, P3, VoidCheckerFnParm> {
+ typedef void (*Func)(void *, P1, P2, P3);
+ Func Fn;
+public:
+ void *Checker;
+ CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { }
+ void operator()(P1 p1, P2 p2, P3 p3) { Fn(Checker, p1, p2, p3); }
+};
+
+template <typename P1, typename P2>
+class CheckerFn<P1, P2, VoidCheckerFnParm, VoidCheckerFnParm> {
+ typedef void (*Func)(void *, P1, P2);
+ Func Fn;
+public:
+ void *Checker;
+ CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { }
+ void operator()(P1 p1, P2 p2) { Fn(Checker, p1, p2); }
+};
+
+template <>
+class CheckerFn<VoidCheckerFnParm, VoidCheckerFnParm, VoidCheckerFnParm,
+ VoidCheckerFnParm> {
+ typedef void (*Func)(void *);
+ Func Fn;
+public:
+ void *Checker;
+ CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { }
+ void operator()() { Fn(Checker); }
+};
class CheckerManager {
+ const LangOptions LangOpts;
+
public:
+ CheckerManager(const LangOptions &langOpts) : LangOpts(langOpts) { }
~CheckerManager();
+ const LangOptions &getLangOptions() const { return LangOpts; }
+
typedef void *CheckerRef;
+ typedef CheckerFn<> CheckerDtor;
//===----------------------------------------------------------------------===//
// registerChecker
@@ -40,17 +109,12 @@ public:
template <typename CHECKER>
void registerChecker() {
CHECKER *checker = new CHECKER();
- Checkers.push_back(std::pair<CheckerRef, Dtor>(checker, destruct<CHECKER>));
+ CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>));
CHECKER::_register(checker, *this);
}
- typedef void (*RegisterToEngFunc)(ExprEngine &Eng);
- void addCheckerRegisterFunction(RegisterToEngFunc fn) {
- Funcs.push_back(fn);
- }
-
//===----------------------------------------------------------------------===//
-// Functions for running checkers.
+// Functions for running checkers for AST traversing..
//===----------------------------------------------------------------------===//
/// \brief Run checkers handling Decls.
@@ -62,48 +126,290 @@ public:
BugReporter &BR);
//===----------------------------------------------------------------------===//
-// Internal registration functions.
+// Functions for running checkers for path-sensitive checking.
+//===----------------------------------------------------------------------===//
+
+ /// \brief Run checkers for pre-visiting Stmts.
+ void runCheckersForPreStmt(ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ const Stmt *S,
+ ExprEngine &Eng) {
+ runCheckersForStmt(/*isPreVisit=*/true, Dst, Src, S, Eng);
+ }
+
+ /// \brief Run checkers for post-visiting Stmts.
+ void runCheckersForPostStmt(ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ const Stmt *S,
+ ExprEngine &Eng) {
+ runCheckersForStmt(/*isPreVisit=*/false, Dst, Src, S, Eng);
+ }
+
+ /// \brief Run checkers for visiting Stmts.
+ void runCheckersForStmt(bool isPreVisit,
+ ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
+ const Stmt *S, ExprEngine &Eng);
+
+ /// \brief Run checkers for pre-visiting obj-c messages.
+ void runCheckersForPreObjCMessage(ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ const ObjCMessage &msg,
+ ExprEngine &Eng) {
+ runCheckersForObjCMessage(/*isPreVisit=*/true, Dst, Src, msg, Eng);
+ }
+
+ /// \brief Run checkers for post-visiting obj-c messages.
+ void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ const ObjCMessage &msg,
+ ExprEngine &Eng) {
+ runCheckersForObjCMessage(/*isPreVisit=*/false, Dst, Src, msg, Eng);
+ }
+
+ /// \brief Run checkers for visiting obj-c messages.
+ void runCheckersForObjCMessage(bool isPreVisit,
+ ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ const ObjCMessage &msg, ExprEngine &Eng);
+
+ /// \brief Run checkers for load/store of a location.
+ void runCheckersForLocation(ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ SVal location, bool isLoad,
+ const Stmt *S,
+ ExprEngine &Eng);
+
+ /// \brief Run checkers for end of analysis.
+ void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR,
+ ExprEngine &Eng);
+
+ /// \brief Run checkers for end of path.
+ void runCheckersForEndPath(EndOfFunctionNodeBuilder &B, ExprEngine &Eng);
+
+ /// \brief Run checkers for live symbols.
+ void runCheckersForLiveSymbols(const GRState *state,
+ SymbolReaper &SymReaper);
+
+ /// \brief Run checkers for dead symbols.
+ void runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ SymbolReaper &SymReaper, const Stmt *S,
+ ExprEngine &Eng);
+
+ /// \brief True if at least one checker wants to check region changes.
+ bool wantsRegionChangeUpdate(const GRState *state);
+
+ /// \brief Run checkers for region changes.
+ const GRState *runCheckersForRegionChanges(const GRState *state,
+ const MemRegion * const *Begin,
+ const MemRegion * const *End);
+
+ /// \brief Run checkers for evaluating a call.
+ void runCheckersForEvalCall(ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ const CallExpr *CE, ExprEngine &Eng,
+ GraphExpander *defaultEval = 0);
+
+//===----------------------------------------------------------------------===//
+// Internal registration functions for AST traversing.
//===----------------------------------------------------------------------===//
// Functions used by the registration mechanism, checkers should not touch
// these directly.
- typedef void (*CheckDeclFunc)(CheckerRef checker, const Decl *D,
- AnalysisManager& mgr, BugReporter &BR);
+ typedef CheckerFn<const Decl *, AnalysisManager&, BugReporter &>
+ CheckDeclFunc;
+ typedef CheckerFn<const Stmt *, CheckerContext &> CheckStmtFunc;
+
typedef bool (*HandlesDeclFunc)(const Decl *D);
- void _registerForDecl(CheckerRef checker, CheckDeclFunc checkfn,
- HandlesDeclFunc isForDeclFn);
+ void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn);
- void _registerForBody(CheckerRef checker, CheckDeclFunc checkfn);
-
- void registerCheckersToEngine(ExprEngine &eng);
+ void _registerForBody(CheckDeclFunc checkfn);
+
+//===----------------------------------------------------------------------===//
+// Internal registration functions for path-sensitive checking.
+//===----------------------------------------------------------------------===//
+
+ typedef CheckerFn<const ObjCMessage &, CheckerContext &> CheckObjCMessageFunc;
+ typedef CheckerFn<const SVal &/*location*/, bool/*isLoad*/, CheckerContext &>
+ CheckLocationFunc;
+ typedef CheckerFn<ExplodedGraph &, BugReporter &, ExprEngine &>
+ CheckEndAnalysisFunc;
+ typedef CheckerFn<EndOfFunctionNodeBuilder &, ExprEngine &> CheckEndPathFunc;
+ typedef CheckerFn<SymbolReaper &, CheckerContext &> CheckDeadSymbolsFunc;
+ typedef CheckerFn<const GRState *, SymbolReaper &> CheckLiveSymbolsFunc;
+
+ typedef bool (*HandlesStmtFunc)(const Stmt *D);
+ void _registerForPreStmt(CheckStmtFunc checkfn,
+ HandlesStmtFunc isForStmtFn);
+ void _registerForPostStmt(CheckStmtFunc checkfn,
+ HandlesStmtFunc isForStmtFn);
+
+ void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn);
+ void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn);
+
+ void _registerForLocation(CheckLocationFunc checkfn);
+
+ void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn);
+
+ void _registerForEndPath(CheckEndPathFunc checkfn);
+
+ void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn);
+
+ void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn);
+
+ class CheckRegionChangesFunc {
+ typedef const GRState * (*Func)(void *, const GRState *,
+ const MemRegion * const *,
+ const MemRegion * const *);
+ Func Fn;
+ public:
+ void *Checker;
+ CheckRegionChangesFunc(void *checker, Func fn) : Fn(fn), Checker(checker) {}
+ const GRState *operator()(const GRState *state,
+ const MemRegion * const *begin,
+ const MemRegion * const *end) {
+ return Fn(Checker, state, begin, end);
+ }
+ };
+
+ class WantsRegionChangeUpdateFunc {
+ typedef bool (*Func)(void *, const GRState *);
+ Func Fn;
+ public:
+ void *Checker;
+ WantsRegionChangeUpdateFunc(void *checker, Func fn)
+ : Fn(fn), Checker(checker) { }
+ bool operator()(const GRState *state) {
+ return Fn(Checker, state);
+ }
+ };
+
+ void _registerForRegionChanges(CheckRegionChangesFunc checkfn,
+ WantsRegionChangeUpdateFunc wantUpdateFn);
+
+ class EvalCallFunc {
+ typedef bool (*Func)(void *, const CallExpr *, CheckerContext &);
+ Func Fn;
+ public:
+ void *Checker;
+ EvalCallFunc(void *checker, Func fn) : Fn(fn), Checker(checker) { }
+ bool operator()(const CallExpr *CE, CheckerContext &C) {
+ return Fn(Checker, CE, C);
+ }
+ };
+
+ void _registerForEvalCall(EvalCallFunc checkfn);
+
+//===----------------------------------------------------------------------===//
+// Implementation details.
+//===----------------------------------------------------------------------===//
private:
template <typename CHECKER>
static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); }
- std::vector<RegisterToEngFunc> Funcs;
+ std::vector<CheckerDtor> CheckerDtors;
struct DeclCheckerInfo {
- CheckerRef Checker;
CheckDeclFunc CheckFn;
HandlesDeclFunc IsForDeclFn;
};
std::vector<DeclCheckerInfo> DeclCheckers;
- std::vector<std::pair<CheckerRef, CheckDeclFunc> > BodyCheckers;
-
- typedef void (*Dtor)(void *);
- std::vector<std::pair<CheckerRef, Dtor> > Checkers;
+ std::vector<CheckDeclFunc> BodyCheckers;
- typedef llvm::SmallVector<std::pair<CheckerRef, CheckDeclFunc>, 4>
- CachedDeclCheckers;
+ typedef llvm::SmallVector<CheckDeclFunc, 4> CachedDeclCheckers;
typedef llvm::DenseMap<unsigned, CachedDeclCheckers> CachedDeclCheckersMapTy;
CachedDeclCheckersMapTy CachedDeclCheckersMap;
+
+ struct StmtCheckerInfo {
+ CheckStmtFunc CheckFn;
+ HandlesStmtFunc IsForStmtFn;
+ bool IsPreVisit;
+ };
+ std::vector<StmtCheckerInfo> StmtCheckers;
+
+ struct CachedStmtCheckersKey {
+ unsigned StmtKind;
+ bool IsPreVisit;
+
+ CachedStmtCheckersKey() : StmtKind(0), IsPreVisit(0) { }
+ CachedStmtCheckersKey(unsigned stmtKind, bool isPreVisit)
+ : StmtKind(stmtKind), IsPreVisit(isPreVisit) { }
+
+ static CachedStmtCheckersKey getSentinel() {
+ return CachedStmtCheckersKey(~0U, 0);
+ }
+ unsigned getHashValue() const {
+ llvm::FoldingSetNodeID ID;
+ ID.AddInteger(StmtKind);
+ ID.AddBoolean(IsPreVisit);
+ return ID.ComputeHash();
+ }
+ bool operator==(const CachedStmtCheckersKey &RHS) const {
+ return StmtKind == RHS.StmtKind && IsPreVisit == RHS.IsPreVisit;
+ }
+ };
+ friend struct llvm::DenseMapInfo<CachedStmtCheckersKey>;
+
+ typedef llvm::SmallVector<CheckStmtFunc, 4> CachedStmtCheckers;
+ typedef llvm::DenseMap<CachedStmtCheckersKey, CachedStmtCheckers>
+ CachedStmtCheckersMapTy;
+ CachedStmtCheckersMapTy CachedStmtCheckersMap;
+
+ CachedStmtCheckers *getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit);
+
+ std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers;
+ std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers;
+
+ std::vector<CheckLocationFunc> LocationCheckers;
+
+ std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers;
+
+ std::vector<CheckEndPathFunc> EndPathCheckers;
+
+ std::vector<CheckLiveSymbolsFunc> LiveSymbolsCheckers;
+
+ std::vector<CheckDeadSymbolsFunc> DeadSymbolsCheckers;
+
+ struct RegionChangesCheckerInfo {
+ CheckRegionChangesFunc CheckFn;
+ WantsRegionChangeUpdateFunc WantUpdateFn;
+ };
+ std::vector<RegionChangesCheckerInfo> RegionChangesCheckers;
+
+ std::vector<EvalCallFunc> EvalCallCheckers;
};
} // end ento namespace
} // end clang namespace
+namespace llvm {
+ /// Define DenseMapInfo so that CachedStmtCheckersKey can be used as key
+ /// in DenseMap and DenseSets.
+ template <>
+ struct DenseMapInfo<clang::ento::CheckerManager::CachedStmtCheckersKey> {
+ static inline clang::ento::CheckerManager::CachedStmtCheckersKey
+ getEmptyKey() {
+ return clang::ento::CheckerManager::CachedStmtCheckersKey();
+ }
+ static inline clang::ento::CheckerManager::CachedStmtCheckersKey
+ getTombstoneKey() {
+ return clang::ento::CheckerManager::CachedStmtCheckersKey::getSentinel();
+ }
+
+ static unsigned
+ getHashValue(clang::ento::CheckerManager::CachedStmtCheckersKey S) {
+ return S.getHashValue();
+ }
+
+ static bool isEqual(clang::ento::CheckerManager::CachedStmtCheckersKey LHS,
+ clang::ento::CheckerManager::CachedStmtCheckersKey RHS) {
+ return LHS == RHS;
+ }
+ };
+} // end namespace llvm
+
#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerProvider.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerProvider.h
index 414ad92..40b838e 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerProvider.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerProvider.h
@@ -17,6 +17,10 @@
#include "llvm/ADT/StringRef.h"
#include <vector>
+namespace llvm {
+ class raw_ostream;
+}
+
namespace clang {
namespace ento {
@@ -45,6 +49,7 @@ public:
virtual ~CheckerProvider();
virtual void registerCheckers(CheckerManager &checkerMgr,
CheckerOptInfo *checkOpts, unsigned numCheckOpts) = 0;
+ virtual void printHelp(llvm::raw_ostream &OS) = 0;
};
} // end ento namespace
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerV2.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerV2.h
index 8c96866..e080d19 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerV2.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerV2.h
@@ -41,7 +41,9 @@ class ASTDecl {
public:
template <typename CHECKER>
static void _register(CHECKER *checker, CheckerManager &mgr) {
- mgr._registerForDecl(checker, _checkDecl<CHECKER>, _handlesDecl);
+ mgr._registerForDecl(CheckerManager::CheckDeclFunc(checker,
+ _checkDecl<CHECKER>),
+ _handlesDecl);
}
};
@@ -55,12 +57,197 @@ class ASTCodeBody {
public:
template <typename CHECKER>
static void _register(CHECKER *checker, CheckerManager &mgr) {
- mgr._registerForBody(checker, _checkBody<CHECKER>);
+ mgr._registerForBody(CheckerManager::CheckDeclFunc(checker,
+ _checkBody<CHECKER>));
+ }
+};
+
+template <typename STMT>
+class PreStmt {
+ template <typename CHECKER>
+ static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
+ ((const CHECKER *)checker)->checkPreStmt(llvm::cast<STMT>(S), C);
+ }
+
+ static bool _handlesStmt(const Stmt *S) {
+ return llvm::isa<STMT>(S);
+ }
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForPreStmt(CheckerManager::CheckStmtFunc(checker,
+ _checkStmt<CHECKER>),
+ _handlesStmt);
+ }
+};
+
+template <typename STMT>
+class PostStmt {
+ template <typename CHECKER>
+ static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
+ ((const CHECKER *)checker)->checkPostStmt(llvm::cast<STMT>(S), C);
+ }
+
+ static bool _handlesStmt(const Stmt *S) {
+ return llvm::isa<STMT>(S);
+ }
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForPostStmt(CheckerManager::CheckStmtFunc(checker,
+ _checkStmt<CHECKER>),
+ _handlesStmt);
+ }
+};
+
+class PreObjCMessage {
+ template <typename CHECKER>
+ static void _checkObjCMessage(void *checker, const ObjCMessage &msg,
+ CheckerContext &C) {
+ ((const CHECKER *)checker)->checkPreObjCMessage(msg, C);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForPreObjCMessage(
+ CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
+ }
+};
+
+class PostObjCMessage {
+ template <typename CHECKER>
+ static void _checkObjCMessage(void *checker, const ObjCMessage &msg,
+ CheckerContext &C) {
+ ((const CHECKER *)checker)->checkPostObjCMessage(msg, C);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForPostObjCMessage(
+ CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
+ }
+};
+
+class Location {
+ template <typename CHECKER>
+ static void _checkLocation(void *checker, const SVal &location, bool isLoad,
+ CheckerContext &C) {
+ ((const CHECKER *)checker)->checkLocation(location, isLoad, C);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForLocation(
+ CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>));
+ }
+};
+
+class EndAnalysis {
+ template <typename CHECKER>
+ static void _checkEndAnalysis(void *checker, ExplodedGraph &G,
+ BugReporter &BR, ExprEngine &Eng) {
+ ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForEndAnalysis(
+ CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>));
+ }
+};
+
+class EndPath {
+ template <typename CHECKER>
+ static void _checkEndPath(void *checker, EndOfFunctionNodeBuilder &B,
+ ExprEngine &Eng) {
+ ((const CHECKER *)checker)->checkEndPath(B, Eng);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForEndPath(
+ CheckerManager::CheckEndPathFunc(checker, _checkEndPath<CHECKER>));
+ }
+};
+
+class LiveSymbols {
+ template <typename CHECKER>
+ static void _checkLiveSymbols(void *checker, const GRState *state,
+ SymbolReaper &SR) {
+ ((const CHECKER *)checker)->checkLiveSymbols(state, SR);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForLiveSymbols(
+ CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>));
+ }
+};
+
+class DeadSymbols {
+ template <typename CHECKER>
+ static void _checkDeadSymbols(void *checker,
+ SymbolReaper &SR, CheckerContext &C) {
+ ((const CHECKER *)checker)->checkDeadSymbols(SR, C);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForDeadSymbols(
+ CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>));
+ }
+};
+
+class RegionChanges {
+ template <typename CHECKER>
+ static const GRState *_checkRegionChanges(void *checker, const GRState *state,
+ const MemRegion * const *Begin,
+ const MemRegion * const *End) {
+ return ((const CHECKER *)checker)->checkRegionChanges(state, Begin, End);
+ }
+ template <typename CHECKER>
+ static bool _wantsRegionChangeUpdate(void *checker, const GRState *state) {
+ return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForRegionChanges(
+ CheckerManager::CheckRegionChangesFunc(checker,
+ _checkRegionChanges<CHECKER>),
+ CheckerManager::WantsRegionChangeUpdateFunc(checker,
+ _wantsRegionChangeUpdate<CHECKER>));
}
};
} // end check namespace
+namespace eval {
+
+class Call {
+ template <typename CHECKER>
+ static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) {
+ return ((const CHECKER *)checker)->evalCall(CE, C);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForEvalCall(
+ CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>));
+ }
+};
+
+} // end eval namespace
+
template <typename CHECK1, typename CHECK2=check::_VoidCheck,
typename CHECK3=check::_VoidCheck, typename CHECK4=check::_VoidCheck,
typename CHECK5=check::_VoidCheck, typename CHECK6=check::_VoidCheck,
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Checker.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Checker.h
index 22c2027..627bc0a 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Checker.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Checker.h
@@ -15,8 +15,7 @@
#ifndef LLVM_CLANG_GR_CHECKER
#define LLVM_CLANG_GR_CHECKER
-#include "clang/Analysis/Support/SaveAndRestore.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
//===----------------------------------------------------------------------===//
// Checker interface.
@@ -26,163 +25,6 @@ namespace clang {
namespace ento {
-class CheckerContext {
- ExplodedNodeSet &Dst;
- StmtNodeBuilder &B;
- ExprEngine &Eng;
- ExplodedNode *Pred;
- SaveAndRestore<bool> OldSink;
- const void *checkerTag;
- SaveAndRestore<ProgramPoint::Kind> OldPointKind;
- SaveOr OldHasGen;
- const GRState *ST;
- const Stmt *statement;
- const unsigned size;
-public:
- bool *respondsToCallback;
-public:
- CheckerContext(ExplodedNodeSet &dst, StmtNodeBuilder &builder,
- ExprEngine &eng, ExplodedNode *pred,
- const void *tag, ProgramPoint::Kind K,
- bool *respondsToCB = 0,
- const Stmt *stmt = 0, const GRState *st = 0)
- : Dst(dst), B(builder), Eng(eng), Pred(pred),
- OldSink(B.BuildSinks),
- checkerTag(tag),
- OldPointKind(B.PointKind, K),
- OldHasGen(B.hasGeneratedNode),
- ST(st), statement(stmt), size(Dst.size()),
- respondsToCallback(respondsToCB) {}
-
- ~CheckerContext();
-
- ExprEngine &getEngine() {
- return Eng;
- }
-
- AnalysisManager &getAnalysisManager() {
- return Eng.getAnalysisManager();
- }
-
- ConstraintManager &getConstraintManager() {
- return Eng.getConstraintManager();
- }
-
- StoreManager &getStoreManager() {
- return Eng.getStoreManager();
- }
-
- ExplodedNodeSet &getNodeSet() { return Dst; }
- StmtNodeBuilder &getNodeBuilder() { return B; }
- ExplodedNode *&getPredecessor() { return Pred; }
- const GRState *getState() { return ST ? ST : B.GetState(Pred); }
-
- ASTContext &getASTContext() {
- return Eng.getContext();
- }
-
- BugReporter &getBugReporter() {
- return Eng.getBugReporter();
- }
-
- SourceManager &getSourceManager() {
- return getBugReporter().getSourceManager();
- }
-
- SValBuilder &getSValBuilder() {
- return Eng.getSValBuilder();
- }
-
- ExplodedNode *generateNode(bool autoTransition = true) {
- assert(statement && "Only transitions with statements currently supported");
- ExplodedNode *N = generateNodeImpl(statement, getState(), false,
- checkerTag);
- if (N && autoTransition)
- Dst.Add(N);
- return N;
- }
-
- ExplodedNode *generateNode(const Stmt *stmt, const GRState *state,
- bool autoTransition = true, const void *tag = 0) {
- assert(state);
- ExplodedNode *N = generateNodeImpl(stmt, state, false,
- tag ? tag : checkerTag);
- if (N && autoTransition)
- addTransition(N);
- return N;
- }
-
- ExplodedNode *generateNode(const GRState *state, ExplodedNode *pred,
- bool autoTransition = true) {
- assert(statement && "Only transitions with statements currently supported");
- ExplodedNode *N = generateNodeImpl(statement, state, pred, false);
- if (N && autoTransition)
- addTransition(N);
- return N;
- }
-
- ExplodedNode *generateNode(const GRState *state, bool autoTransition = true,
- const void *tag = 0) {
- assert(statement && "Only transitions with statements currently supported");
- ExplodedNode *N = generateNodeImpl(statement, state, false,
- tag ? tag : checkerTag);
- if (N && autoTransition)
- addTransition(N);
- return N;
- }
-
- ExplodedNode *generateSink(const Stmt *stmt, const GRState *state = 0) {
- return generateNodeImpl(stmt, state ? state : getState(), true,
- checkerTag);
- }
-
- ExplodedNode *generateSink(const GRState *state = 0) {
- assert(statement && "Only transitions with statements currently supported");
- return generateNodeImpl(statement, state ? state : getState(), true,
- checkerTag);
- }
-
- void addTransition(ExplodedNode *node) {
- Dst.Add(node);
- }
-
- void addTransition(const GRState *state, const void *tag = 0) {
- assert(state);
- // If the 'state' is not new, we need to check if the cached state 'ST'
- // is new.
- if (state != getState() || (ST && ST != B.GetState(Pred)))
- // state is new or equals to ST.
- generateNode(state, true, tag);
- else
- Dst.Add(Pred);
- }
-
- void EmitReport(BugReport *R) {
- Eng.getBugReporter().EmitReport(R);
- }
-
- AnalysisContext *getCurrentAnalysisContext() const {
- return Pred->getLocationContext()->getAnalysisContext();
- }
-
-private:
- ExplodedNode *generateNodeImpl(const Stmt* stmt, const GRState *state,
- bool markAsSink, const void *tag) {
- ExplodedNode *node = B.generateNode(stmt, state, Pred, tag);
- if (markAsSink && node)
- node->markAsSink();
- return node;
- }
-
- ExplodedNode *generateNodeImpl(const Stmt* stmt, const GRState *state,
- ExplodedNode *pred, bool markAsSink) {
- ExplodedNode *node = B.generateNode(stmt, state, pred, checkerTag);
- if (markAsSink && node)
- node->markAsSink();
- return node;
- }
-};
-
class Checker {
private:
friend class ExprEngine;
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
new file mode 100644
index 0000000..4429c6b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
@@ -0,0 +1,187 @@
+//== CheckerContext.h - Context info for path-sensitive checkers--*- 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 CheckerContext that provides contextual info for
+// path-sensitive checkers.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SA_CORE_PATHSENSITIVE_CHECKERCONTEXT
+#define LLVM_CLANG_SA_CORE_PATHSENSITIVE_CHECKERCONTEXT
+
+#include "clang/Analysis/Support/SaveAndRestore.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+
+namespace clang {
+
+namespace ento {
+
+class CheckerContext {
+ ExplodedNodeSet &Dst;
+ StmtNodeBuilder &B;
+ ExprEngine &Eng;
+ ExplodedNode *Pred;
+ SaveAndRestore<bool> OldSink;
+ const void *checkerTag;
+ SaveAndRestore<ProgramPoint::Kind> OldPointKind;
+ SaveOr OldHasGen;
+ const GRState *ST;
+ const Stmt *statement;
+ const unsigned size;
+public:
+ bool *respondsToCallback;
+public:
+ CheckerContext(ExplodedNodeSet &dst, StmtNodeBuilder &builder,
+ ExprEngine &eng, ExplodedNode *pred,
+ const void *tag, ProgramPoint::Kind K,
+ bool *respondsToCB = 0,
+ const Stmt *stmt = 0, const GRState *st = 0)
+ : Dst(dst), B(builder), Eng(eng), Pred(pred),
+ OldSink(B.BuildSinks),
+ checkerTag(tag),
+ OldPointKind(B.PointKind, K),
+ OldHasGen(B.hasGeneratedNode),
+ ST(st), statement(stmt), size(Dst.size()),
+ respondsToCallback(respondsToCB) {}
+
+ ~CheckerContext();
+
+ ExprEngine &getEngine() {
+ return Eng;
+ }
+
+ AnalysisManager &getAnalysisManager() {
+ return Eng.getAnalysisManager();
+ }
+
+ ConstraintManager &getConstraintManager() {
+ return Eng.getConstraintManager();
+ }
+
+ StoreManager &getStoreManager() {
+ return Eng.getStoreManager();
+ }
+
+ ExplodedNodeSet &getNodeSet() { return Dst; }
+ StmtNodeBuilder &getNodeBuilder() { return B; }
+ ExplodedNode *&getPredecessor() { return Pred; }
+ const GRState *getState() { return ST ? ST : B.GetState(Pred); }
+ const Stmt *getStmt() const { return statement; }
+
+ ASTContext &getASTContext() {
+ return Eng.getContext();
+ }
+
+ BugReporter &getBugReporter() {
+ return Eng.getBugReporter();
+ }
+
+ SourceManager &getSourceManager() {
+ return getBugReporter().getSourceManager();
+ }
+
+ SValBuilder &getSValBuilder() {
+ return Eng.getSValBuilder();
+ }
+
+ ExplodedNode *generateNode(bool autoTransition = true) {
+ assert(statement && "Only transitions with statements currently supported");
+ ExplodedNode *N = generateNodeImpl(statement, getState(), false,
+ checkerTag);
+ if (N && autoTransition)
+ Dst.Add(N);
+ return N;
+ }
+
+ ExplodedNode *generateNode(const Stmt *stmt, const GRState *state,
+ bool autoTransition = true, const void *tag = 0) {
+ assert(state);
+ ExplodedNode *N = generateNodeImpl(stmt, state, false,
+ tag ? tag : checkerTag);
+ if (N && autoTransition)
+ addTransition(N);
+ return N;
+ }
+
+ ExplodedNode *generateNode(const GRState *state, ExplodedNode *pred,
+ bool autoTransition = true) {
+ assert(statement && "Only transitions with statements currently supported");
+ ExplodedNode *N = generateNodeImpl(statement, state, pred, false);
+ if (N && autoTransition)
+ addTransition(N);
+ return N;
+ }
+
+ ExplodedNode *generateNode(const GRState *state, bool autoTransition = true,
+ const void *tag = 0) {
+ assert(statement && "Only transitions with statements currently supported");
+ ExplodedNode *N = generateNodeImpl(statement, state, false,
+ tag ? tag : checkerTag);
+ if (N && autoTransition)
+ addTransition(N);
+ return N;
+ }
+
+ ExplodedNode *generateSink(const Stmt *stmt, const GRState *state = 0) {
+ return generateNodeImpl(stmt, state ? state : getState(), true,
+ checkerTag);
+ }
+
+ ExplodedNode *generateSink(const GRState *state = 0) {
+ assert(statement && "Only transitions with statements currently supported");
+ return generateNodeImpl(statement, state ? state : getState(), true,
+ checkerTag);
+ }
+
+ void addTransition(ExplodedNode *node) {
+ Dst.Add(node);
+ }
+
+ void addTransition(const GRState *state, const void *tag = 0) {
+ assert(state);
+ // If the 'state' is not new, we need to check if the cached state 'ST'
+ // is new.
+ if (state != getState() || (ST && ST != B.GetState(Pred)))
+ // state is new or equals to ST.
+ generateNode(state, true, tag);
+ else
+ Dst.Add(Pred);
+ }
+
+ void EmitReport(BugReport *R) {
+ Eng.getBugReporter().EmitReport(R);
+ }
+
+ AnalysisContext *getCurrentAnalysisContext() const {
+ return Pred->getLocationContext()->getAnalysisContext();
+ }
+
+private:
+ ExplodedNode *generateNodeImpl(const Stmt* stmt, const GRState *state,
+ bool markAsSink, const void *tag) {
+ ExplodedNode *node = B.generateNode(stmt, state, Pred, tag);
+ if (markAsSink && node)
+ node->markAsSink();
+ return node;
+ }
+
+ ExplodedNode *generateNodeImpl(const Stmt* stmt, const GRState *state,
+ ExplodedNode *pred, bool markAsSink) {
+ ExplodedNode *node = B.generateNode(stmt, state, pred, checkerTag);
+ if (markAsSink && node)
+ node->markAsSink();
+ return node;
+ }
+};
+
+} // end GR namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
index 800e63a..25c6447 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
@@ -447,16 +447,22 @@ class EndOfFunctionNodeBuilder {
CoreEngine &Eng;
const CFGBlock& B;
ExplodedNode* Pred;
+ void *Tag;
public:
bool hasGeneratedNode;
public:
- EndOfFunctionNodeBuilder(const CFGBlock* b, ExplodedNode* N, CoreEngine* e)
- : Eng(*e), B(*b), Pred(N), hasGeneratedNode(false) {}
+ EndOfFunctionNodeBuilder(const CFGBlock* b, ExplodedNode* N, CoreEngine* e,
+ void *checkerTag = 0)
+ : Eng(*e), B(*b), Pred(N), Tag(checkerTag), hasGeneratedNode(false) {}
~EndOfFunctionNodeBuilder();
+ EndOfFunctionNodeBuilder withCheckerTag(void *tag) {
+ return EndOfFunctionNodeBuilder(&B, Pred, &Eng, tag);
+ }
+
WorkList &getWorkList() { return *Eng.WList; }
ExplodedNode* getPredecessor() const { return Pred; }
@@ -471,8 +477,8 @@ public:
B.getBlockID());
}
- ExplodedNode* generateNode(const GRState* State, const void *tag = 0,
- ExplodedNode *P = 0);
+ ExplodedNode* generateNode(const GRState* State, ExplodedNode *P = 0,
+ const void *tag = 0);
void GenerateCallExitNode(const GRState *state);
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index 767644a..16f54ee 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -137,6 +137,10 @@ public:
virtual AnalysisManager &getAnalysisManager() { return AMgr; }
+ CheckerManager &getCheckerManager() const {
+ return *AMgr.getCheckerManager();
+ }
+
SValBuilder &getSValBuilder() { return svalBuilder; }
TransferFuncs& getTF() { return *TF; }
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h
index 411441f..07cdbf5 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h
@@ -151,7 +151,21 @@ namespace ento {
typedef bool data_type;
static inline data_type MakeData(void* const* p) {
- return (bool) (uintptr_t) p;
+ return p ? (data_type) (uintptr_t) *p
+ : data_type();
+ }
+ static inline void *MakeVoidPtr(data_type d) {
+ return (void*) (uintptr_t) d;
+ }
+ };
+
+ // Partial specialization for unsigned.
+ template <> struct GRStatePartialTrait<unsigned> {
+ typedef unsigned data_type;
+
+ static inline data_type MakeData(void* const* p) {
+ return p ? (data_type) (uintptr_t) *p
+ : data_type();
}
static inline void *MakeVoidPtr(data_type d) {
return (void*) (uintptr_t) d;
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h
index 4c3e379..9d6298f 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h
@@ -12,12 +12,15 @@
namespace clang {
class AnalyzerOptions;
+ class LangOptions;
class Diagnostic;
namespace ento {
class CheckerManager;
-CheckerManager *registerCheckers(const AnalyzerOptions &opts,Diagnostic &diags);
+CheckerManager *registerCheckers(const AnalyzerOptions &opts,
+ const LangOptions &langOpts,
+ Diagnostic &diags);
} // end ento namespace
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
index e3867a2..f014181 100644
--- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
@@ -26,6 +26,8 @@ protected:
llvm::StringRef InFile);
};
+void printCheckerHelp(llvm::raw_ostream &OS);
+
} // end GR namespace
} // end namespace clang
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp
index 945dfb8..9c24550 100644
--- a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp
@@ -205,7 +205,7 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM,
DeclarationNames(*this),
ExternalSource(0), Listener(0), PrintingPolicy(LOpts),
LastSDM(0, 0),
- UniqueBlockByRefTypeID(0), UniqueBlockParmTypeID(0) {
+ UniqueBlockByRefTypeID(0) {
ObjCIdRedefinitionType = QualType();
ObjCClassRedefinitionType = QualType();
ObjCSelRedefinitionType = QualType();
@@ -874,7 +874,7 @@ ASTContext::getTypeInfo(const Type *T) const {
case Type::Auto: {
const AutoType *A = cast<AutoType>(T);
assert(A->isDeduced() && "Cannot request the size of a dependent type");
- return getTypeInfo(cast<AutoType>(T)->getDeducedType().getTypePtr());
+ return getTypeInfo(A->getDeducedType().getTypePtr());
}
case Type::Paren:
@@ -2683,12 +2683,22 @@ QualType ASTContext::getDecltypeType(Expr *e) const {
return QualType(dt, 0);
}
-/// getAutoType - Unlike many "get<Type>" functions, we don't unique
-/// AutoType AST's.
+/// getAutoType - We only unique auto types after they've been deduced.
QualType ASTContext::getAutoType(QualType DeducedType) const {
- AutoType *at = new (*this, TypeAlignment) AutoType(DeducedType);
- Types.push_back(at);
- return QualType(at, 0);
+ void *InsertPos = 0;
+ if (!DeducedType.isNull()) {
+ // Look in the folding set for an existing type.
+ llvm::FoldingSetNodeID ID;
+ AutoType::Profile(ID, DeducedType);
+ if (AutoType *AT = AutoTypes.FindNodeOrInsertPos(ID, InsertPos))
+ return QualType(AT, 0);
+ }
+
+ AutoType *AT = new (*this, TypeAlignment) AutoType(DeducedType);
+ Types.push_back(AT);
+ if (InsertPos)
+ AutoTypes.InsertNode(AT, InsertPos);
+ return QualType(AT, 0);
}
/// getTagDeclType - Return the unique reference to the type for the
@@ -2971,7 +2981,15 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const {
case NestedNameSpecifier::Namespace:
// A namespace is canonical; build a nested-name-specifier with
// this namespace and no prefix.
- return NestedNameSpecifier::Create(*this, 0, NNS->getAsNamespace());
+ return NestedNameSpecifier::Create(*this, 0,
+ NNS->getAsNamespace()->getOriginalNamespace());
+
+ case NestedNameSpecifier::NamespaceAlias:
+ // A namespace is canonical; build a nested-name-specifier with
+ // this namespace and no prefix.
+ return NestedNameSpecifier::Create(*this, 0,
+ NNS->getAsNamespaceAlias()->getNamespace()
+ ->getOriginalNamespace());
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate: {
@@ -3609,78 +3627,6 @@ ASTContext::BuildByRefType(llvm::StringRef DeclName, QualType Ty) const {
return getPointerType(getTagDeclType(T));
}
-
-QualType ASTContext::getBlockParmType(
- bool BlockHasCopyDispose,
- llvm::SmallVectorImpl<const Expr *> &Layout) const {
-
- // FIXME: Move up
- llvm::SmallString<36> Name;
- llvm::raw_svector_ostream(Name) << "__block_literal_"
- << ++UniqueBlockParmTypeID;
- RecordDecl *T;
- T = CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(),
- &Idents.get(Name.str()));
- T->startDefinition();
- QualType FieldTypes[] = {
- getPointerType(VoidPtrTy),
- IntTy,
- IntTy,
- getPointerType(VoidPtrTy),
- (BlockHasCopyDispose ?
- getPointerType(getBlockDescriptorExtendedType()) :
- getPointerType(getBlockDescriptorType()))
- };
-
- const char *FieldNames[] = {
- "__isa",
- "__flags",
- "__reserved",
- "__FuncPtr",
- "__descriptor"
- };
-
- for (size_t i = 0; i < 5; ++i) {
- FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(),
- &Idents.get(FieldNames[i]),
- FieldTypes[i], /*TInfo=*/0,
- /*BitWidth=*/0, /*Mutable=*/false);
- Field->setAccess(AS_public);
- T->addDecl(Field);
- }
-
- for (unsigned i = 0; i < Layout.size(); ++i) {
- const Expr *E = Layout[i];
-
- QualType FieldType = E->getType();
- IdentifierInfo *FieldName = 0;
- if (isa<CXXThisExpr>(E)) {
- FieldName = &Idents.get("this");
- } else if (const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E)) {
- const ValueDecl *D = BDRE->getDecl();
- FieldName = D->getIdentifier();
- if (BDRE->isByRef())
- FieldType = BuildByRefType(D->getName(), FieldType);
- } else {
- // Padding.
- assert(isa<ConstantArrayType>(FieldType) &&
- isa<DeclRefExpr>(E) &&
- !cast<DeclRefExpr>(E)->getDecl()->getDeclName() &&
- "doesn't match characteristics of padding decl");
- }
-
- FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(),
- FieldName, FieldType, /*TInfo=*/0,
- /*BitWidth=*/0, /*Mutable=*/false);
- Field->setAccess(AS_public);
- T->addDecl(Field);
- }
-
- T->completeDefinition();
-
- return getPointerType(getTagDeclType(T));
-}
-
void ASTContext::setObjCFastEnumerationStateType(QualType T) {
const RecordType *Rec = T->getAs<RecordType>();
assert(Rec && "Invalid ObjCFAstEnumerationStateType");
diff --git a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp
index 65c0a3b..21f10fb 100644
--- a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp
@@ -2097,11 +2097,7 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) {
D->isScoped(), D->isScopedUsingClassTag(),
D->isFixed());
// Import the qualifier, if any.
- if (D->getQualifier()) {
- NestedNameSpecifier *NNS = Importer.Import(D->getQualifier());
- SourceRange NNSRange = Importer.Import(D->getQualifierRange());
- D2->setQualifierInfo(NNS, NNSRange);
- }
+ D2->setQualifierInfo(Importer.Import(D->getQualifierLoc()));
D2->setAccess(D->getAccess());
D2->setLexicalDeclContext(LexicalDC);
Importer.Imported(D, D2);
@@ -2225,12 +2221,8 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
Name.getAsIdentifierInfo(),
Importer.Import(D->getTagKeywordLoc()));
}
- // Import the qualifier, if any.
- if (D->getQualifier()) {
- NestedNameSpecifier *NNS = Importer.Import(D->getQualifier());
- SourceRange NNSRange = Importer.Import(D->getQualifierRange());
- D2->setQualifierInfo(NNS, NNSRange);
- }
+
+ D2->setQualifierInfo(Importer.Import(D->getQualifierLoc()));
D2->setLexicalDeclContext(LexicalDC);
LexicalDC->addDecl(D2);
}
@@ -2408,11 +2400,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
}
// Import the qualifier, if any.
- if (D->getQualifier()) {
- NestedNameSpecifier *NNS = Importer.Import(D->getQualifier());
- SourceRange NNSRange = Importer.Import(D->getQualifierRange());
- ToFunction->setQualifierInfo(NNS, NNSRange);
- }
+ ToFunction->setQualifierInfo(Importer.Import(D->getQualifierLoc()));
ToFunction->setAccess(D->getAccess());
ToFunction->setLexicalDeclContext(LexicalDC);
ToFunction->setVirtualAsWritten(D->isVirtualAsWritten());
@@ -2666,12 +2654,7 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) {
Name.getAsIdentifierInfo(), T, TInfo,
D->getStorageClass(),
D->getStorageClassAsWritten());
- // Import the qualifier, if any.
- if (D->getQualifier()) {
- NestedNameSpecifier *NNS = Importer.Import(D->getQualifier());
- SourceRange NNSRange = Importer.Import(D->getQualifierRange());
- ToVar->setQualifierInfo(NNS, NNSRange);
- }
+ ToVar->setQualifierInfo(Importer.Import(D->getQualifierLoc()));
ToVar->setAccess(D->getAccess());
ToVar->setLexicalDeclContext(LexicalDC);
Importer.Imported(D, ToVar);
@@ -3591,14 +3574,7 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
Name.getAsIdentifierInfo(),
Importer.Import(DTemplated->getTagKeywordLoc()));
D2Templated->setAccess(DTemplated->getAccess());
-
-
- // Import the qualifier, if any.
- if (DTemplated->getQualifier()) {
- NestedNameSpecifier *NNS = Importer.Import(DTemplated->getQualifier());
- SourceRange NNSRange = Importer.Import(DTemplated->getQualifierRange());
- D2Templated->setQualifierInfo(NNS, NNSRange);
- }
+ D2Templated->setQualifierInfo(Importer.Import(DTemplated->getQualifierLoc()));
D2Templated->setLexicalDeclContext(LexicalDC);
// Create the class template declaration itself.
@@ -3703,12 +3679,7 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl(
ClassTemplate->AddSpecialization(D2, InsertPos);
// Import the qualifier, if any.
- if (D->getQualifier()) {
- NestedNameSpecifier *NNS = Importer.Import(D->getQualifier());
- SourceRange NNSRange = Importer.Import(D->getQualifierRange());
- D2->setQualifierInfo(NNS, NNSRange);
- }
-
+ D2->setQualifierInfo(Importer.Import(D->getQualifierLoc()));
// Add the specialization to this context.
D2->setLexicalDeclContext(LexicalDC);
@@ -4067,6 +4038,11 @@ NestedNameSpecifier *ASTImporter::Import(NestedNameSpecifier *FromNNS) {
return 0;
}
+NestedNameSpecifierLoc ASTImporter::Import(NestedNameSpecifierLoc FromNNS) {
+ // FIXME: Implement!
+ return NestedNameSpecifierLoc();
+}
+
TemplateName ASTImporter::Import(TemplateName From) {
switch (From.getKind()) {
case TemplateName::Template:
diff --git a/contrib/llvm/tools/clang/lib/AST/Decl.cpp b/contrib/llvm/tools/clang/lib/AST/Decl.cpp
index 56db8c7..73fe117 100644
--- a/contrib/llvm/tools/clang/lib/AST/Decl.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Decl.cpp
@@ -266,8 +266,12 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
return LinkageInfo::internal();
}
- if (D->isInAnonymousNamespace())
- return LinkageInfo::uniqueExternal();
+ if (D->isInAnonymousNamespace()) {
+ const VarDecl *Var = dyn_cast<VarDecl>(D);
+ const FunctionDecl *Func = dyn_cast<FunctionDecl>(D);
+ if ((!Var || !Var->isExternC()) && (!Func || !Func->isExternC()))
+ return LinkageInfo::uniqueExternal();
+ }
// Set up the defaults.
@@ -704,7 +708,7 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) {
// external linkage.
if (D->getLexicalDeclContext()->isFunctionOrMethod()) {
if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
- if (Function->isInAnonymousNamespace())
+ if (Function->isInAnonymousNamespace() && !Function->isExternC())
return LinkageInfo::uniqueExternal();
LinkageInfo LV;
@@ -725,7 +729,7 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) {
if (const VarDecl *Var = dyn_cast<VarDecl>(D))
if (Var->getStorageClass() == SC_Extern ||
Var->getStorageClass() == SC_PrivateExtern) {
- if (Var->isInAnonymousNamespace())
+ if (Var->isInAnonymousNamespace() && !Var->isExternC())
return LinkageInfo::uniqueExternal();
LinkageInfo LV;
@@ -837,8 +841,10 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD) const {
// UsingDirectiveDecl's are not really NamedDecl's, and all have same name.
// We want to keep it, unless it nominates same namespace.
if (getKind() == Decl::UsingDirective) {
- return cast<UsingDirectiveDecl>(this)->getNominatedNamespace() ==
- cast<UsingDirectiveDecl>(OldD)->getNominatedNamespace();
+ return cast<UsingDirectiveDecl>(this)->getNominatedNamespace()
+ ->getOriginalNamespace() ==
+ cast<UsingDirectiveDecl>(OldD)->getNominatedNamespace()
+ ->getOriginalNamespace();
}
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(this))
@@ -864,9 +870,13 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD) const {
return cast<UsingShadowDecl>(this)->getTargetDecl() ==
cast<UsingShadowDecl>(OldD)->getTargetDecl();
- if (isa<UsingDecl>(this) && isa<UsingDecl>(OldD))
- return cast<UsingDecl>(this)->getTargetNestedNameDecl() ==
- cast<UsingDecl>(OldD)->getTargetNestedNameDecl();
+ if (isa<UsingDecl>(this) && isa<UsingDecl>(OldD)) {
+ ASTContext &Context = getASTContext();
+ return Context.getCanonicalNestedNameSpecifier(
+ cast<UsingDecl>(this)->getQualifier()) ==
+ Context.getCanonicalNestedNameSpecifier(
+ cast<UsingDecl>(OldD)->getQualifier());
+ }
// For non-function declarations, if the declarations are of the
// same kind then this must be a redeclaration, or semantic analysis
@@ -927,9 +937,8 @@ SourceLocation DeclaratorDecl::getTypeSpecStartLoc() const {
return SourceLocation();
}
-void DeclaratorDecl::setQualifierInfo(NestedNameSpecifier *Qualifier,
- SourceRange QualifierRange) {
- if (Qualifier) {
+void DeclaratorDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) {
+ if (QualifierLoc) {
// Make sure the extended decl info is allocated.
if (!hasExtInfo()) {
// Save (non-extended) type source info pointer.
@@ -940,12 +949,10 @@ void DeclaratorDecl::setQualifierInfo(NestedNameSpecifier *Qualifier,
getExtInfo()->TInfo = savedTInfo;
}
// Set qualifier info.
- getExtInfo()->NNS = Qualifier;
- getExtInfo()->NNSRange = QualifierRange;
+ getExtInfo()->QualifierLoc = QualifierLoc;
}
else {
// Here Qualifier == 0, i.e., we are removing the qualifier (if any).
- assert(QualifierRange.isInvalid());
if (hasExtInfo()) {
// Save type source info pointer.
TypeSourceInfo *savedTInfo = getExtInfo()->TInfo;
@@ -967,7 +974,7 @@ QualifierInfo::setTemplateParameterListsInfo(ASTContext &Context,
TemplateParameterList **TPLists) {
assert((NumTPLists == 0 || TPLists != 0) &&
"Empty array of template parameters with positive size!");
- assert((NumTPLists == 0 || NNS) &&
+ assert((NumTPLists == 0 || QualifierLoc) &&
"Nonempty array of template parameters with no qualifier!");
// Free previous template parameters (if any).
@@ -1037,8 +1044,11 @@ bool VarDecl::isExternC() const {
getStorageClass() != SC_Static) ||
(getDeclContext()->isFunctionOrMethod() && hasExternalStorage());
- for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit();
- DC = DC->getParent()) {
+ const DeclContext *DC = getDeclContext();
+ if (DC->isFunctionOrMethod())
+ return false;
+
+ for (; !DC->isTranslationUnit(); DC = DC->getParent()) {
if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) {
if (Linkage->getLanguage() == LinkageSpecDecl::lang_c)
return getStorageClass() != SC_Static;
@@ -1046,8 +1056,6 @@ bool VarDecl::isExternC() const {
break;
}
- if (DC->isFunctionOrMethod())
- return false;
}
return false;
@@ -1363,8 +1371,11 @@ bool FunctionDecl::isExternC() const {
if (!Context.getLangOptions().CPlusPlus)
return getStorageClass() != SC_Static && !getAttr<OverloadableAttr>();
- for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit();
- DC = DC->getParent()) {
+ const DeclContext *DC = getDeclContext();
+ if (DC->isRecord())
+ return false;
+
+ for (; !DC->isTranslationUnit(); DC = DC->getParent()) {
if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) {
if (Linkage->getLanguage() == LinkageSpecDecl::lang_c)
return getStorageClass() != SC_Static &&
@@ -1372,9 +1383,6 @@ bool FunctionDecl::isExternC() const {
break;
}
-
- if (DC->isRecord())
- break;
}
return isMain();
@@ -2018,19 +2026,16 @@ TagDecl* TagDecl::getDefinition() const {
return 0;
}
-void TagDecl::setQualifierInfo(NestedNameSpecifier *Qualifier,
- SourceRange QualifierRange) {
- if (Qualifier) {
+void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) {
+ if (QualifierLoc) {
// Make sure the extended qualifier info is allocated.
if (!hasExtInfo())
TypedefDeclOrQualifier = new (getASTContext()) ExtInfo;
// Set qualifier info.
- getExtInfo()->NNS = Qualifier;
- getExtInfo()->NNSRange = QualifierRange;
+ getExtInfo()->QualifierLoc = QualifierLoc;
}
else {
// Here Qualifier == 0, i.e., we are removing the qualifier (if any).
- assert(QualifierRange.isInvalid());
if (hasExtInfo()) {
getASTContext().Deallocate(getExtInfo());
TypedefDeclOrQualifier = (TypedefDecl*) 0;
@@ -2211,8 +2216,10 @@ NamespaceDecl *NamespaceDecl::getNextNamespace() {
}
ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC,
- SourceLocation L, IdentifierInfo *Id, QualType T) {
- return new (C) ImplicitParamDecl(ImplicitParam, DC, L, Id, T);
+ SourceLocation loc,
+ IdentifierInfo *name,
+ QualType type) {
+ return new (C) ImplicitParamDecl(DC, loc, name, type);
}
FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC,
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp
index be379d5..81df00d 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp
@@ -465,6 +465,22 @@ void Decl::CheckAccessDeclContext() const {
#endif
}
+DeclContext *Decl::getNonClosureContext() {
+ DeclContext *DC = getDeclContext();
+
+ // This is basically "while (DC->isClosure()) DC = DC->getParent();"
+ // except that it's significantly more efficient to cast to a known
+ // decl type and call getDeclContext() than to call getParent().
+ do {
+ if (isa<BlockDecl>(DC)) {
+ DC = cast<BlockDecl>(DC)->getDeclContext();
+ continue;
+ }
+ } while (false);
+
+ assert(!DC->isClosure());
+ return DC;
+}
//===----------------------------------------------------------------------===//
// DeclContext Implementation
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp
index fba73f5..46768c1 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp
@@ -1267,15 +1267,14 @@ LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
UsingDirectiveDecl *UsingDirectiveDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
SourceLocation NamespaceLoc,
- SourceRange QualifierRange,
- NestedNameSpecifier *Qualifier,
+ NestedNameSpecifierLoc QualifierLoc,
SourceLocation IdentLoc,
NamedDecl *Used,
DeclContext *CommonAncestor) {
if (NamespaceDecl *NS = dyn_cast_or_null<NamespaceDecl>(Used))
Used = NS->getOriginalNamespace();
- return new (C) UsingDirectiveDecl(DC, L, NamespaceLoc, QualifierRange,
- Qualifier, IdentLoc, Used, CommonAncestor);
+ return new (C) UsingDirectiveDecl(DC, L, NamespaceLoc, QualifierLoc,
+ IdentLoc, Used, CommonAncestor);
}
NamespaceDecl *UsingDirectiveDecl::getNominatedNamespace() {
@@ -1289,14 +1288,13 @@ NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation UsingLoc,
SourceLocation AliasLoc,
IdentifierInfo *Alias,
- SourceRange QualifierRange,
- NestedNameSpecifier *Qualifier,
+ NestedNameSpecifierLoc QualifierLoc,
SourceLocation IdentLoc,
NamedDecl *Namespace) {
if (NamespaceDecl *NS = dyn_cast_or_null<NamespaceDecl>(Namespace))
Namespace = NS->getOriginalNamespace();
- return new (C) NamespaceAliasDecl(DC, UsingLoc, AliasLoc, Alias, QualifierRange,
- Qualifier, IdentLoc, Namespace);
+ return new (C) NamespaceAliasDecl(DC, UsingLoc, AliasLoc, Alias,
+ QualifierLoc, IdentLoc, Namespace);
}
UsingDecl *UsingShadowDecl::getUsingDecl() const {
@@ -1337,35 +1335,31 @@ void UsingDecl::removeShadowDecl(UsingShadowDecl *S) {
S->UsingOrNextShadow = this;
}
-UsingDecl *UsingDecl::Create(ASTContext &C, DeclContext *DC,
- SourceRange NNR, SourceLocation UL,
- NestedNameSpecifier* TargetNNS,
+UsingDecl *UsingDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation UL,
+ NestedNameSpecifierLoc QualifierLoc,
const DeclarationNameInfo &NameInfo,
bool IsTypeNameArg) {
- return new (C) UsingDecl(DC, NNR, UL, TargetNNS, NameInfo, IsTypeNameArg);
+ return new (C) UsingDecl(DC, UL, QualifierLoc, NameInfo, IsTypeNameArg);
}
UnresolvedUsingValueDecl *
UnresolvedUsingValueDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation UsingLoc,
- SourceRange TargetNNR,
- NestedNameSpecifier *TargetNNS,
+ NestedNameSpecifierLoc QualifierLoc,
const DeclarationNameInfo &NameInfo) {
return new (C) UnresolvedUsingValueDecl(DC, C.DependentTy, UsingLoc,
- TargetNNR, TargetNNS, NameInfo);
+ QualifierLoc, NameInfo);
}
UnresolvedUsingTypenameDecl *
UnresolvedUsingTypenameDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation UsingLoc,
SourceLocation TypenameLoc,
- SourceRange TargetNNR,
- NestedNameSpecifier *TargetNNS,
+ NestedNameSpecifierLoc QualifierLoc,
SourceLocation TargetNameLoc,
DeclarationName TargetName) {
return new (C) UnresolvedUsingTypenameDecl(DC, UsingLoc, TypenameLoc,
- TargetNNR, TargetNNS,
- TargetNameLoc,
+ QualifierLoc, TargetNameLoc,
TargetName.getAsIdentifierInfo());
}
diff --git a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp
index 77b4257..c6ae128 100644
--- a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp
@@ -918,20 +918,20 @@ void DeclPrinter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) {
void DeclPrinter::VisitUsingDecl(UsingDecl *D) {
Out << "using ";
- D->getTargetNestedNameDecl()->print(Out, Policy);
+ D->getQualifier()->print(Out, Policy);
Out << D;
}
void
DeclPrinter::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
Out << "using typename ";
- D->getTargetNestedNameSpecifier()->print(Out, Policy);
+ D->getQualifier()->print(Out, Policy);
Out << D->getDeclName();
}
void DeclPrinter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
Out << "using ";
- D->getTargetNestedNameSpecifier()->print(Out, Policy);
+ D->getQualifier()->print(Out, Policy);
Out << D->getDeclName();
}
diff --git a/contrib/llvm/tools/clang/lib/AST/Expr.cpp b/contrib/llvm/tools/clang/lib/AST/Expr.cpp
index 391b26a..1c1061b 100644
--- a/contrib/llvm/tools/clang/lib/AST/Expr.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Expr.cpp
@@ -836,6 +836,19 @@ QualType CallExpr::getCallReturnType() const {
return FnType->getResultType();
}
+SourceRange CallExpr::getSourceRange() const {
+ if (isa<CXXOperatorCallExpr>(this))
+ return cast<CXXOperatorCallExpr>(this)->getSourceRange();
+
+ SourceLocation begin = getCallee()->getLocStart();
+ if (begin.isInvalid() && getNumArgs() > 0)
+ begin = getArg(0)->getLocStart();
+ SourceLocation end = getRParenLoc();
+ if (end.isInvalid() && getNumArgs() > 0)
+ end = getArg(getNumArgs() - 1)->getLocEnd();
+ return SourceRange(begin, end);
+}
+
OffsetOfExpr *OffsetOfExpr::Create(ASTContext &C, QualType type,
SourceLocation OperatorLoc,
TypeSourceInfo *tsi,
diff --git a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp
index 28ff9fb..4f4a6b4 100644
--- a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp
@@ -128,10 +128,10 @@ PseudoDestructorTypeStorage::PseudoDestructorTypeStorage(TypeSourceInfo *Info)
}
CXXPseudoDestructorExpr::CXXPseudoDestructorExpr(ASTContext &Context,
- Expr *Base, bool isArrow, SourceLocation OperatorLoc,
- NestedNameSpecifier *Qualifier, SourceRange QualifierRange,
- TypeSourceInfo *ScopeType, SourceLocation ColonColonLoc,
- SourceLocation TildeLoc, PseudoDestructorTypeStorage DestroyedType)
+ Expr *Base, bool isArrow, SourceLocation OperatorLoc,
+ NestedNameSpecifierLoc QualifierLoc, TypeSourceInfo *ScopeType,
+ SourceLocation ColonColonLoc, SourceLocation TildeLoc,
+ PseudoDestructorTypeStorage DestroyedType)
: Expr(CXXPseudoDestructorExprClass,
Context.getPointerType(Context.getFunctionType(Context.VoidTy, 0, 0,
FunctionProtoType::ExtProtoInfo())),
@@ -142,15 +142,16 @@ CXXPseudoDestructorExpr::CXXPseudoDestructorExpr(ASTContext &Context,
/*isValueDependent=*/Base->isValueDependent(),
// ContainsUnexpandedParameterPack
(Base->containsUnexpandedParameterPack() ||
- (Qualifier && Qualifier->containsUnexpandedParameterPack()) ||
+ (QualifierLoc &&
+ QualifierLoc.getNestedNameSpecifier()
+ ->containsUnexpandedParameterPack()) ||
(ScopeType &&
ScopeType->getType()->containsUnexpandedParameterPack()) ||
(DestroyedType.getTypeSourceInfo() &&
DestroyedType.getTypeSourceInfo()->getType()
->containsUnexpandedParameterPack()))),
Base(static_cast<Stmt *>(Base)), IsArrow(isArrow),
- OperatorLoc(OperatorLoc), Qualifier(Qualifier),
- QualifierRange(QualifierRange),
+ OperatorLoc(OperatorLoc), QualifierLoc(QualifierLoc),
ScopeType(ScopeType), ColonColonLoc(ColonColonLoc), TildeLoc(TildeLoc),
DestroyedType(DestroyedType) { }
@@ -282,15 +283,16 @@ CXXRecordDecl *OverloadExpr::getNamingClass() const {
// DependentScopeDeclRefExpr
DependentScopeDeclRefExpr::DependentScopeDeclRefExpr(QualType T,
- NestedNameSpecifier *Qualifier,
- SourceRange QualifierRange,
+ NestedNameSpecifierLoc QualifierLoc,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *Args)
: Expr(DependentScopeDeclRefExprClass, T, VK_LValue, OK_Ordinary,
true, true,
(NameInfo.containsUnexpandedParameterPack() ||
- (Qualifier && Qualifier->containsUnexpandedParameterPack()))),
- NameInfo(NameInfo), QualifierRange(QualifierRange), Qualifier(Qualifier),
+ (QualifierLoc &&
+ QualifierLoc.getNestedNameSpecifier()
+ ->containsUnexpandedParameterPack()))),
+ QualifierLoc(QualifierLoc), NameInfo(NameInfo),
HasExplicitTemplateArgs(Args != 0)
{
if (Args) {
@@ -306,16 +308,14 @@ DependentScopeDeclRefExpr::DependentScopeDeclRefExpr(QualType T,
DependentScopeDeclRefExpr *
DependentScopeDeclRefExpr::Create(ASTContext &C,
- NestedNameSpecifier *Qualifier,
- SourceRange QualifierRange,
+ NestedNameSpecifierLoc QualifierLoc,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *Args) {
std::size_t size = sizeof(DependentScopeDeclRefExpr);
if (Args)
size += ExplicitTemplateArgumentList::sizeFor(*Args);
void *Mem = C.Allocate(size);
- return new (Mem) DependentScopeDeclRefExpr(C.DependentTy,
- Qualifier, QualifierRange,
+ return new (Mem) DependentScopeDeclRefExpr(C.DependentTy, QualifierLoc,
NameInfo, Args);
}
@@ -328,13 +328,16 @@ DependentScopeDeclRefExpr::CreateEmpty(ASTContext &C,
size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs);
void *Mem = C.Allocate(size);
DependentScopeDeclRefExpr *E
- = new (Mem) DependentScopeDeclRefExpr(QualType(), 0, SourceRange(),
+ = new (Mem) DependentScopeDeclRefExpr(QualType(), NestedNameSpecifierLoc(),
DeclarationNameInfo(), 0);
E->HasExplicitTemplateArgs = HasExplicitTemplateArgs;
return E;
}
SourceRange CXXConstructExpr::getSourceRange() const {
+ if (isa<CXXTemporaryObjectExpr>(this))
+ return cast<CXXTemporaryObjectExpr>(this)->getSourceRange();
+
if (ParenRange.isValid())
return SourceRange(Loc, ParenRange.getEnd());
@@ -397,13 +400,6 @@ CXXRecordDecl *CXXMemberCallExpr::getRecordDecl() {
return ThisArg->getType()->getAsCXXRecordDecl();
}
-SourceRange CXXMemberCallExpr::getSourceRange() const {
- SourceLocation LocStart = getCallee()->getLocStart();
- if (LocStart.isInvalid() && getNumArgs() > 0)
- LocStart = getArg(0)->getLocStart();
- return SourceRange(LocStart, getRParenLoc());
-}
-
//===----------------------------------------------------------------------===//
// Named casts
diff --git a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp
index 656bb99..3a5eb66 100644
--- a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp
@@ -2926,7 +2926,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
Exp->getOpcode() == BO_Rem) {
// Evaluate gives an error for undefined Div/Rem, so make sure
// we don't evaluate one.
- if (LHSResult.Val != 2 && RHSResult.Val != 2) {
+ if (LHSResult.Val == 0 && RHSResult.Val == 0) {
llvm::APSInt REval = Exp->getRHS()->EvaluateAsInt(Ctx);
if (REval == 0)
return ICEDiag(1, E->getLocStart());
diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp
index d66c374..939ca7a 100644
--- a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp
@@ -606,6 +606,9 @@ void CXXNameMangler::mangleUnresolvedScope(NestedNameSpecifier *Qualifier) {
case NestedNameSpecifier::Namespace:
mangleName(Qualifier->getAsNamespace());
break;
+ case NestedNameSpecifier::NamespaceAlias:
+ mangleName(Qualifier->getAsNamespaceAlias()->getNamespace());
+ break;
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate: {
const Type *QTy = Qualifier->getAsType();
@@ -1647,8 +1650,11 @@ void CXXNameMangler::mangleType(const DecltypeType *T) {
void CXXNameMangler::mangleType(const AutoType *T) {
QualType D = T->getDeducedType();
- assert(!D.isNull() && "can't mangle undeduced auto type");
- mangleType(D);
+ // <builtin-type> ::= Da # dependent auto
+ if (D.isNull())
+ Out << "Da";
+ else
+ mangleType(D);
}
void CXXNameMangler::mangleIntegerLiteral(QualType T,
diff --git a/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp b/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp
index 650321d..6f1ec05 100644
--- a/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp
@@ -14,8 +14,10 @@
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/Type.h"
+#include "clang/AST/TypeLoc.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
@@ -46,7 +48,7 @@ NestedNameSpecifier::Create(const ASTContext &Context,
NestedNameSpecifier Mockup;
Mockup.Prefix.setPointer(Prefix);
- Mockup.Prefix.setInt(Identifier);
+ Mockup.Prefix.setInt(StoredIdentifier);
Mockup.Specifier = II;
return FindOrInsert(Context, Mockup);
}
@@ -60,19 +62,34 @@ NestedNameSpecifier::Create(const ASTContext &Context,
"Broken nested name specifier");
NestedNameSpecifier Mockup;
Mockup.Prefix.setPointer(Prefix);
- Mockup.Prefix.setInt(Namespace);
+ Mockup.Prefix.setInt(StoredNamespaceOrAlias);
Mockup.Specifier = NS;
return FindOrInsert(Context, Mockup);
}
NestedNameSpecifier *
NestedNameSpecifier::Create(const ASTContext &Context,
+ NestedNameSpecifier *Prefix,
+ NamespaceAliasDecl *Alias) {
+ assert(Alias && "Namespace alias cannot be NULL");
+ assert((!Prefix ||
+ (Prefix->getAsType() == 0 && Prefix->getAsIdentifier() == 0)) &&
+ "Broken nested name specifier");
+ NestedNameSpecifier Mockup;
+ Mockup.Prefix.setPointer(Prefix);
+ Mockup.Prefix.setInt(StoredNamespaceOrAlias);
+ Mockup.Specifier = Alias;
+ return FindOrInsert(Context, Mockup);
+}
+
+NestedNameSpecifier *
+NestedNameSpecifier::Create(const ASTContext &Context,
NestedNameSpecifier *Prefix,
bool Template, const Type *T) {
assert(T && "Type cannot be NULL");
NestedNameSpecifier Mockup;
Mockup.Prefix.setPointer(Prefix);
- Mockup.Prefix.setInt(Template? TypeSpecWithTemplate : TypeSpec);
+ Mockup.Prefix.setInt(Template? StoredTypeSpecWithTemplate : StoredTypeSpec);
Mockup.Specifier = const_cast<Type*>(T);
return FindOrInsert(Context, Mockup);
}
@@ -82,7 +99,7 @@ NestedNameSpecifier::Create(const ASTContext &Context, IdentifierInfo *II) {
assert(II && "Identifier cannot be NULL");
NestedNameSpecifier Mockup;
Mockup.Prefix.setPointer(0);
- Mockup.Prefix.setInt(Identifier);
+ Mockup.Prefix.setInt(StoredIdentifier);
Mockup.Specifier = II;
return FindOrInsert(Context, Mockup);
}
@@ -94,6 +111,47 @@ NestedNameSpecifier::GlobalSpecifier(const ASTContext &Context) {
return Context.GlobalNestedNameSpecifier;
}
+NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const {
+ if (Specifier == 0)
+ return Global;
+
+ switch (Prefix.getInt()) {
+ case StoredIdentifier:
+ return Identifier;
+
+ case StoredNamespaceOrAlias:
+ return isa<NamespaceDecl>(static_cast<NamedDecl *>(Specifier))? Namespace
+ : NamespaceAlias;
+
+ case StoredTypeSpec:
+ return TypeSpec;
+
+ case StoredTypeSpecWithTemplate:
+ return TypeSpecWithTemplate;
+ }
+
+ return Global;
+}
+
+/// \brief Retrieve the namespace stored in this nested name
+/// specifier.
+NamespaceDecl *NestedNameSpecifier::getAsNamespace() const {
+ if (Prefix.getInt() == StoredNamespaceOrAlias)
+ return dyn_cast<NamespaceDecl>(static_cast<NamedDecl *>(Specifier));
+
+ return 0;
+}
+
+/// \brief Retrieve the namespace alias stored in this nested name
+/// specifier.
+NamespaceAliasDecl *NestedNameSpecifier::getAsNamespaceAlias() const {
+ if (Prefix.getInt() == StoredNamespaceOrAlias)
+ return dyn_cast<NamespaceAliasDecl>(static_cast<NamedDecl *>(Specifier));
+
+ return 0;
+}
+
+
/// \brief Whether this nested name specifier refers to a dependent
/// type or not.
bool NestedNameSpecifier::isDependent() const {
@@ -103,6 +161,7 @@ bool NestedNameSpecifier::isDependent() const {
return true;
case Namespace:
+ case NamespaceAlias:
case Global:
return false;
@@ -121,6 +180,7 @@ bool NestedNameSpecifier::containsUnexpandedParameterPack() const {
return getPrefix() && getPrefix()->containsUnexpandedParameterPack();
case Namespace:
+ case NamespaceAlias:
case Global:
return false;
@@ -147,7 +207,11 @@ NestedNameSpecifier::print(llvm::raw_ostream &OS,
break;
case Namespace:
- OS << getAsNamespace()->getIdentifier()->getName();
+ OS << getAsNamespace()->getName();
+ break;
+
+ case NamespaceAlias:
+ OS << getAsNamespaceAlias()->getName();
break;
case Global:
@@ -199,3 +263,111 @@ NestedNameSpecifier::print(llvm::raw_ostream &OS,
void NestedNameSpecifier::dump(const LangOptions &LO) {
print(llvm::errs(), PrintingPolicy(LO));
}
+
+unsigned
+NestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) {
+ assert(Qualifier && "Expected a non-NULL qualifier");
+
+ // Location of the trailing '::'.
+ unsigned Length = sizeof(unsigned);
+
+ switch (Qualifier->getKind()) {
+ case NestedNameSpecifier::Global:
+ // Nothing more to add.
+ break;
+
+ case NestedNameSpecifier::Identifier:
+ case NestedNameSpecifier::Namespace:
+ case NestedNameSpecifier::NamespaceAlias:
+ // The location of the identifier or namespace name.
+ Length += sizeof(unsigned);
+ break;
+
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ case NestedNameSpecifier::TypeSpec:
+ // The "void*" that points at the TypeLoc data.
+ // Note: the 'template' keyword is part of the TypeLoc.
+ Length += sizeof(void *);
+ break;
+ }
+
+ return Length;
+}
+
+unsigned
+NestedNameSpecifierLoc::getDataLength(NestedNameSpecifier *Qualifier) {
+ unsigned Length = 0;
+ for (; Qualifier; Qualifier = Qualifier->getPrefix())
+ Length += getLocalDataLength(Qualifier);
+ return Length;
+}
+
+namespace {
+ /// \brief Load a (possibly unaligned) source location from a given address
+ /// and offset.
+ SourceLocation LoadSourceLocation(void *Data, unsigned Offset) {
+ unsigned Raw;
+ memcpy(&Raw, static_cast<char *>(Data) + Offset, sizeof(unsigned));
+ return SourceLocation::getFromRawEncoding(Raw);
+ }
+
+ /// \brief Load a (possibly unaligned) pointer from a given address and
+ /// offset.
+ void *LoadPointer(void *Data, unsigned Offset) {
+ void *Result;
+ memcpy(&Result, static_cast<char *>(Data) + Offset, sizeof(void*));
+ return Result;
+ }
+}
+
+SourceRange NestedNameSpecifierLoc::getSourceRange() const {
+ if (!Qualifier)
+ return SourceRange();
+
+ NestedNameSpecifierLoc First = *this;
+ while (NestedNameSpecifierLoc Prefix = First.getPrefix())
+ First = Prefix;
+
+ return SourceRange(First.getLocalSourceRange().getBegin(),
+ getLocalSourceRange().getEnd());
+}
+
+SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const {
+ if (!Qualifier)
+ return SourceRange();
+
+ unsigned Offset = getDataLength(Qualifier->getPrefix());
+ switch (Qualifier->getKind()) {
+ case NestedNameSpecifier::Global:
+ return LoadSourceLocation(Data, Offset);
+
+ case NestedNameSpecifier::Identifier:
+ case NestedNameSpecifier::Namespace:
+ case NestedNameSpecifier::NamespaceAlias:
+ return SourceRange(LoadSourceLocation(Data, Offset),
+ LoadSourceLocation(Data, Offset + sizeof(unsigned)));
+
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ case NestedNameSpecifier::TypeSpec: {
+ // The "void*" that points at the TypeLoc data.
+ // Note: the 'template' keyword is part of the TypeLoc.
+ void *TypeData = LoadPointer(Data, Offset);
+ TypeLoc TL(Qualifier->getAsType(), TypeData);
+ return SourceRange(TL.getBeginLoc(),
+ LoadSourceLocation(Data, Offset + sizeof(void*)));
+ }
+ }
+
+ return SourceRange();
+}
+
+TypeLoc NestedNameSpecifierLoc::getTypeLoc() const {
+ assert((Qualifier->getKind() == NestedNameSpecifier::TypeSpec ||
+ Qualifier->getKind() == NestedNameSpecifier::TypeSpecWithTemplate) &&
+ "Nested-name-specifier location is not a type");
+
+ // The "void*" that points at the TypeLoc data.
+ unsigned Offset = getDataLength(Qualifier->getPrefix());
+ void *TypeData = LoadPointer(Data, Offset);
+ return TypeLoc(Qualifier->getAsType(), TypeData);
+}
diff --git a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp
index cf14eba..4ed031f 100644
--- a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp
@@ -698,6 +698,25 @@ protected:
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID);
+ CharUnits getSize() const {
+ assert(Size % Context.getCharWidth() == 0);
+ return Context.toCharUnitsFromBits(Size);
+ }
+ uint64_t getSizeInBits() const { return Size; }
+
+ void setSize(CharUnits NewSize) { Size = Context.toBits(NewSize); }
+ void setSize(uint64_t NewSize) { Size = NewSize; }
+
+ CharUnits getDataSize() const {
+ assert(DataSize % Context.getCharWidth() == 0);
+ return Context.toCharUnitsFromBits(DataSize);
+ }
+ uint64_t getDataSizeInBits() const { return DataSize; }
+
+ void setDataSize(CharUnits NewSize) { DataSize = Context.toBits(NewSize); }
+ void setDataSize(uint64_t NewSize) { DataSize = NewSize; }
+
+
RecordLayoutBuilder(const RecordLayoutBuilder&); // DO NOT IMPLEMENT
void operator=(const RecordLayoutBuilder&); // DO NOT IMPLEMENT
public:
@@ -796,8 +815,8 @@ void RecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) {
assert(DataSize == 0 && "Vtable pointer must be at offset zero!");
// Update the size.
- Size += GetVirtualPointersSize(RD);
- DataSize = Size;
+ setSize(getSizeInBits() + GetVirtualPointersSize(RD));
+ setDataSize(getSizeInBits());
CharUnits UnpackedBaseAlign =
Context.toCharUnitsFromBits(Context.Target.getPointerAlign(0));
@@ -1090,7 +1109,7 @@ CharUnits RecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) {
if (Base->Class->isEmpty() &&
EmptySubobjects->CanPlaceBaseAtOffset(Base, CharUnits::Zero())) {
uint64_t RecordSizeInBits = Context.toBits(Layout.getSize());
- Size = std::max(Size, RecordSizeInBits);
+ setSize(std::max(getSizeInBits(), RecordSizeInBits));
return CharUnits::Zero();
}
@@ -1106,7 +1125,7 @@ CharUnits RecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) {
// Round up the current record size to the base's alignment boundary.
uint64_t Offset =
- llvm::RoundUpToAlignment(DataSize, Context.toBits(BaseAlign));
+ llvm::RoundUpToAlignment(getDataSizeInBits(), Context.toBits(BaseAlign));
// Try to place the base.
while (!EmptySubobjects->CanPlaceBaseAtOffset(Base,
@@ -1115,11 +1134,12 @@ CharUnits RecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) {
if (!Base->Class->isEmpty()) {
// Update the data size.
- DataSize = Offset + Context.toBits(Layout.getNonVirtualSize());
+ setDataSize(Offset + Context.toBits(Layout.getNonVirtualSize()));
- Size = std::max(Size, DataSize);
+ setSize(std::max(getSizeInBits(), getDataSizeInBits()));
} else
- Size = std::max(Size, Offset + Context.toBits(Layout.getSize()));
+ setSize(std::max(getSizeInBits(),
+ Offset + Context.toBits(Layout.getSize())));
// Remember max struct/class alignment.
UpdateAlignment(BaseAlign, UnpackedBaseAlign);
@@ -1167,7 +1187,8 @@ void RecordLayoutBuilder::Layout(const CXXRecordDecl *RD) {
LayoutFields(RD);
- NonVirtualSize = Context.toCharUnitsFromBits(Size);
+ // FIXME: Size isn't always an exact multiple of the char width. Round up?
+ NonVirtualSize = Context.toCharUnitsFromBits(getSizeInBits());
NonVirtualAlignment = Alignment;
// Lay out the virtual bases and add the primary virtual base offsets.
@@ -1211,8 +1232,8 @@ void RecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D) {
// We start laying out ivars not at the end of the superclass
// structure, but at the next byte following the last field.
- Size = Context.toBits(SL.getDataSize());
- DataSize = Size;
+ setSize(SL.getDataSize());
+ setDataSize(getSizeInBits());
}
InitializeLayout(D);
@@ -1270,20 +1291,20 @@ void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
UnfilledBitsInLastByte = 0;
uint64_t FieldOffset;
- uint64_t UnpaddedFieldOffset = DataSize - UnfilledBitsInLastByte;
+ uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastByte;
if (IsUnion) {
- DataSize = std::max(DataSize, FieldSize);
+ setDataSize(std::max(getDataSizeInBits(), FieldSize));
FieldOffset = 0;
} else {
// The bitfield is allocated starting at the next offset aligned appropriately
// for T', with length n bits.
- FieldOffset = llvm::RoundUpToAlignment(DataSize, TypeAlign);
+ FieldOffset = llvm::RoundUpToAlignment(getDataSizeInBits(), TypeAlign);
uint64_t NewSizeInBits = FieldOffset + FieldSize;
- DataSize = llvm::RoundUpToAlignment(NewSizeInBits, 8);
- UnfilledBitsInLastByte = DataSize - NewSizeInBits;
+ setDataSize(llvm::RoundUpToAlignment(NewSizeInBits, 8));
+ UnfilledBitsInLastByte = getDataSizeInBits() - NewSizeInBits;
}
// Place this field at the current location.
@@ -1293,7 +1314,7 @@ void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
TypeAlign, FieldPacked, D);
// Update the size.
- Size = std::max(Size, DataSize);
+ setSize(std::max(getSizeInBits(), getDataSizeInBits()));
// Remember max struct/class alignment.
UpdateAlignment(Context.toCharUnitsFromBits(TypeAlign));
@@ -1301,7 +1322,7 @@ void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
bool FieldPacked = Packed || D->hasAttr<PackedAttr>();
- uint64_t UnpaddedFieldOffset = DataSize - UnfilledBitsInLastByte;
+ uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastByte;
uint64_t FieldOffset = IsUnion ? 0 : UnpaddedFieldOffset;
uint64_t FieldSize = D->getBitWidth()->EvaluateAsInt(Context).getZExtValue();
@@ -1355,16 +1376,16 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
// Update DataSize to include the last byte containing (part of) the bitfield.
if (IsUnion) {
// FIXME: I think FieldSize should be TypeSize here.
- DataSize = std::max(DataSize, FieldSize);
+ setDataSize(std::max(getDataSizeInBits(), FieldSize));
} else {
uint64_t NewSizeInBits = FieldOffset + FieldSize;
- DataSize = llvm::RoundUpToAlignment(NewSizeInBits, 8);
- UnfilledBitsInLastByte = DataSize - NewSizeInBits;
+ setDataSize(llvm::RoundUpToAlignment(NewSizeInBits, 8));
+ UnfilledBitsInLastByte = getDataSizeInBits() - NewSizeInBits;
}
// Update the size.
- Size = std::max(Size, DataSize);
+ setSize(std::max(getSizeInBits(), getDataSizeInBits()));
// Remember max struct/class alignment.
UpdateAlignment(Context.toCharUnitsFromBits(FieldAlign),
@@ -1377,14 +1398,14 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) {
return;
}
- uint64_t UnpaddedFieldOffset = DataSize - UnfilledBitsInLastByte;
+ uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastByte;
// Reset the unfilled bits.
UnfilledBitsInLastByte = 0;
bool FieldPacked = Packed || D->hasAttr<PackedAttr>();
CharUnits FieldOffset =
- IsUnion ? CharUnits::Zero() : Context.toCharUnitsFromBits(DataSize);
+ IsUnion ? CharUnits::Zero() : getDataSize();
CharUnits FieldSize;
CharUnits FieldAlign;
@@ -1464,12 +1485,12 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) {
// Reserve space for this field.
uint64_t FieldSizeInBits = Context.toBits(FieldSize);
if (IsUnion)
- Size = std::max(Size, FieldSizeInBits);
+ setSize(std::max(getSizeInBits(), FieldSizeInBits));
else
- Size = Context.toBits(FieldOffset) + FieldSizeInBits;
+ setSize(Context.toBits(FieldOffset) + FieldSizeInBits);
// Update the data size.
- DataSize = Size;
+ setDataSize(getSizeInBits());
// Remember max struct/class alignment.
UpdateAlignment(FieldAlign, UnpackedFieldAlign);
@@ -1477,29 +1498,30 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) {
void RecordLayoutBuilder::FinishLayout(const NamedDecl *D) {
// In C++, records cannot be of size 0.
- if (Context.getLangOptions().CPlusPlus && Size == 0) {
+ if (Context.getLangOptions().CPlusPlus && getSizeInBits() == 0) {
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
// Compatibility with gcc requires a class (pod or non-pod)
// which is not empty but of size 0; such as having fields of
// array of zero-length, remains of Size 0
if (RD->isEmpty())
- Size = 8;
+ setSize(8);
}
else
- Size = 8;
+ setSize(8);
}
// Finally, round the size of the record up to the alignment of the
// record itself.
- uint64_t UnpaddedSize = Size - UnfilledBitsInLastByte;
+ uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastByte;
uint64_t UnpackedSize =
- llvm::RoundUpToAlignment(Size, Context.toBits(UnpackedAlignment));
- Size = llvm::RoundUpToAlignment(Size, Context.toBits(Alignment));
+ llvm::RoundUpToAlignment(getSizeInBits(),
+ Context.toBits(UnpackedAlignment));
+ setSize(llvm::RoundUpToAlignment(getSizeInBits(), Context.toBits(Alignment)));
unsigned CharBitNum = Context.Target.getCharWidth();
if (const RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
// Warn if padding was introduced to the struct/class/union.
- if (Size > UnpaddedSize) {
- unsigned PadSize = Size - UnpaddedSize;
+ if (getSizeInBits() > UnpaddedSize) {
+ unsigned PadSize = getSizeInBits() - UnpaddedSize;
bool InBits = true;
if (PadSize % CharBitNum == 0) {
PadSize = PadSize / CharBitNum;
@@ -1513,7 +1535,8 @@ void RecordLayoutBuilder::FinishLayout(const NamedDecl *D) {
// Warn if we packed it unnecessarily. If the alignment is 1 byte don't
// bother since there won't be alignment issues.
- if (Packed && UnpackedAlignment > CharUnits::One() && Size == UnpackedSize)
+ if (Packed && UnpackedAlignment > CharUnits::One() &&
+ getSizeInBits() == UnpackedSize)
Diag(D->getLocation(), diag::warn_unnecessary_packed)
<< Context.getTypeDeclType(RD);
}
diff --git a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp
index 7e73f02..8a80275 100644
--- a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp
@@ -218,6 +218,10 @@ unsigned AsmStmt::getNumPlusOperands() const {
Expr *AsmStmt::getInputExpr(unsigned i) {
return cast<Expr>(Exprs[i + NumOutputs]);
}
+void AsmStmt::setInputExpr(unsigned i, Expr *E) {
+ Exprs[i + NumOutputs] = E;
+}
+
/// getInputConstraint - Return the specified input constraint. Unlike output
/// constraints, these can be empty.
diff --git a/contrib/llvm/tools/clang/lib/AST/StmtDumper.cpp b/contrib/llvm/tools/clang/lib/AST/StmtDumper.cpp
index 846bd4c..5c7dbb3 100644
--- a/contrib/llvm/tools/clang/lib/AST/StmtDumper.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/StmtDumper.cpp
@@ -279,8 +279,8 @@ void StmtDumper::DumpDeclarator(Decl *D) {
// print using decl (e.g. "using std::string;")
const char *tn = UD->isTypeName() ? "typename " : "";
OS << '"' << UD->getDeclKindName() << tn;
- UD->getTargetNestedNameDecl()->print(OS,
- PrintingPolicy(UD->getASTContext().getLangOptions()));
+ UD->getQualifier()->print(OS,
+ PrintingPolicy(UD->getASTContext().getLangOptions()));
OS << ";\"";
} else if (LabelDecl *LD = dyn_cast<LabelDecl>(D)) {
OS << "label " << LD->getNameAsString();
diff --git a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp
index 5ab5f46..1764f4a 100644
--- a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp
@@ -24,8 +24,6 @@
#include "llvm/ADT/FoldingSet.h"
#include <algorithm>
#include <cctype>
-#include <iomanip>
-#include <sstream>
using namespace clang;
@@ -42,17 +40,11 @@ static void printIntegral(const TemplateArgument &TemplArg,
if (T->isBooleanType()) {
Out << (Val->getBoolValue() ? "true" : "false");
} else if (T->isCharType()) {
- char Ch = Val->getSExtValue();
- if (std::isprint(Ch)) {
- Out << "'";
- if (Ch == '\'' || Ch == '\\')
- Out << '\\';
- Out << Ch << "'";
- } else {
- std::ostringstream Str;
- Str << std::setw(2) << std::setfill('0') << std::hex << (int)Ch;
- Out << "'\\x" << Str.str() << "'";
- }
+ const unsigned char Ch = Val->getZExtValue();
+ const std::string Str(1, Ch);
+ Out << ((Ch == '\'') ? "'\\" : "'");
+ Out.write_escaped(Str, /*UseHexEscapes=*/ true);
+ Out << "'";
} else {
Out << Val->toString(10);
}
diff --git a/contrib/llvm/tools/clang/lib/Analysis/AnalysisContext.cpp b/contrib/llvm/tools/clang/lib/Analysis/AnalysisContext.cpp
index 5233d3b..62097ef 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/AnalysisContext.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/AnalysisContext.cpp
@@ -19,8 +19,10 @@
#include "clang/AST/StmtVisitor.h"
#include "clang/Analysis/Analyses/LiveVariables.h"
#include "clang/Analysis/Analyses/PseudoConstantAnalysis.h"
+#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
#include "clang/Analysis/AnalysisContext.h"
#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/CFGStmtMap.h"
#include "clang/Analysis/Support/BumpVector.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/Support/ErrorHandling.h"
@@ -86,6 +88,30 @@ CFG *AnalysisContext::getUnoptimizedCFG() {
return completeCFG;
}
+CFGStmtMap *AnalysisContext::getCFGStmtMap() {
+ if (cfgStmtMap)
+ return cfgStmtMap;
+
+ if (CFG *c = getCFG()) {
+ cfgStmtMap = CFGStmtMap::Build(c, &getParentMap());
+ return cfgStmtMap;
+ }
+
+ return 0;
+}
+
+CFGReachabilityAnalysis *AnalysisContext::getCFGReachablityAnalysis() {
+ if (CFA)
+ return CFA;
+
+ if (CFG *c = getCFG()) {
+ CFA = new CFGReachabilityAnalysis(*c);
+ return CFA;
+ }
+
+ return 0;
+}
+
void AnalysisContext::dumpCFG() {
getCFG()->dump(getASTContext().getLangOptions());
}
@@ -346,10 +372,12 @@ AnalysisContext::getReferencedBlockVars(const BlockDecl *BD) {
AnalysisContext::~AnalysisContext() {
delete cfg;
delete completeCFG;
+ delete cfgStmtMap;
delete liveness;
delete relaxedLiveness;
delete PM;
delete PCA;
+ delete CFA;
delete ReferencedBlockVars;
}
diff --git a/contrib/llvm/tools/clang/lib/Analysis/CFG.cpp b/contrib/llvm/tools/clang/lib/Analysis/CFG.cpp
index a0ec5fe..cc6e9c5 100644
--- a/contrib/llvm/tools/clang/lib/Analysis/CFG.cpp
+++ b/contrib/llvm/tools/clang/lib/Analysis/CFG.cpp
@@ -17,6 +17,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/PrettyPrinter.h"
+#include "clang/AST/CharUnits.h"
#include "llvm/Support/GraphWriter.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Format.h"
@@ -413,9 +414,16 @@ private:
Expr::EvalResult Result;
if (!S->isTypeDependent() && !S->isValueDependent() &&
- S->Evaluate(Result, *Context) && Result.Val.isInt())
- return Result.Val.getInt().getBoolValue();
-
+ S->Evaluate(Result, *Context)) {
+ if (Result.Val.isInt())
+ return Result.Val.getInt().getBoolValue();
+ if (Result.Val.isLValue()) {
+ Expr *e = Result.Val.getLValueBase();
+ const CharUnits &c = Result.Val.getLValueOffset();
+ if (!e && c.isZero())
+ return false;
+ }
+ }
return TryResult();
}
};
@@ -928,11 +936,13 @@ CFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) {
/// VisitChildren - Visit the children of a Stmt.
CFGBlock *CFGBuilder::VisitChildren(Stmt* Terminator) {
- CFGBlock *B = Block;
- for (Stmt::child_range I = Terminator->children(); I; ++I) {
- if (*I) B = Visit(*I);
- }
- return B;
+ CFGBlock *lastBlock = Block;
+ for (Stmt::child_range I = Terminator->children(); I; ++I)
+ if (Stmt *child = *I)
+ if (CFGBlock *b = Visit(child))
+ lastBlock = b;
+
+ return lastBlock;
}
CFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A,
@@ -1207,6 +1217,8 @@ CFGBlock *CFGBuilder::VisitConditionalOperator(AbstractConditionalOperator *C,
return 0;
Block = NULL;
}
+ else
+ LHSBlock = ConfluenceBlock;
// Create the block for the RHS expression.
Succ = ConfluenceBlock;
@@ -1219,23 +1231,23 @@ CFGBlock *CFGBuilder::VisitConditionalOperator(AbstractConditionalOperator *C,
// See if this is a known constant.
const TryResult& KnownVal = tryEvaluateBool(C->getCond());
- if (LHSBlock)
- addSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock);
+ addSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock);
addSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock);
Block->setTerminator(C);
Expr *condExpr = C->getCond();
- CFGBlock *result = 0;
-
- // Run the condition expression if it's not trivially expressed in
- // terms of the opaque value (or if there is no opaque value).
- if (condExpr != opaqueValue) result = addStmt(condExpr);
-
- // Before that, run the common subexpression if there was one.
- // At least one of this or the above will be run.
- if (opaqueValue) result = addStmt(BCO->getCommon());
+ if (opaqueValue) {
+ // Run the condition expression if it's not trivially expressed in
+ // terms of the opaque value (or if there is no opaque value).
+ if (condExpr != opaqueValue)
+ addStmt(condExpr);
- return result;
+ // Before that, run the common subexpression if there was one.
+ // At least one of this or the above will be run.
+ return addStmt(BCO->getCommon());
+ }
+
+ return addStmt(condExpr);
}
CFGBlock *CFGBuilder::VisitDeclStmt(DeclStmt *DS) {
@@ -1819,6 +1831,7 @@ CFGBlock* CFGBuilder::VisitWhileStmt(WhileStmt* W) {
if (badCFG)
return 0;
LoopSuccessor = Block;
+ Block = 0;
} else
LoopSuccessor = Succ;
diff --git a/contrib/llvm/tools/clang/lib/Analysis/CFGReachabilityAnalysis.cpp b/contrib/llvm/tools/clang/lib/Analysis/CFGReachabilityAnalysis.cpp
new file mode 100644
index 0000000..7786584
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Analysis/CFGReachabilityAnalysis.cpp
@@ -0,0 +1,76 @@
+//==- CFGReachabilityAnalysis.cpp - Basic reachability analysis --*- 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 a flow-sensitive, (mostly) path-insensitive reachability
+// analysis based on Clang's CFGs. Clients can query if a given basic block
+// is reachable within the CFG.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/SmallVector.h"
+#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
+#include "clang/Analysis/CFG.h"
+
+using namespace clang;
+
+CFGReachabilityAnalysis::CFGReachabilityAnalysis(const CFG &cfg)
+ : analyzed(cfg.getNumBlockIDs(), false) {}
+
+bool CFGReachabilityAnalysis::isReachable(const CFGBlock *Src,
+ const CFGBlock *Dst) {
+
+ const unsigned DstBlockID = Dst->getBlockID();
+
+ // If we haven't analyzed the destination node, run the analysis now
+ if (!analyzed[DstBlockID]) {
+ mapReachability(Dst);
+ analyzed[DstBlockID] = true;
+ }
+
+ // Return the cached result
+ return reachable[DstBlockID][Src->getBlockID()];
+}
+
+// Maps reachability to a common node by walking the predecessors of the
+// destination node.
+void CFGReachabilityAnalysis::mapReachability(const CFGBlock *Dst) {
+ llvm::SmallVector<const CFGBlock *, 11> worklist;
+ llvm::BitVector visited(analyzed.size());
+
+ ReachableSet &DstReachability = reachable[Dst->getBlockID()];
+ DstReachability.resize(analyzed.size(), false);
+
+ // Start searching from the destination node, since we commonly will perform
+ // multiple queries relating to a destination node.
+ worklist.push_back(Dst);
+ bool firstRun = true;
+
+ while (!worklist.empty()) {
+ const CFGBlock *block = worklist.back();
+ worklist.pop_back();
+
+ if (visited[block->getBlockID()])
+ continue;
+ visited[block->getBlockID()] = true;
+
+ // Update reachability information for this node -> Dst
+ if (!firstRun) {
+ // Don't insert Dst -> Dst unless it was a predecessor of itself
+ DstReachability[block->getBlockID()] = true;
+ }
+ else
+ firstRun = false;
+
+ // Add the predecessors to the worklist.
+ for (CFGBlock::const_pred_iterator i = block->pred_begin(),
+ e = block->pred_end(); i != e; ++i) {
+ worklist.push_back(*i);
+ }
+ }
+}
diff --git a/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp b/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp
index 8725e7f..553e4c9 100644
--- a/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp
@@ -288,14 +288,15 @@ const char *DiagnosticIDs::getDescription(unsigned DiagID) const {
/// the DiagnosticClient.
DiagnosticIDs::Level
DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, SourceLocation Loc,
- const Diagnostic &Diag) const {
+ const Diagnostic &Diag,
+ diag::Mapping *mapping) const {
// Handle custom diagnostics, which cannot be mapped.
if (DiagID >= diag::DIAG_UPPER_LIMIT)
return CustomDiagInfo->getLevel(DiagID);
unsigned DiagClass = getBuiltinDiagClass(DiagID);
assert(DiagClass != CLASS_NOTE && "Cannot get diagnostic level of a note!");
- return getDiagnosticLevel(DiagID, DiagClass, Loc, Diag);
+ return getDiagnosticLevel(DiagID, DiagClass, Loc, Diag, mapping);
}
/// \brief Based on the way the client configured the Diagnostic
@@ -307,7 +308,8 @@ DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, SourceLocation Loc,
DiagnosticIDs::Level
DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass,
SourceLocation Loc,
- const Diagnostic &Diag) const {
+ const Diagnostic &Diag,
+ diag::Mapping *mapping) const {
// Specific non-error diagnostics may be mapped to various levels from ignored
// to error. Errors can only be mapped to fatal.
DiagnosticIDs::Level Result = DiagnosticIDs::Fatal;
@@ -323,6 +325,9 @@ DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass,
MappingInfo = GetDefaultDiagMapping(DiagID);
Diag.setDiagnosticMappingInternal(DiagID, MappingInfo, State, false, false);
}
+
+ if (mapping)
+ *mapping = (diag::Mapping) (MappingInfo & 7);
switch (MappingInfo & 7) {
default: assert(0 && "Unknown mapping!");
diff --git a/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp b/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp
index 044c88d..e2783ba 100644
--- a/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp
@@ -823,6 +823,12 @@ unsigned SourceManager::getInstantiationColumnNumber(SourceLocation Loc,
return getColumnNumber(LocInfo.first, LocInfo.second, Invalid);
}
+unsigned SourceManager::getPresumedColumnNumber(SourceLocation Loc,
+ bool *Invalid) const {
+ if (isInvalid(Loc, Invalid)) return 0;
+ return getPresumedLoc(Loc).getColumn();
+}
+
static LLVM_ATTRIBUTE_NOINLINE void
ComputeLineNumbers(Diagnostic &Diag, ContentCache *FI,
llvm::BumpPtrAllocator &Alloc,
@@ -985,17 +991,22 @@ unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos,
return LineNo;
}
+unsigned SourceManager::getSpellingLineNumber(SourceLocation Loc,
+ bool *Invalid) const {
+ if (isInvalid(Loc, Invalid)) return 0;
+ std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(Loc);
+ return getLineNumber(LocInfo.first, LocInfo.second);
+}
unsigned SourceManager::getInstantiationLineNumber(SourceLocation Loc,
bool *Invalid) const {
if (isInvalid(Loc, Invalid)) return 0;
std::pair<FileID, unsigned> LocInfo = getDecomposedInstantiationLoc(Loc);
return getLineNumber(LocInfo.first, LocInfo.second);
}
-unsigned SourceManager::getSpellingLineNumber(SourceLocation Loc,
+unsigned SourceManager::getPresumedLineNumber(SourceLocation Loc,
bool *Invalid) const {
if (isInvalid(Loc, Invalid)) return 0;
- std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(Loc);
- return getLineNumber(LocInfo.first, LocInfo.second);
+ return getPresumedLoc(Loc).getLine();
}
/// getFileCharacteristic - return the file characteristic of the specified
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets.cpp
index a8198e4..55321f24 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets.cpp
@@ -152,6 +152,7 @@ public:
DarwinTargetInfo(const std::string& triple) :
OSTargetInfo<Target>(triple) {
this->TLSSupported = llvm::Triple(triple).getDarwinMajorNumber() > 10;
+ this->MCountName = "\01mcount";
}
virtual std::string isValidSectionSpecifier(llvm::StringRef SR) const {
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp
index a35648d..9587de2 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp
@@ -895,12 +895,9 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
QualType selfTy = getContext().VoidPtrTy;
IdentifierInfo *II = &CGM.getContext().Idents.get(".block_descriptor");
- // FIXME: this leaks, and we only need it very temporarily.
- ImplicitParamDecl *selfDecl =
- ImplicitParamDecl::Create(getContext(),
- const_cast<BlockDecl*>(blockDecl),
- SourceLocation(), II, selfTy);
- args.push_back(std::make_pair(selfDecl, selfTy));
+ ImplicitParamDecl selfDecl(const_cast<BlockDecl*>(blockDecl),
+ SourceLocation(), II, selfTy);
+ args.push_back(std::make_pair(&selfDecl, selfTy));
// Now add the rest of the parameters.
for (BlockDecl::param_const_iterator i = blockDecl->param_begin(),
@@ -928,12 +925,11 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
blockInfo.getBlockExpr()->getBody()->getLocEnd());
CurFuncDecl = outerFnDecl; // StartFunction sets this to blockDecl
- // Okay. Undo some of what StartFunction did. We really don't need
- // an alloca for the block address; in theory we could remove it,
- // but that might do unpleasant things to debug info.
- llvm::AllocaInst *blockAddrAlloca
- = cast<llvm::AllocaInst>(LocalDeclMap[selfDecl]);
- llvm::Value *blockAddr = Builder.CreateLoad(blockAddrAlloca);
+ // Okay. Undo some of what StartFunction did.
+
+ // Pull the 'self' reference out of the local decl map.
+ llvm::Value *blockAddr = LocalDeclMap[&selfDecl];
+ LocalDeclMap.erase(&selfDecl);
BlockPointer = Builder.CreateBitCast(blockAddr,
blockInfo.StructureType->getPointerTo(),
"block");
@@ -1010,7 +1006,7 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
continue;
}
- DI->EmitDeclareOfBlockDeclRefVariable(variable, blockAddrAlloca,
+ DI->EmitDeclareOfBlockDeclRefVariable(variable, BlockPointer,
Builder, blockInfo);
}
}
@@ -1376,10 +1372,9 @@ llvm::Constant *CodeGenModule::BuildbyrefCopyHelper(const llvm::Type *T,
BlockFieldFlags flags,
unsigned align,
const VarDecl *var) {
- // All alignments below that of pointer alignment collapse down to just
- // pointer alignment, as we always have at least that much alignment to begin
- // with.
- align /= unsigned(getTarget().getPointerAlign(0) / 8);
+ // All alignments below pointer alignment are bumped up, as we
+ // always have at least that much alignment to begin with.
+ if (align < PointerAlignInBytes) align = PointerAlignInBytes;
// As an optimization, we only generate a single function of each kind we
// might need. We need a different one for each alignment and for each
@@ -1396,10 +1391,9 @@ llvm::Constant *CodeGenModule::BuildbyrefDestroyHelper(const llvm::Type *T,
BlockFieldFlags flags,
unsigned align,
const VarDecl *var) {
- // All alignments below that of pointer alignment collpase down to just
- // pointer alignment, as we always have at least that much alignment to begin
- // with.
- align /= unsigned(getTarget().getPointerAlign(0) / 8);
+ // All alignments below pointer alignment are bumped up, as we
+ // always have at least that much alignment to begin with.
+ if (align < PointerAlignInBytes) align = PointerAlignInBytes;
// As an optimization, we only generate a single function of each kind we
// might need. We need a different one for each alignment and for each
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.h b/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.h
index bee729d..0bc8bca 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.h
@@ -177,7 +177,6 @@ public:
const BlockExpr *Block;
CharUnits BlockSize;
CharUnits BlockAlign;
- llvm::SmallVector<const Expr*, 8> BlockLayout;
const Capture &getCapture(const VarDecl *var) const {
llvm::DenseMap<const VarDecl*, Capture>::const_iterator
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp
index 8e88beb..cd28bbe 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp
@@ -17,6 +17,7 @@
#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/StmtCXX.h"
+#include "clang/Frontend/CodeGenOptions.h"
using namespace clang;
using namespace CodeGen;
@@ -1140,6 +1141,16 @@ CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
llvm::Value *This,
CallExpr::const_arg_iterator ArgBeg,
CallExpr::const_arg_iterator ArgEnd) {
+
+ CGDebugInfo *DI = getDebugInfo();
+ if (DI && CGM.getCodeGenOpts().LimitDebugInfo) {
+ // If debug info for this class has been emitted then this is the right time
+ // to do so.
+ const CXXRecordDecl *Parent = D->getParent();
+ DI->getOrCreateRecordType(CGM.getContext().getTypeDeclType(Parent),
+ Parent->getLocation());
+ }
+
if (D->isTrivial()) {
if (ArgBeg == ArgEnd) {
// Trivial default constructor, no codegen required.
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp
index 374ede8..1d7901a 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp
@@ -876,7 +876,7 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
///
/// As a side-effect, this method clears the insertion point.
void CodeGenFunction::EmitBranchThroughCleanup(JumpDest Dest) {
- assert(Dest.getScopeDepth().encloses(EHStack.getInnermostNormalCleanup())
+ assert(Dest.getScopeDepth().encloses(EHStack.stable_begin())
&& "stale jump destination");
if (!HaveInsertPoint())
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp
index 469b460..dfd9f56 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -156,14 +156,14 @@ CGDebugInfo::getClassName(RecordDecl *RD) {
llvm::DIFile CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
if (!Loc.isValid())
// If Location is not valid then use main input file.
- return DBuilder.CreateFile(TheCU.getFilename(), TheCU.getDirectory());
+ return DBuilder.createFile(TheCU.getFilename(), TheCU.getDirectory());
SourceManager &SM = CGM.getContext().getSourceManager();
PresumedLoc PLoc = SM.getPresumedLoc(Loc);
if (PLoc.isInvalid() || llvm::StringRef(PLoc.getFilename()).empty())
// If the location is not valid then use main input file.
- return DBuilder.CreateFile(TheCU.getFilename(), TheCU.getDirectory());
+ return DBuilder.createFile(TheCU.getFilename(), TheCU.getDirectory());
// Cache the results.
const char *fname = PLoc.getFilename();
@@ -176,7 +176,7 @@ llvm::DIFile CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
return llvm::DIFile(cast<llvm::MDNode>(it->second));
}
- llvm::DIFile F = DBuilder.CreateFile(PLoc.getFilename(), getCurrentDirname());
+ llvm::DIFile F = DBuilder.createFile(PLoc.getFilename(), getCurrentDirname());
DIFileCache[fname] = F;
return F;
@@ -185,7 +185,7 @@ llvm::DIFile CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
/// getOrCreateMainFile - Get the file info for main compile unit.
llvm::DIFile CGDebugInfo::getOrCreateMainFile() {
- return DBuilder.CreateFile(TheCU.getFilename(), TheCU.getDirectory());
+ return DBuilder.createFile(TheCU.getFilename(), TheCU.getDirectory());
}
/// getLineNumber - Get line number for the location. If location is invalid
@@ -264,7 +264,7 @@ void CGDebugInfo::CreateCompileUnit() {
RuntimeVers = LO.ObjCNonFragileABI ? 2 : 1;
// Create new compile unit.
- DBuilder.CreateCompileUnit(
+ DBuilder.createCompileUnit(
LangTag, Filename, getCurrentDirname(),
Producer,
LO.Optimize, CGM.getCodeGenOpts().DwarfDebugFlags, RuntimeVers);
@@ -282,7 +282,7 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) {
case BuiltinType::Void:
return llvm::DIType();
case BuiltinType::ObjCClass:
- return DBuilder.CreateStructType(TheCU, "objc_class",
+ return DBuilder.createStructType(TheCU, "objc_class",
getOrCreateMainFile(), 0, 0, 0,
llvm::DIDescriptor::FlagFwdDecl,
llvm::DIArray());
@@ -293,28 +293,28 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) {
// } *id;
llvm::DIType OCTy =
- DBuilder.CreateStructType(TheCU, "objc_class",
+ DBuilder.createStructType(TheCU, "objc_class",
getOrCreateMainFile(), 0, 0, 0,
llvm::DIDescriptor::FlagFwdDecl,
llvm::DIArray());
unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
- llvm::DIType ISATy = DBuilder.CreatePointerType(OCTy, Size);
+ llvm::DIType ISATy = DBuilder.createPointerType(OCTy, Size);
llvm::SmallVector<llvm::Value *, 16> EltTys;
llvm::DIType FieldTy =
- DBuilder.CreateMemberType("isa", getOrCreateMainFile(),
+ DBuilder.createMemberType("isa", getOrCreateMainFile(),
0,Size, 0, 0, 0, ISATy);
EltTys.push_back(FieldTy);
llvm::DIArray Elements =
- DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size());
+ DBuilder.getOrCreateArray(EltTys.data(), EltTys.size());
- return DBuilder.CreateStructType(TheCU, "objc_object",
+ return DBuilder.createStructType(TheCU, "objc_object",
getOrCreateMainFile(),
0, 0, 0, 0, Elements);
}
case BuiltinType::ObjCSel: {
- return DBuilder.CreateStructType(TheCU, "objc_selector",
+ return DBuilder.createStructType(TheCU, "objc_selector",
getOrCreateMainFile(), 0, 0, 0,
llvm::DIDescriptor::FlagFwdDecl,
llvm::DIArray());
@@ -350,7 +350,7 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) {
uint64_t Size = CGM.getContext().getTypeSize(BT);
uint64_t Align = CGM.getContext().getTypeAlign(BT);
llvm::DIType DbgTy =
- DBuilder.CreateBasicType(BTName, Size, Align, Encoding);
+ DBuilder.createBasicType(BTName, Size, Align, Encoding);
return DbgTy;
}
@@ -363,7 +363,7 @@ llvm::DIType CGDebugInfo::CreateType(const ComplexType *Ty) {
uint64_t Size = CGM.getContext().getTypeSize(Ty);
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
llvm::DIType DbgTy =
- DBuilder.CreateBasicType("complex", Size, Align, Encoding);
+ DBuilder.createBasicType("complex", Size, Align, Encoding);
return DbgTy;
}
@@ -399,7 +399,7 @@ llvm::DIType CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DIFile Unit) {
// No need to fill in the Name, Line, Size, Alignment, Offset in case of
// CVR derived types.
- llvm::DIType DbgTy = DBuilder.CreateQualifiedType(Tag, FromTy);
+ llvm::DIType DbgTy = DBuilder.createQualifiedType(Tag, FromTy);
return DbgTy;
}
@@ -430,19 +430,19 @@ llvm::DIType CGDebugInfo::CreatePointeeType(QualType PointeeTy,
llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation());
unsigned Line = getLineNumber(RD->getLocation());
llvm::DIDescriptor FDContext =
- getContextDescriptor(dyn_cast<Decl>(RD->getDeclContext()));
+ getContextDescriptor(cast<Decl>(RD->getDeclContext()));
if (RD->isStruct())
- return DBuilder.CreateStructType(FDContext, RD->getName(), DefUnit,
+ return DBuilder.createStructType(FDContext, RD->getName(), DefUnit,
Line, 0, 0, llvm::DIType::FlagFwdDecl,
llvm::DIArray());
else if (RD->isUnion())
- return DBuilder.CreateUnionType(FDContext, RD->getName(), DefUnit,
+ return DBuilder.createUnionType(FDContext, RD->getName(), DefUnit,
Line, 0, 0, llvm::DIType::FlagFwdDecl,
llvm::DIArray());
else {
assert(RD->isClass() && "Unknown RecordType!");
- return DBuilder.CreateClassType(FDContext, RD->getName(), DefUnit,
+ return DBuilder.createClassType(FDContext, RD->getName(), DefUnit,
Line, 0, 0, 0, llvm::DIType::FlagFwdDecl,
llvm::DIType(), llvm::DIArray());
}
@@ -457,7 +457,7 @@ llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag,
llvm::DIFile Unit) {
if (Tag == llvm::dwarf::DW_TAG_reference_type)
- return DBuilder.CreateReferenceType(CreatePointeeType(PointeeTy, Unit));
+ return DBuilder.createReferenceType(CreatePointeeType(PointeeTy, Unit));
// Bit size, align and offset of the type.
// Size is always the size of a pointer. We can't use getTypeSize here
@@ -467,7 +467,7 @@ llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag,
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
return
- DBuilder.CreatePointerType(CreatePointeeType(PointeeTy, Unit), Size, Align);
+ DBuilder.createPointerType(CreatePointeeType(PointeeTy, Unit), Size, Align);
}
llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty,
@@ -488,20 +488,20 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty,
EltTys.push_back(CreateMemberType(Unit, FType, "reserved", &FieldOffset));
EltTys.push_back(CreateMemberType(Unit, FType, "Size", &FieldOffset));
- Elements = DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size());
+ Elements = DBuilder.getOrCreateArray(EltTys.data(), EltTys.size());
EltTys.clear();
unsigned Flags = llvm::DIDescriptor::FlagAppleBlock;
unsigned LineNo = getLineNumber(CurLoc);
- EltTy = DBuilder.CreateStructType(Unit, "__block_descriptor",
+ EltTy = DBuilder.createStructType(Unit, "__block_descriptor",
Unit, LineNo, FieldOffset, 0,
Flags, Elements);
// Bit size, align and offset of the type.
uint64_t Size = CGM.getContext().getTypeSize(Ty);
- DescTy = DBuilder.CreatePointerType(EltTy, Size);
+ DescTy = DBuilder.createPointerType(EltTy, Size);
FieldOffset = 0;
FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
@@ -516,20 +516,20 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty,
FieldTy = DescTy;
FieldSize = CGM.getContext().getTypeSize(Ty);
FieldAlign = CGM.getContext().getTypeAlign(Ty);
- FieldTy = DBuilder.CreateMemberType("__descriptor", Unit,
+ FieldTy = DBuilder.createMemberType("__descriptor", Unit,
LineNo, FieldSize, FieldAlign,
FieldOffset, 0, FieldTy);
EltTys.push_back(FieldTy);
FieldOffset += FieldSize;
- Elements = DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size());
+ Elements = DBuilder.getOrCreateArray(EltTys.data(), EltTys.size());
- EltTy = DBuilder.CreateStructType(Unit, "__block_literal_generic",
+ EltTy = DBuilder.createStructType(Unit, "__block_literal_generic",
Unit, LineNo, FieldOffset, 0,
Flags, Elements);
BlockLiteralGenericSet = true;
- BlockLiteralGeneric = DBuilder.CreatePointerType(EltTy, Size);
+ BlockLiteralGeneric = DBuilder.createPointerType(EltTy, Size);
return BlockLiteralGeneric;
}
@@ -543,7 +543,7 @@ llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty,
// We don't set size information, but do specify where the typedef was
// declared.
unsigned Line = getLineNumber(Ty->getDecl()->getLocation());
- llvm::DIType DbgTy = DBuilder.CreateTypedef(Src, Ty->getDecl()->getName(),
+ llvm::DIType DbgTy = DBuilder.createTypedef(Src, Ty->getDecl()->getName(),
Unit, Line);
return DbgTy;
}
@@ -558,66 +558,76 @@ llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty,
// Set up remainder of arguments if there is a prototype.
// FIXME: IF NOT, HOW IS THIS REPRESENTED? llvm-gcc doesn't represent '...'!
if (isa<FunctionNoProtoType>(Ty))
- EltTys.push_back(DBuilder.CreateUnspecifiedParameter());
+ EltTys.push_back(DBuilder.createUnspecifiedParameter());
else if (const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(Ty)) {
for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
EltTys.push_back(getOrCreateType(FTP->getArgType(i), Unit));
}
llvm::DIArray EltTypeArray =
- DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size());
+ DBuilder.getOrCreateArray(EltTys.data(), EltTys.size());
- llvm::DIType DbgTy = DBuilder.CreateSubroutineType(Unit, EltTypeArray);
+ llvm::DIType DbgTy = DBuilder.createSubroutineType(Unit, EltTypeArray);
return DbgTy;
}
+llvm::DIType CGDebugInfo::createFieldType(llvm::StringRef name,
+ QualType type,
+ Expr *bitWidth,
+ SourceLocation loc,
+ AccessSpecifier AS,
+ uint64_t offsetInBits,
+ llvm::DIFile tunit) {
+ llvm::DIType debugType = getOrCreateType(type, tunit);
+
+ // Get the location for the field.
+ llvm::DIFile file = getOrCreateFile(loc);
+ unsigned line = getLineNumber(loc);
+
+ uint64_t sizeInBits = 0;
+ unsigned alignInBits = 0;
+ if (!type->isIncompleteArrayType()) {
+ llvm::tie(sizeInBits, alignInBits) = CGM.getContext().getTypeInfo(type);
+
+ if (bitWidth)
+ sizeInBits = bitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue();
+ }
+
+ unsigned flags = 0;
+ if (AS == clang::AS_private)
+ flags |= llvm::DIDescriptor::FlagPrivate;
+ else if (AS == clang::AS_protected)
+ flags |= llvm::DIDescriptor::FlagProtected;
+
+ return DBuilder.createMemberType(name, file, line, sizeInBits, alignInBits,
+ offsetInBits, flags, debugType);
+}
+
/// CollectRecordFields - A helper function to collect debug info for
/// record fields. This is used while creating debug info entry for a Record.
void CGDebugInfo::
-CollectRecordFields(const RecordDecl *RD, llvm::DIFile Unit,
- llvm::SmallVectorImpl<llvm::Value *> &EltTys) {
- unsigned FieldNo = 0;
- const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
- for (RecordDecl::field_iterator I = RD->field_begin(),
- E = RD->field_end();
- I != E; ++I, ++FieldNo) {
- FieldDecl *Field = *I;
- llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
- llvm::StringRef FieldName = Field->getName();
-
- // Ignore unnamed fields. Do not ignore unnamed records.
- if (FieldName.empty() && !isa<RecordType>(Field->getType()))
+CollectRecordFields(const RecordDecl *record, llvm::DIFile tunit,
+ llvm::SmallVectorImpl<llvm::Value *> &elements) {
+ unsigned fieldNo = 0;
+ const ASTRecordLayout &layout = CGM.getContext().getASTRecordLayout(record);
+ for (RecordDecl::field_iterator I = record->field_begin(),
+ E = record->field_end();
+ I != E; ++I, ++fieldNo) {
+ FieldDecl *field = *I;
+
+ llvm::StringRef name = field->getName();
+ QualType type = field->getType();
+
+ // Ignore unnamed fields unless they're anonymous structs/unions.
+ if (name.empty() && !type->isRecordType())
continue;
- // Get the location for the field.
- llvm::DIFile FieldDefUnit = getOrCreateFile(Field->getLocation());
- unsigned FieldLine = getLineNumber(Field->getLocation());
- QualType FType = Field->getType();
- uint64_t FieldSize = 0;
- unsigned FieldAlign = 0;
- if (!FType->isIncompleteArrayType()) {
-
- // Bit size, align and offset of the type.
- FieldSize = CGM.getContext().getTypeSize(FType);
- Expr *BitWidth = Field->getBitWidth();
- if (BitWidth)
- FieldSize = BitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue();
- FieldAlign = CGM.getContext().getTypeAlign(FType);
- }
+ llvm::DIType fieldType
+ = createFieldType(name, type, field->getBitWidth(),
+ field->getLocation(), field->getAccess(),
+ layout.getFieldOffset(fieldNo), tunit);
- uint64_t FieldOffset = RL.getFieldOffset(FieldNo);
-
- unsigned Flags = 0;
- AccessSpecifier Access = I->getAccess();
- if (Access == clang::AS_private)
- Flags |= llvm::DIDescriptor::FlagPrivate;
- else if (Access == clang::AS_protected)
- Flags |= llvm::DIDescriptor::FlagProtected;
-
- FieldTy = DBuilder.CreateMemberType(FieldName, FieldDefUnit,
- FieldLine, FieldSize, FieldAlign,
- FieldOffset, Flags, FieldTy);
- EltTys.push_back(FieldTy);
+ elements.push_back(fieldType);
}
}
@@ -649,7 +659,7 @@ CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method,
QualType ThisPtr =
Context.getPointerType(Context.getTagDeclType(Method->getParent()));
llvm::DIType ThisPtrType =
- DBuilder.CreateArtificialType(getOrCreateType(ThisPtr, Unit));
+ DBuilder.createArtificialType(getOrCreateType(ThisPtr, Unit));
TypeCache[ThisPtr.getAsOpaquePtr()] = ThisPtrType;
Elts.push_back(ThisPtrType);
@@ -660,9 +670,9 @@ CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method,
Elts.push_back(Args.getElement(i));
llvm::DIArray EltTypeArray =
- DBuilder.GetOrCreateArray(Elts.data(), Elts.size());
+ DBuilder.getOrCreateArray(Elts.data(), Elts.size());
- return DBuilder.CreateSubroutineType(Unit, EltTypeArray);
+ return DBuilder.createSubroutineType(Unit, EltTypeArray);
}
/// isFunctionLocalClass - Return true if CXXRecordDecl is defined
@@ -736,7 +746,7 @@ CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method,
Flags |= llvm::DIDescriptor::FlagPrototyped;
llvm::DISubprogram SP =
- DBuilder.CreateMethod(RecordTy , MethodName, MethodLinkageName,
+ DBuilder.createMethod(RecordTy , MethodName, MethodLinkageName,
MethodDefUnit, MethodLine,
MethodTy, /*isLocalToUnit=*/false,
/* isDefinition=*/ false,
@@ -780,7 +790,7 @@ CollectCXXFriends(const CXXRecordDecl *RD, llvm::DIFile Unit,
for (CXXRecordDecl::friend_iterator BI = RD->friend_begin(),
BE = RD->friend_end(); BI != BE; ++BI) {
if (TypeSourceInfo *TInfo = (*BI)->getFriendType())
- EltTys.push_back(DBuilder.CreateFriend(RecordTy,
+ EltTys.push_back(DBuilder.createFriend(RecordTy,
getOrCreateType(TInfo->getType(),
Unit)));
}
@@ -818,7 +828,7 @@ CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile Unit,
BFlags |= llvm::DIDescriptor::FlagProtected;
llvm::DIType DTy =
- DBuilder.CreateInheritance(RecordTy,
+ DBuilder.createInheritance(RecordTy,
getOrCreateType(BI->getType(), Unit),
BaseOffset, BFlags);
EltTys.push_back(DTy);
@@ -834,12 +844,12 @@ llvm::DIType CGDebugInfo::getOrCreateVTablePtrType(llvm::DIFile Unit) {
/* Function type */
llvm::Value *STy = getOrCreateType(Context.IntTy, Unit);
- llvm::DIArray SElements = DBuilder.GetOrCreateArray(&STy, 1);
- llvm::DIType SubTy = DBuilder.CreateSubroutineType(Unit, SElements);
+ llvm::DIArray SElements = DBuilder.getOrCreateArray(&STy, 1);
+ llvm::DIType SubTy = DBuilder.createSubroutineType(Unit, SElements);
unsigned Size = Context.getTypeSize(Context.VoidPtrTy);
- llvm::DIType vtbl_ptr_type = DBuilder.CreatePointerType(SubTy, Size, 0,
+ llvm::DIType vtbl_ptr_type = DBuilder.createPointerType(SubTy, Size, 0,
"__vtbl_ptr_type");
- VTablePtrType = DBuilder.CreatePointerType(vtbl_ptr_type, Size);
+ VTablePtrType = DBuilder.createPointerType(vtbl_ptr_type, Size);
return VTablePtrType;
}
@@ -872,7 +882,7 @@ CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile Unit,
unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
llvm::DIType VPTR
- = DBuilder.CreateMemberType(getVTableName(RD), Unit,
+ = DBuilder.createMemberType(getVTableName(RD), Unit,
0, Size, 0, 0, 0,
getOrCreateVTablePtrType(Unit));
EltTys.push_back(VPTR);
@@ -882,7 +892,7 @@ CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile Unit,
llvm::DIType CGDebugInfo::getOrCreateRecordType(QualType RTy,
SourceLocation Loc) {
llvm::DIType T = getOrCreateType(RTy, getOrCreateFile(Loc));
- DBuilder.RetainType(T);
+ DBuilder.retainType(T);
return T;
}
@@ -902,13 +912,13 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
// may refer to the forward decl if the struct is recursive) and replace all
// uses of the forward declaration with the final definition.
llvm::DIDescriptor FDContext =
- getContextDescriptor(dyn_cast<Decl>(RD->getDeclContext()));
+ getContextDescriptor(cast<Decl>(RD->getDeclContext()));
// If this is just a forward declaration, construct an appropriately
// marked node and just return it.
if (!RD->getDefinition()) {
llvm::DIType FwdDecl =
- DBuilder.CreateStructType(FDContext, RD->getName(),
+ DBuilder.createStructType(FDContext, RD->getName(),
DefUnit, Line, 0, 0,
llvm::DIDescriptor::FlagFwdDecl,
llvm::DIArray());
@@ -916,7 +926,7 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
return FwdDecl;
}
- llvm::DIType FwdDecl = DBuilder.CreateTemporaryType(DefUnit);
+ llvm::DIType FwdDecl = DBuilder.createTemporaryType(DefUnit);
llvm::MDNode *MN = FwdDecl;
llvm::TrackingVH<llvm::MDNode> FwdDeclNode = MN;
@@ -952,7 +962,7 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
llvm::DIType VTy = getOrCreateType(V->getType(), VUnit);
// Do not use DIGlobalVariable for enums.
if (VTy.getTag() != llvm::dwarf::DW_TAG_enumeration_type) {
- DBuilder.CreateStaticVariable(FwdDecl, VName, VName, VUnit,
+ DBuilder.createStaticVariable(FwdDecl, VName, VName, VUnit,
getLineNumber(V->getLocation()),
VTy, true, CI);
}
@@ -973,13 +983,13 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
if (TA.getKind() == TemplateArgument::Type) {
llvm::DIType TTy = getOrCreateType(TA.getAsType(), Unit);
llvm::DITemplateTypeParameter TTP =
- DBuilder.CreateTemplateTypeParameter(TheCU, TTy.getName(), TTy);
+ DBuilder.createTemplateTypeParameter(TheCU, TTy.getName(), TTy);
TemplateParams.push_back(TTP);
} else if (TA.getKind() == TemplateArgument::Integral) {
llvm::DIType TTy = getOrCreateType(TA.getIntegralType(), Unit);
// FIXME: Get parameter name, instead of parameter type name.
llvm::DITemplateValueParameter TVP =
- DBuilder.CreateTemplateValueParameter(TheCU, TTy.getName(), TTy,
+ DBuilder.createTemplateValueParameter(TheCU, TTy.getName(), TTy,
TA.getAsIntegral()->getZExtValue());
TemplateParams.push_back(TVP);
}
@@ -994,19 +1004,19 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
RegionMap.erase(RI);
llvm::DIDescriptor RDContext =
- getContextDescriptor(dyn_cast<Decl>(RD->getDeclContext()));
+ getContextDescriptor(cast<Decl>(RD->getDeclContext()));
llvm::StringRef RDName = RD->getName();
uint64_t Size = CGM.getContext().getTypeSize(Ty);
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
llvm::DIArray Elements =
- DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size());
+ DBuilder.getOrCreateArray(EltTys.data(), EltTys.size());
llvm::MDNode *RealDecl = NULL;
if (RD->isStruct())
- RealDecl = DBuilder.CreateStructType(RDContext, RDName, DefUnit, Line,
+ RealDecl = DBuilder.createStructType(RDContext, RDName, DefUnit, Line,
Size, Align, 0, Elements);
else if (RD->isUnion())
- RealDecl = DBuilder.CreateUnionType(RDContext, RDName, DefUnit, Line,
+ RealDecl = DBuilder.createUnionType(RDContext, RDName, DefUnit, Line,
Size, Align, 0, Elements);
else {
assert(RD->isClass() && "Unknown RecordType!");
@@ -1030,8 +1040,8 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
else if (CXXDecl->isDynamicClass())
ContainingType = FwdDecl;
llvm::DIArray TParamsArray =
- DBuilder.GetOrCreateArray(TemplateParams.data(), TemplateParams.size());
- RealDecl = DBuilder.CreateClassType(RDContext, RDName, DefUnit, Line,
+ DBuilder.getOrCreateArray(TemplateParams.data(), TemplateParams.size());
+ RealDecl = DBuilder.createClassType(RDContext, RDName, DefUnit, Line,
Size, Align, 0, 0, llvm::DIType(),
Elements, ContainingType,
TParamsArray);
@@ -1067,7 +1077,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
// debug type.
if (ID->isForwardDecl()) {
llvm::DIType FwdDecl =
- DBuilder.CreateStructType(Unit, ID->getName(),
+ DBuilder.createStructType(Unit, ID->getName(),
DefUnit, Line, 0, 0, 0,
llvm::DIArray(), RuntimeLang);
return FwdDecl;
@@ -1079,7 +1089,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
// its members. Finally, we create a descriptor for the complete type (which
// may refer to the forward decl if the struct is recursive) and replace all
// uses of the forward declaration with the final definition.
- llvm::DIType FwdDecl = DBuilder.CreateTemporaryType(DefUnit);
+ llvm::DIType FwdDecl = DBuilder.createTemporaryType(DefUnit);
llvm::MDNode *MN = FwdDecl;
llvm::TrackingVH<llvm::MDNode> FwdDeclNode = MN;
@@ -1101,7 +1111,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
return llvm::DIType();
llvm::DIType InhTag =
- DBuilder.CreateInheritance(FwdDecl, SClassTy, 0, 0);
+ DBuilder.createInheritance(FwdDecl, SClassTy, 0, 0);
EltTys.push_back(InhTag);
}
@@ -1146,14 +1156,14 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
else if (Field->getAccessControl() == ObjCIvarDecl::Private)
Flags = llvm::DIDescriptor::FlagPrivate;
- FieldTy = DBuilder.CreateMemberType(FieldName, FieldDefUnit,
+ FieldTy = DBuilder.createMemberType(FieldName, FieldDefUnit,
FieldLine, FieldSize, FieldAlign,
FieldOffset, Flags, FieldTy);
EltTys.push_back(FieldTy);
}
llvm::DIArray Elements =
- DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size());
+ DBuilder.getOrCreateArray(EltTys.data(), EltTys.size());
RegionStack.pop_back();
llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator RI =
@@ -1166,7 +1176,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
llvm::DIType RealDecl =
- DBuilder.CreateStructType(Unit, ID->getName(), DefUnit,
+ DBuilder.createStructType(Unit, ID->getName(), DefUnit,
Line, Size, Align, 0,
Elements, RuntimeLang);
@@ -1194,14 +1204,14 @@ llvm::DIType CGDebugInfo::CreateType(const VectorType *Ty,
if (NumElems > 0)
--NumElems;
- llvm::Value *Subscript = DBuilder.GetOrCreateSubrange(0, NumElems);
- llvm::DIArray SubscriptArray = DBuilder.GetOrCreateArray(&Subscript, 1);
+ llvm::Value *Subscript = DBuilder.getOrCreateSubrange(0, NumElems);
+ llvm::DIArray SubscriptArray = DBuilder.getOrCreateArray(&Subscript, 1);
uint64_t Size = CGM.getContext().getTypeSize(Ty);
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
return
- DBuilder.CreateVectorType(Size, Align, ElementTy, SubscriptArray);
+ DBuilder.createVectorType(Size, Align, ElementTy, SubscriptArray);
}
llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty,
@@ -1238,16 +1248,16 @@ llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty,
if (CAT->getSize().getZExtValue())
Upper = CAT->getSize().getZExtValue() - 1;
// FIXME: Verify this is right for VLAs.
- Subscripts.push_back(DBuilder.GetOrCreateSubrange(0, Upper));
+ Subscripts.push_back(DBuilder.getOrCreateSubrange(0, Upper));
EltTy = Ty->getElementType();
}
}
llvm::DIArray SubscriptArray =
- DBuilder.GetOrCreateArray(Subscripts.data(), Subscripts.size());
+ DBuilder.getOrCreateArray(Subscripts.data(), Subscripts.size());
llvm::DIType DbgTy =
- DBuilder.CreateArrayType(Size, Align, getOrCreateType(EltTy, Unit),
+ DBuilder.createArrayType(Size, Align, getOrCreateType(EltTy, Unit),
SubscriptArray);
return DbgTy;
}
@@ -1283,21 +1293,21 @@ llvm::DIType CGDebugInfo::CreateType(const MemberPointerType *Ty,
// FIXME: This should probably be a function type instead.
ElementTypes[0] =
- DBuilder.CreateMemberType("ptr", U, 0,
+ DBuilder.createMemberType("ptr", U, 0,
Info.first, Info.second, FieldOffset, 0,
PointerDiffDITy);
FieldOffset += Info.first;
ElementTypes[1] =
- DBuilder.CreateMemberType("ptr", U, 0,
+ DBuilder.createMemberType("ptr", U, 0,
Info.first, Info.second, FieldOffset, 0,
PointerDiffDITy);
llvm::DIArray Elements =
- DBuilder.GetOrCreateArray(&ElementTypes[0],
+ DBuilder.getOrCreateArray(&ElementTypes[0],
llvm::array_lengthof(ElementTypes));
- return DBuilder.CreateStructType(U, llvm::StringRef("test"),
+ return DBuilder.createStructType(U, llvm::StringRef("test"),
U, 0, FieldOffset,
0, 0, Elements);
}
@@ -1312,13 +1322,13 @@ llvm::DIType CGDebugInfo::CreateEnumType(const EnumDecl *ED) {
Enum = ED->enumerator_begin(), EnumEnd = ED->enumerator_end();
Enum != EnumEnd; ++Enum) {
Enumerators.push_back(
- DBuilder.CreateEnumerator(Enum->getName(),
+ DBuilder.createEnumerator(Enum->getName(),
Enum->getInitVal().getZExtValue()));
}
// Return a CompositeType for the enum itself.
llvm::DIArray EltArray =
- DBuilder.GetOrCreateArray(Enumerators.data(), Enumerators.size());
+ DBuilder.getOrCreateArray(Enumerators.data(), Enumerators.size());
llvm::DIFile DefUnit = getOrCreateFile(ED->getLocation());
unsigned Line = getLineNumber(ED->getLocation());
@@ -1329,9 +1339,9 @@ llvm::DIType CGDebugInfo::CreateEnumType(const EnumDecl *ED) {
Align = CGM.getContext().getTypeAlign(ED->getTypeForDecl());
}
llvm::DIDescriptor EnumContext =
- getContextDescriptor(dyn_cast<Decl>(ED->getDeclContext()));
+ getContextDescriptor(cast<Decl>(ED->getDeclContext()));
llvm::DIType DbgTy =
- DBuilder.CreateEnumerationType(EnumContext, ED->getName(), DefUnit, Line,
+ DBuilder.createEnumerationType(EnumContext, ED->getName(), DefUnit, Line,
Size, Align, EltArray);
return DbgTy;
}
@@ -1485,7 +1495,7 @@ llvm::DIType CGDebugInfo::CreateMemberType(llvm::DIFile Unit, QualType FType,
llvm::DIType FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
uint64_t FieldSize = CGM.getContext().getTypeSize(FType);
unsigned FieldAlign = CGM.getContext().getTypeAlign(FType);
- llvm::DIType Ty = DBuilder.CreateMemberType(Name, Unit, 0,
+ llvm::DIType Ty = DBuilder.createMemberType(Name, Unit, 0,
FieldSize, FieldAlign,
*Offset, 0, FieldTy);
*Offset += FieldSize;
@@ -1548,7 +1558,7 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType,
if (D->isImplicit())
Flags |= llvm::DIDescriptor::FlagArtificial;
llvm::DISubprogram SP =
- DBuilder.CreateFunction(FDContext, Name, LinkageName, Unit,
+ DBuilder.createFunction(FDContext, Name, LinkageName, Unit,
LineNo, getOrCreateType(FnType, Unit),
Fn->hasInternalLinkage(), true/*definition*/,
Flags, CGM.getLangOptions().Optimize, Fn);
@@ -1640,7 +1650,7 @@ void CGDebugInfo::UpdateLineDirectiveRegion(CGBuilderTy &Builder) {
/// region - "llvm.dbg.region.start.".
void CGDebugInfo::EmitRegionStart(CGBuilderTy &Builder) {
llvm::DIDescriptor D =
- DBuilder.CreateLexicalBlock(RegionStack.empty() ?
+ DBuilder.createLexicalBlock(RegionStack.empty() ?
llvm::DIDescriptor() :
llvm::DIDescriptor(RegionStack.back()),
getOrCreateFile(CurLoc),
@@ -1725,18 +1735,18 @@ llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const ValueDecl *VD,
FieldAlign = Align.getQuantity()*8;
*XOffset = FieldOffset;
- FieldTy = DBuilder.CreateMemberType(VD->getName(), Unit,
+ FieldTy = DBuilder.createMemberType(VD->getName(), Unit,
0, FieldSize, FieldAlign,
FieldOffset, 0, FieldTy);
EltTys.push_back(FieldTy);
FieldOffset += FieldSize;
llvm::DIArray Elements =
- DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size());
+ DBuilder.getOrCreateArray(EltTys.data(), EltTys.size());
unsigned Flags = llvm::DIDescriptor::FlagBlockByrefStruct;
- return DBuilder.CreateStructType(Unit, "", Unit, 0, FieldOffset, 0, Flags,
+ return DBuilder.createStructType(Unit, "", Unit, 0, FieldOffset, 0, Flags,
Elements);
}
@@ -1762,13 +1772,13 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
// If Storage is an aggregate returned as 'sret' then let debugger know
// about this.
if (Arg->hasStructRetAttr())
- Ty = DBuilder.CreateReferenceType(Ty);
+ Ty = DBuilder.createReferenceType(Ty);
else if (CXXRecordDecl *Record = VD->getType()->getAsCXXRecordDecl()) {
// If an aggregate variable has non trivial destructor or non trivial copy
// constructor than it is pass indirectly. Let debug info know about this
// by using reference of the aggregate type as a argument type.
if (!Record->hasTrivialCopyConstructor() || !Record->hasTrivialDestructor())
- Ty = DBuilder.CreateReferenceType(Ty);
+ Ty = DBuilder.createReferenceType(Ty);
}
}
@@ -1799,27 +1809,27 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
// Create the descriptor for the variable.
llvm::DIVariable D =
- DBuilder.CreateComplexVariable(Tag,
+ DBuilder.createComplexVariable(Tag,
llvm::DIDescriptor(RegionStack.back()),
VD->getName(), Unit, Line, Ty,
addr.data(), addr.size());
// Insert an llvm.dbg.declare into the current block.
llvm::Instruction *Call =
- DBuilder.InsertDeclare(Storage, D, Builder.GetInsertBlock());
+ DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock());
Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
return;
}
// Create the descriptor for the variable.
llvm::DIVariable D =
- DBuilder.CreateLocalVariable(Tag, llvm::DIDescriptor(Scope),
+ DBuilder.createLocalVariable(Tag, llvm::DIDescriptor(Scope),
Name, Unit, Line, Ty,
CGM.getLangOptions().Optimize, Flags);
// Insert an llvm.dbg.declare into the current block.
llvm::Instruction *Call =
- DBuilder.InsertDeclare(Storage, D, Builder.GetInsertBlock());
+ DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock());
Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
return;
@@ -1827,33 +1837,34 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
// If VD is an anonymous union then Storage represents value for
// all union fields.
- if (const RecordType *RT = dyn_cast<RecordType>(VD->getType()))
- if (const RecordDecl *RD = dyn_cast<RecordDecl>(RT->getDecl()))
- if (RD->isUnion()) {
- for (RecordDecl::field_iterator I = RD->field_begin(),
- E = RD->field_end();
- I != E; ++I) {
- FieldDecl *Field = *I;
- llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
- llvm::StringRef FieldName = Field->getName();
+ if (const RecordType *RT = dyn_cast<RecordType>(VD->getType())) {
+ const RecordDecl *RD = cast<RecordDecl>(RT->getDecl());
+ if (RD->isUnion()) {
+ for (RecordDecl::field_iterator I = RD->field_begin(),
+ E = RD->field_end();
+ I != E; ++I) {
+ FieldDecl *Field = *I;
+ llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
+ llvm::StringRef FieldName = Field->getName();
- // Ignore unnamed fields. Do not ignore unnamed records.
- if (FieldName.empty() && !isa<RecordType>(Field->getType()))
- continue;
+ // Ignore unnamed fields. Do not ignore unnamed records.
+ if (FieldName.empty() && !isa<RecordType>(Field->getType()))
+ continue;
- // Use VarDecl's Tag, Scope and Line number.
- llvm::DIVariable D =
- DBuilder.CreateLocalVariable(Tag, llvm::DIDescriptor(Scope),
- FieldName, Unit, Line, FieldTy,
- CGM.getLangOptions().Optimize, Flags);
+ // Use VarDecl's Tag, Scope and Line number.
+ llvm::DIVariable D =
+ DBuilder.createLocalVariable(Tag, llvm::DIDescriptor(Scope),
+ FieldName, Unit, Line, FieldTy,
+ CGM.getLangOptions().Optimize, Flags);
- // Insert an llvm.dbg.declare into the current block.
- llvm::Instruction *Call =
- DBuilder.InsertDeclare(Storage, D, Builder.GetInsertBlock());
+ // Insert an llvm.dbg.declare into the current block.
+ llvm::Instruction *Call =
+ DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock());
- Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
- }
+ Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
}
+ }
+ }
}
/// EmitDeclare - Emit local variable declaration debug info.
@@ -1887,7 +1898,6 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
llvm::SmallVector<llvm::Value *, 9> addr;
const llvm::Type *Int64Ty = llvm::Type::getInt64Ty(CGM.getLLVMContext());
- addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpDeref));
addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus));
addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity()));
if (isByRef) {
@@ -1905,12 +1915,12 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
// Create the descriptor for the variable.
llvm::DIVariable D =
- DBuilder.CreateComplexVariable(Tag, llvm::DIDescriptor(RegionStack.back()),
+ DBuilder.createComplexVariable(Tag, llvm::DIDescriptor(RegionStack.back()),
VD->getName(), Unit, Line, Ty,
addr.data(), addr.size());
// Insert an llvm.dbg.declare into the current block.
llvm::Instruction *Call =
- DBuilder.InsertDeclare(Storage, D, Builder.GetInsertBlock());
+ DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock());
llvm::MDNode *Scope = RegionStack.back();
Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
@@ -1936,7 +1946,146 @@ void CGDebugInfo::EmitDeclareOfArgVariable(const VarDecl *VD, llvm::Value *AI,
EmitDeclare(VD, llvm::dwarf::DW_TAG_arg_variable, AI, Builder);
}
+namespace {
+ struct BlockLayoutChunk {
+ uint64_t OffsetInBits;
+ const BlockDecl::Capture *Capture;
+ };
+ bool operator<(const BlockLayoutChunk &l, const BlockLayoutChunk &r) {
+ return l.OffsetInBits < r.OffsetInBits;
+ }
+}
+
+void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
+ llvm::Value *addr,
+ CGBuilderTy &Builder) {
+ ASTContext &C = CGM.getContext();
+ const BlockDecl *blockDecl = block.getBlockDecl();
+
+ // Collect some general information about the block's location.
+ SourceLocation loc = blockDecl->getCaretLocation();
+ llvm::DIFile tunit = getOrCreateFile(loc);
+ unsigned line = getLineNumber(loc);
+ unsigned column = getColumnNumber(loc);
+
+ // Build the debug-info type for the block literal.
+ llvm::DIDescriptor enclosingContext =
+ getContextDescriptor(cast<Decl>(blockDecl->getDeclContext()));
+
+ const llvm::StructLayout *blockLayout =
+ CGM.getTargetData().getStructLayout(block.StructureType);
+
+ llvm::SmallVector<llvm::Value*, 16> fields;
+ fields.push_back(createFieldType("__isa", C.VoidPtrTy, 0, loc, AS_public,
+ blockLayout->getElementOffsetInBits(0),
+ tunit));
+ fields.push_back(createFieldType("__flags", C.IntTy, 0, loc, AS_public,
+ blockLayout->getElementOffsetInBits(1),
+ tunit));
+ fields.push_back(createFieldType("__reserved", C.IntTy, 0, loc, AS_public,
+ blockLayout->getElementOffsetInBits(2),
+ tunit));
+ fields.push_back(createFieldType("__FuncPtr", C.VoidPtrTy, 0, loc, AS_public,
+ blockLayout->getElementOffsetInBits(3),
+ tunit));
+ fields.push_back(createFieldType("__descriptor",
+ C.getPointerType(block.NeedsCopyDispose ?
+ C.getBlockDescriptorExtendedType() :
+ C.getBlockDescriptorType()),
+ 0, loc, AS_public,
+ blockLayout->getElementOffsetInBits(4),
+ tunit));
+
+ // We want to sort the captures by offset, not because DWARF
+ // requires this, but because we're paranoid about debuggers.
+ llvm::SmallVector<BlockLayoutChunk, 8> chunks;
+
+ // 'this' capture.
+ if (blockDecl->capturesCXXThis()) {
+ BlockLayoutChunk chunk;
+ chunk.OffsetInBits =
+ blockLayout->getElementOffsetInBits(block.CXXThisIndex);
+ chunk.Capture = 0;
+ chunks.push_back(chunk);
+ }
+
+ // Variable captures.
+ for (BlockDecl::capture_const_iterator
+ i = blockDecl->capture_begin(), e = blockDecl->capture_end();
+ i != e; ++i) {
+ const BlockDecl::Capture &capture = *i;
+ const VarDecl *variable = capture.getVariable();
+ const CGBlockInfo::Capture &captureInfo = block.getCapture(variable);
+ // Ignore constant captures.
+ if (captureInfo.isConstant())
+ continue;
+
+ BlockLayoutChunk chunk;
+ chunk.OffsetInBits =
+ blockLayout->getElementOffsetInBits(captureInfo.getIndex());
+ chunk.Capture = &capture;
+ chunks.push_back(chunk);
+ }
+
+ // Sort by offset.
+ llvm::array_pod_sort(chunks.begin(), chunks.end());
+
+ for (llvm::SmallVectorImpl<BlockLayoutChunk>::iterator
+ i = chunks.begin(), e = chunks.end(); i != e; ++i) {
+ uint64_t offsetInBits = i->OffsetInBits;
+ const BlockDecl::Capture *capture = i->Capture;
+
+ // If we have a null capture, this must be the C++ 'this' capture.
+ if (!capture) {
+ const CXXMethodDecl *method =
+ cast<CXXMethodDecl>(blockDecl->getNonClosureContext());
+ QualType type = method->getThisType(C);
+
+ fields.push_back(createFieldType("this", type, 0, loc, AS_public,
+ offsetInBits, tunit));
+ continue;
+ }
+
+ const VarDecl *variable = capture->getVariable();
+ QualType type = (capture->isByRef() ? C.VoidPtrTy : variable->getType());
+ llvm::StringRef name = variable->getName();
+ fields.push_back(createFieldType(name, type, 0, loc, AS_public,
+ offsetInBits, tunit));
+ }
+
+ llvm::SmallString<36> typeName;
+ llvm::raw_svector_ostream(typeName)
+ << "__block_literal_" << CGM.getUniqueBlockCount();
+
+ llvm::DIArray fieldsArray =
+ DBuilder.getOrCreateArray(fields.data(), fields.size());
+
+ llvm::DIType type =
+ DBuilder.createStructType(tunit, typeName.str(), tunit, line,
+ CGM.getContext().toBits(block.BlockSize),
+ CGM.getContext().toBits(block.BlockAlign),
+ 0, fieldsArray);
+ type = DBuilder.createPointerType(type, CGM.PointerWidthInBits);
+
+ // Get overall information about the block.
+ unsigned flags = llvm::DIDescriptor::FlagArtificial;
+ llvm::MDNode *scope = RegionStack.back();
+ llvm::StringRef name = ".block_descriptor";
+
+ // Create the descriptor for the parameter.
+ llvm::DIVariable debugVar =
+ DBuilder.createLocalVariable(llvm::dwarf::DW_TAG_arg_variable,
+ llvm::DIDescriptor(scope),
+ name, tunit, line, type,
+ CGM.getLangOptions().Optimize, flags);
+
+ // Insert an llvm.dbg.value into the current block.
+ llvm::Instruction *declare =
+ DBuilder.insertDbgValueIntrinsic(addr, 0, debugVar,
+ Builder.GetInsertBlock());
+ declare->setDebugLoc(llvm::DebugLoc::get(line, column, scope));
+}
/// EmitGlobalVariable - Emit information about a global variable.
void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
@@ -1967,7 +2116,7 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
LinkageName = llvm::StringRef();
llvm::DIDescriptor DContext =
getContextDescriptor(dyn_cast<Decl>(D->getDeclContext()));
- DBuilder.CreateStaticVariable(DContext, DeclName, LinkageName,
+ DBuilder.createStaticVariable(DContext, DeclName, LinkageName,
Unit, LineNo, getOrCreateType(T, Unit),
Var->hasInternalLinkage(), Var);
}
@@ -1994,7 +2143,7 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
ArrayType::Normal, 0);
}
- DBuilder.CreateGlobalVariable(Name, Unit, LineNo,
+ DBuilder.createGlobalVariable(Name, Unit, LineNo,
getOrCreateType(T, Unit),
Var->hasInternalLinkage(), Var);
}
@@ -2013,7 +2162,7 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD,
// Do not use DIGlobalVariable for enums.
if (Ty.getTag() == llvm::dwarf::DW_TAG_enumeration_type)
return;
- DBuilder.CreateStaticVariable(Unit, Name, Name, Unit,
+ DBuilder.createStaticVariable(Unit, Name, Name, Unit,
getLineNumber(VD->getLocation()),
Ty, true, Init);
}
@@ -2032,7 +2181,7 @@ CGDebugInfo::getOrCreateNameSpace(const NamespaceDecl *NSDecl) {
llvm::DIDescriptor Context =
getContextDescriptor(dyn_cast<Decl>(NSDecl->getDeclContext()));
llvm::DINameSpace NS =
- DBuilder.CreateNameSpace(Context, NSDecl->getName(), FileD, LineNo);
+ DBuilder.createNameSpace(Context, NSDecl->getName(), FileD, LineNo);
NameSpaceCache[NSDecl] = llvm::WeakVH(NS);
return NS;
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h
index 6a9ab9c..a390788 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h
@@ -123,7 +123,10 @@ class CGDebugInfo {
llvm::SmallVectorImpl<llvm::Value *> &EltTys,
llvm::DIType RecordTy);
-
+ llvm::DIType createFieldType(llvm::StringRef name, QualType type,
+ Expr *bitWidth, SourceLocation loc,
+ AccessSpecifier AS, uint64_t offsetInBits,
+ llvm::DIFile tunit);
void CollectRecordFields(const RecordDecl *Decl, llvm::DIFile F,
llvm::SmallVectorImpl<llvm::Value *> &E);
@@ -180,6 +183,13 @@ public:
void EmitDeclareOfArgVariable(const VarDecl *Decl, llvm::Value *AI,
CGBuilderTy &Builder);
+ /// EmitDeclareOfBlockLiteralArgVariable - Emit call to
+ /// llvm.dbg.declare for the block-literal argument to a block
+ /// invocation function.
+ void EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
+ llvm::Value *addr,
+ CGBuilderTy &Builder);
+
/// EmitGlobalVariable - Emit information about a global variable.
void EmitGlobalVariable(llvm::GlobalVariable *GV, const VarDecl *Decl);
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp
index a87dfae..f4db01d 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp
@@ -474,14 +474,19 @@ namespace {
struct CallCleanupFunction : EHScopeStack::Cleanup {
llvm::Constant *CleanupFn;
const CGFunctionInfo &FnInfo;
- llvm::Value *Addr;
const VarDecl &Var;
CallCleanupFunction(llvm::Constant *CleanupFn, const CGFunctionInfo *Info,
- llvm::Value *Addr, const VarDecl *Var)
- : CleanupFn(CleanupFn), FnInfo(*Info), Addr(Addr), Var(*Var) {}
+ const VarDecl *Var)
+ : CleanupFn(CleanupFn), FnInfo(*Info), Var(*Var) {}
void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ DeclRefExpr DRE(const_cast<VarDecl*>(&Var), Var.getType(), VK_LValue,
+ SourceLocation());
+ // Compute the address of the local variable, in case it's a byref
+ // or something.
+ llvm::Value *Addr = CGF.EmitDeclRefLValue(&DRE).getAddress();
+
// In some cases, the type of the function argument will be different from
// the type of the pointer. An example of this is
// void f(void* arg);
@@ -543,7 +548,7 @@ static bool canEmitInitWithFewStoresAfterMemset(llvm::Constant *Init,
/// canEmitInitWithFewStoresAfterMemset returned true for, emit the scalar
/// stores that would be required.
static void emitStoresForInitAfterMemset(llvm::Constant *Init, llvm::Value *Loc,
- CGBuilderTy &Builder) {
+ bool isVolatile, CGBuilderTy &Builder) {
// Zero doesn't require any stores.
if (isa<llvm::ConstantAggregateZero>(Init) ||
isa<llvm::ConstantPointerNull>(Init) ||
@@ -554,7 +559,7 @@ static void emitStoresForInitAfterMemset(llvm::Constant *Init, llvm::Value *Loc,
isa<llvm::ConstantVector>(Init) || isa<llvm::BlockAddress>(Init) ||
isa<llvm::ConstantExpr>(Init)) {
if (!Init->isNullValue())
- Builder.CreateStore(Init, Loc);
+ Builder.CreateStore(Init, Loc, isVolatile);
return;
}
@@ -567,7 +572,7 @@ static void emitStoresForInitAfterMemset(llvm::Constant *Init, llvm::Value *Loc,
// Otherwise, get a pointer to the element and emit it.
emitStoresForInitAfterMemset(Elt, Builder.CreateConstGEP2_32(Loc, 0, i),
- Builder);
+ isVolatile, Builder);
}
}
@@ -597,37 +602,55 @@ static bool shouldUseMemSetPlusStoresToInitialize(llvm::Constant *Init,
/// EmitAutoVarDecl - Emit code and set up an entry in LocalDeclMap for a
/// variable declaration with auto, register, or no storage class specifier.
/// These turn into simple stack objects, or GlobalValues depending on target.
-void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D,
- SpecialInitFn *SpecialInit) {
+void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D) {
+ AutoVarEmission emission = EmitAutoVarAlloca(D);
+ EmitAutoVarInit(emission);
+ EmitAutoVarCleanups(emission);
+}
+
+/// EmitAutoVarAlloca - Emit the alloca and debug information for a
+/// local variable. Does not emit initalization or destruction.
+CodeGenFunction::AutoVarEmission
+CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
QualType Ty = D.getType();
- unsigned Alignment = getContext().getDeclAlign(&D).getQuantity();
+
+ AutoVarEmission emission(D);
+
bool isByRef = D.hasAttr<BlocksAttr>();
- bool needsDispose = false;
- CharUnits Align = CharUnits::Zero();
- bool IsSimpleConstantInitializer = false;
+ emission.IsByRef = isByRef;
+
+ CharUnits alignment = getContext().getDeclAlign(&D);
+ emission.Alignment = alignment;
- bool NRVO = false;
- llvm::Value *NRVOFlag = 0;
llvm::Value *DeclPtr;
if (Ty->isConstantSizeType()) {
if (!Target.useGlobalsForAutomaticVariables()) {
- NRVO = getContext().getLangOptions().ElideConstructors &&
- D.isNRVOVariable();
- // If this value is an array or struct, is POD, and if the initializer is
- // a staticly determinable constant, try to optimize it (unless the NRVO
- // is already optimizing this).
- if (!NRVO && D.getInit() && !isByRef &&
- (Ty->isArrayType() || Ty->isRecordType()) &&
- Ty->isPODType() &&
+ bool NRVO = getContext().getLangOptions().ElideConstructors &&
+ D.isNRVOVariable();
+
+ // If this value is a POD array or struct with a statically
+ // determinable constant initializer, there are optimizations we
+ // can do.
+ // TODO: we can potentially constant-evaluate non-POD structs and
+ // arrays as long as the initialization is trivial (e.g. if they
+ // have a non-trivial destructor, but not a non-trivial constructor).
+ if (D.getInit() &&
+ (Ty->isArrayType() || Ty->isRecordType()) && Ty->isPODType() &&
D.getInit()->isConstantInitializer(getContext(), false)) {
- // If this variable is marked 'const', emit the value as a global.
- if (CGM.getCodeGenOpts().MergeAllConstants &&
- Ty.isConstant(getContext())) {
- EmitStaticVarDecl(D, llvm::GlobalValue::InternalLinkage);
- return;
+
+ // If the variable's a const type, and it's neither an NRVO
+ // candidate nor a __block variable, emit it as a global instead.
+ if (CGM.getCodeGenOpts().MergeAllConstants && Ty.isConstQualified() &&
+ !NRVO && !isByRef) {
+ EmitStaticVarDecl(D, llvm::GlobalValue::PrivateLinkage);
+
+ emission.Address = 0; // signal this condition to later callbacks
+ assert(emission.wasEmittedAsGlobal());
+ return emission;
}
-
- IsSimpleConstantInitializer = true;
+
+ // Otherwise, tell the initialization code that we're in this case.
+ emission.IsConstantAggregate = true;
}
// A normal fixed sized variable becomes an alloca in the entry block,
@@ -646,12 +669,13 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D,
// to this variable. Set it to zero to indicate that NRVO was not
// applied.
llvm::Value *Zero = Builder.getFalse();
- NRVOFlag = CreateTempAlloca(Zero->getType(), "nrvo");
+ llvm::Value *NRVOFlag = CreateTempAlloca(Zero->getType(), "nrvo");
EnsureInsertPoint();
Builder.CreateStore(Zero, NRVOFlag);
// Record the NRVO flag for this variable.
NRVOFlags[&D] = NRVOFlag;
+ emission.NRVOFlag = NRVOFlag;
}
}
} else {
@@ -661,11 +685,11 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D,
llvm::AllocaInst *Alloc = CreateTempAlloca(LTy);
Alloc->setName(D.getNameAsString());
- Align = getContext().getDeclAlign(&D);
+ CharUnits allocaAlignment = alignment;
if (isByRef)
- Align = std::max(Align,
+ allocaAlignment = std::max(allocaAlignment,
getContext().toCharUnitsFromBits(Target.getPointerAlign(0)));
- Alloc->setAlignment(Align.getQuantity());
+ Alloc->setAlignment(allocaAlignment.getQuantity());
DeclPtr = Alloc;
}
} else {
@@ -707,7 +731,7 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D,
// Allocate memory for the array.
llvm::AllocaInst *VLA =
Builder.CreateAlloca(llvm::Type::getInt8Ty(getLLVMContext()), VLASize, "vla");
- VLA->setAlignment(getContext().getDeclAlign(&D).getQuantity());
+ VLA->setAlignment(alignment.getQuantity());
DeclPtr = Builder.CreateBitCast(VLA, LElemPtrTy, "tmp");
}
@@ -715,6 +739,7 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D,
llvm::Value *&DMEntry = LocalDeclMap[&D];
assert(DMEntry == 0 && "Decl already exists in localdeclmap!");
DMEntry = DeclPtr;
+ emission.Address = DeclPtr;
// Emit debug info for local var declaration.
if (CGDebugInfo *DI = getDebugInfo()) {
@@ -727,53 +752,92 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D,
DI->EmitDeclareOfAutoVariable(&D, DeclPtr, Builder);
}
+ return emission;
+}
+
+/// Determines whether the given __block variable is potentially
+/// captured by the given expression.
+static bool isCapturedBy(const VarDecl &var, const Expr *e) {
+ // Skip the most common kinds of expressions that make
+ // hierarchy-walking expensive.
+ e = e->IgnoreParenCasts();
+
+ if (const BlockExpr *be = dyn_cast<BlockExpr>(e)) {
+ const BlockDecl *block = be->getBlockDecl();
+ for (BlockDecl::capture_const_iterator i = block->capture_begin(),
+ e = block->capture_end(); i != e; ++i) {
+ if (i->getVariable() == &var)
+ return true;
+ }
+
+ // No need to walk into the subexpressions.
+ return false;
+ }
+
+ for (Stmt::const_child_range children = e->children(); children; ++children)
+ if (isCapturedBy(var, cast<Expr>(*children)))
+ return true;
+
+ return false;
+}
+
+void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
+ assert(emission.Variable && "emission was not valid!");
+
+ // If this was emitted as a global constant, we're done.
+ if (emission.wasEmittedAsGlobal()) return;
+
+ const VarDecl &D = *emission.Variable;
+ QualType type = D.getType();
+
// If this local has an initializer, emit it now.
const Expr *Init = D.getInit();
// If we are at an unreachable point, we don't need to emit the initializer
// unless it contains a label.
if (!HaveInsertPoint()) {
- if (!ContainsLabel(Init))
- Init = 0;
- else
- EnsureInsertPoint();
+ if (!Init || !ContainsLabel(Init)) return;
+ EnsureInsertPoint();
}
- if (isByRef) {
- EnsureInsertPoint();
+ CharUnits alignment = emission.Alignment;
+
+ if (emission.IsByRef) {
llvm::Value *V;
BlockFieldFlags fieldFlags;
bool fieldNeedsCopyDispose = false;
- needsDispose = true;
-
- if (Ty->isBlockPointerType()) {
+ if (type->isBlockPointerType()) {
fieldFlags |= BLOCK_FIELD_IS_BLOCK;
fieldNeedsCopyDispose = true;
- } else if (getContext().isObjCNSObjectType(Ty) ||
- Ty->isObjCObjectPointerType()) {
+ } else if (getContext().isObjCNSObjectType(type) ||
+ type->isObjCObjectPointerType()) {
fieldFlags |= BLOCK_FIELD_IS_OBJECT;
fieldNeedsCopyDispose = true;
} else if (getLangOptions().CPlusPlus) {
if (getContext().getBlockVarCopyInits(&D))
fieldNeedsCopyDispose = true;
- else if (const CXXRecordDecl *record = D.getType()->getAsCXXRecordDecl())
+ else if (const CXXRecordDecl *record = type->getAsCXXRecordDecl())
fieldNeedsCopyDispose = !record->hasTrivialDestructor();
}
+ llvm::Value *addr = emission.Address;
+
// FIXME: Someone double check this.
- if (Ty.isObjCGCWeak())
+ if (type.isObjCGCWeak())
fieldFlags |= BLOCK_FIELD_IS_WEAK;
+ // Initialize the 'isa', which is just 0 or 1.
int isa = 0;
if (fieldFlags & BLOCK_FIELD_IS_WEAK)
isa = 1;
V = Builder.CreateIntToPtr(Builder.getInt32(isa), Int8PtrTy, "isa");
- Builder.CreateStore(V, Builder.CreateStructGEP(DeclPtr, 0, "byref.isa"));
+ Builder.CreateStore(V, Builder.CreateStructGEP(addr, 0, "byref.isa"));
- Builder.CreateStore(DeclPtr, Builder.CreateStructGEP(DeclPtr, 1,
- "byref.forwarding"));
+ // Store the address of the variable into its own forwarding pointer.
+ Builder.CreateStore(addr,
+ Builder.CreateStructGEP(addr, 1, "byref.forwarding"));
// Blocks ABI:
// c) the flags field is set to either 0 if no helper functions are
@@ -781,150 +845,157 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D,
BlockFlags flags;
if (fieldNeedsCopyDispose) flags |= BLOCK_HAS_COPY_DISPOSE;
Builder.CreateStore(llvm::ConstantInt::get(IntTy, flags.getBitMask()),
- Builder.CreateStructGEP(DeclPtr, 2, "byref.flags"));
+ Builder.CreateStructGEP(addr, 2, "byref.flags"));
const llvm::Type *V1;
- V1 = cast<llvm::PointerType>(DeclPtr->getType())->getElementType();
+ V1 = cast<llvm::PointerType>(addr->getType())->getElementType();
V = llvm::ConstantInt::get(IntTy, CGM.GetTargetTypeStoreSize(V1).getQuantity());
- Builder.CreateStore(V, Builder.CreateStructGEP(DeclPtr, 3, "byref.size"));
+ Builder.CreateStore(V, Builder.CreateStructGEP(addr, 3, "byref.size"));
if (fieldNeedsCopyDispose) {
- llvm::Value *copy_helper = Builder.CreateStructGEP(DeclPtr, 4);
- Builder.CreateStore(CGM.BuildbyrefCopyHelper(DeclPtr->getType(),
- fieldFlags,
- Align.getQuantity(), &D),
+ llvm::Value *copy_helper = Builder.CreateStructGEP(addr, 4);
+ Builder.CreateStore(CGM.BuildbyrefCopyHelper(addr->getType(), fieldFlags,
+ alignment.getQuantity(), &D),
copy_helper);
- llvm::Value *destroy_helper = Builder.CreateStructGEP(DeclPtr, 5);
- Builder.CreateStore(CGM.BuildbyrefDestroyHelper(DeclPtr->getType(),
+ llvm::Value *destroy_helper = Builder.CreateStructGEP(addr, 5);
+ Builder.CreateStore(CGM.BuildbyrefDestroyHelper(addr->getType(),
fieldFlags,
- Align.getQuantity(), &D),
+ alignment.getQuantity(),
+ &D),
destroy_helper);
}
}
- if (SpecialInit) {
- SpecialInit(*this, D, DeclPtr);
- } else if (Init) {
- llvm::Value *Loc = DeclPtr;
-
- bool isVolatile = getContext().getCanonicalType(Ty).isVolatileQualified();
+ if (!Init) return;
+
+ // Check whether this is a byref variable that's potentially
+ // captured and moved by its own initializer. If so, we'll need to
+ // emit the initializer first, then copy into the variable.
+ bool capturedByInit = emission.IsByRef && isCapturedBy(D, Init);
+
+ llvm::Value *Loc =
+ capturedByInit ? emission.Address : emission.getObjectAddress(*this);
+
+ bool isVolatile = type.isVolatileQualified();
- // If the initializer was a simple constant initializer, we can optimize it
- // in various ways.
- if (IsSimpleConstantInitializer) {
- llvm::Constant *Init = CGM.EmitConstantExpr(D.getInit(), Ty,this);
- assert(Init != 0 && "Wasn't a simple constant init?");
-
- llvm::Value *SizeVal =
- llvm::ConstantInt::get(IntPtrTy,
- getContext().getTypeSizeInChars(Ty).getQuantity());
-
- const llvm::Type *BP = Int8PtrTy;
- if (Loc->getType() != BP)
- Loc = Builder.CreateBitCast(Loc, BP, "tmp");
+ // If this is a simple aggregate initialization, we can optimize it
+ // in various ways.
+ if (emission.IsConstantAggregate) {
+ assert(!capturedByInit && "constant init contains a capturing block?");
+
+ llvm::Constant *Init = CGM.EmitConstantExpr(D.getInit(), type, this);
+ assert(Init != 0 && "Wasn't a simple constant init?");
- // If the initializer is all or mostly zeros, codegen with memset then do
- // a few stores afterward.
- if (shouldUseMemSetPlusStoresToInitialize(Init,
+ llvm::Value *SizeVal =
+ llvm::ConstantInt::get(IntPtrTy,
+ getContext().getTypeSizeInChars(type).getQuantity());
+
+ const llvm::Type *BP = Int8PtrTy;
+ if (Loc->getType() != BP)
+ Loc = Builder.CreateBitCast(Loc, BP, "tmp");
+
+ // If the initializer is all or mostly zeros, codegen with memset then do
+ // a few stores afterward.
+ if (shouldUseMemSetPlusStoresToInitialize(Init,
CGM.getTargetData().getTypeAllocSize(Init->getType()))) {
- Builder.CreateMemSet(Loc, Builder.getInt8(0), SizeVal,
- Align.getQuantity(), false);
- if (!Init->isNullValue()) {
- Loc = Builder.CreateBitCast(Loc, Init->getType()->getPointerTo());
- emitStoresForInitAfterMemset(Init, Loc, Builder);
- }
-
- } else {
- // Otherwise, create a temporary global with the initializer then
- // memcpy from the global to the alloca.
- std::string Name = GetStaticDeclName(*this, D, ".");
- llvm::GlobalVariable *GV =
+ Builder.CreateMemSet(Loc, llvm::ConstantInt::get(Int8Ty, 0), SizeVal,
+ alignment.getQuantity(), isVolatile);
+ if (!Init->isNullValue()) {
+ Loc = Builder.CreateBitCast(Loc, Init->getType()->getPointerTo());
+ emitStoresForInitAfterMemset(Init, Loc, isVolatile, Builder);
+ }
+ } else {
+ // Otherwise, create a temporary global with the initializer then
+ // memcpy from the global to the alloca.
+ std::string Name = GetStaticDeclName(*this, D, ".");
+ llvm::GlobalVariable *GV =
new llvm::GlobalVariable(CGM.getModule(), Init->getType(), true,
llvm::GlobalValue::InternalLinkage,
Init, Name, 0, false, 0);
- GV->setAlignment(Align.getQuantity());
+ GV->setAlignment(alignment.getQuantity());
- llvm::Value *SrcPtr = GV;
- if (SrcPtr->getType() != BP)
- SrcPtr = Builder.CreateBitCast(SrcPtr, BP, "tmp");
+ llvm::Value *SrcPtr = GV;
+ if (SrcPtr->getType() != BP)
+ SrcPtr = Builder.CreateBitCast(SrcPtr, BP, "tmp");
- Builder.CreateMemCpy(Loc, SrcPtr, SizeVal, Align.getQuantity(), false);
- }
- } else if (Ty->isReferenceType()) {
- RValue RV = EmitReferenceBindingToExpr(Init, &D);
- if (isByRef)
- Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D),
- D.getNameAsString());
- EmitStoreOfScalar(RV.getScalarVal(), Loc, false, Alignment, Ty);
- } else if (!hasAggregateLLVMType(Init->getType())) {
- llvm::Value *V = EmitScalarExpr(Init);
- if (isByRef) {
- // When RHS has side-effect, must go through "forwarding' field
- // to get to the address of the __block variable descriptor.
- if (Init->HasSideEffects(getContext()))
- Loc = BuildBlockByrefAddress(DeclPtr, &D);
- else
- Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D),
- D.getNameAsString());
- }
- EmitStoreOfScalar(V, Loc, isVolatile, Alignment, Ty);
- } else if (Init->getType()->isAnyComplexType()) {
- if (isByRef)
- Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D),
- D.getNameAsString());
- EmitComplexExprIntoAddr(Init, Loc, isVolatile);
- } else {
- if (isByRef)
- Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D),
- D.getNameAsString());
- EmitAggExpr(Init, AggValueSlot::forAddr(Loc, isVolatile, true, false));
+ Builder.CreateMemCpy(Loc, SrcPtr, SizeVal, alignment.getQuantity(),
+ isVolatile);
}
+ } else if (type->isReferenceType()) {
+ RValue RV = EmitReferenceBindingToExpr(Init, &D);
+ if (capturedByInit) Loc = BuildBlockByrefAddress(Loc, &D);
+ EmitStoreOfScalar(RV.getScalarVal(), Loc, false, alignment.getQuantity(),
+ type);
+ } else if (!hasAggregateLLVMType(type)) {
+ llvm::Value *V = EmitScalarExpr(Init);
+ if (capturedByInit) Loc = BuildBlockByrefAddress(Loc, &D);
+ EmitStoreOfScalar(V, Loc, isVolatile, alignment.getQuantity(), type);
+ } else if (type->isAnyComplexType()) {
+ ComplexPairTy complex = EmitComplexExpr(Init);
+ if (capturedByInit) Loc = BuildBlockByrefAddress(Loc, &D);
+ StoreComplexToAddr(complex, Loc, isVolatile);
+ } else {
+ // TODO: how can we delay here if D is captured by its initializer?
+ EmitAggExpr(Init, AggValueSlot::forAddr(Loc, isVolatile, true, false));
}
+}
- // Handle CXX destruction of variables.
- QualType DtorTy(Ty);
- while (const ArrayType *Array = getContext().getAsArrayType(DtorTy))
- DtorTy = getContext().getBaseElementType(Array);
- if (const RecordType *RT = DtorTy->getAs<RecordType>())
- if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
+void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) {
+ assert(emission.Variable && "emission was not valid!");
+
+ // If this was emitted as a global constant, we're done.
+ if (emission.wasEmittedAsGlobal()) return;
+
+ const VarDecl &D = *emission.Variable;
+
+ // Handle C++ destruction of variables.
+ if (getLangOptions().CPlusPlus) {
+ QualType type = D.getType();
+ QualType baseType = getContext().getBaseElementType(type);
+ if (const RecordType *RT = baseType->getAs<RecordType>()) {
+ CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(RT->getDecl());
if (!ClassDecl->hasTrivialDestructor()) {
// Note: We suppress the destructor call when the corresponding NRVO
// flag has been set.
- llvm::Value *Loc = DeclPtr;
- if (isByRef)
- Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D),
- D.getNameAsString());
+
+ // Note that for __block variables, we want to destroy the
+ // original stack object, not the possible forwarded object.
+ llvm::Value *Loc = emission.getObjectAddress(*this);
const CXXDestructorDecl *D = ClassDecl->getDestructor();
assert(D && "EmitLocalBlockVarDecl - destructor is nul");
- if (const ConstantArrayType *Array =
- getContext().getAsConstantArrayType(Ty)) {
+ if (type != baseType) {
+ const ConstantArrayType *Array =
+ getContext().getAsConstantArrayType(type);
+ assert(Array && "types changed without array?");
EHStack.pushCleanup<CallArrayDtor>(NormalAndEHCleanup,
D, Array, Loc);
} else {
EHStack.pushCleanup<CallVarDtor>(NormalAndEHCleanup,
- D, NRVOFlag, Loc);
+ D, emission.NRVOFlag, Loc);
}
}
+ }
}
- // Handle the cleanup attribute
+ // Handle the cleanup attribute.
if (const CleanupAttr *CA = D.getAttr<CleanupAttr>()) {
const FunctionDecl *FD = CA->getFunctionDecl();
- llvm::Constant* F = CGM.GetAddrOfFunction(FD);
+ llvm::Constant *F = CGM.GetAddrOfFunction(FD);
assert(F && "Could not find function!");
const CGFunctionInfo &Info = CGM.getTypes().getFunctionInfo(FD);
- EHStack.pushCleanup<CallCleanupFunction>(NormalAndEHCleanup,
- F, &Info, DeclPtr, &D);
+ EHStack.pushCleanup<CallCleanupFunction>(NormalAndEHCleanup, F, &Info, &D);
}
- // If this is a block variable, clean it up.
- if (needsDispose && CGM.getLangOptions().getGCMode() != LangOptions::GCOnly)
- EHStack.pushCleanup<CallBlockRelease>(NormalAndEHCleanup, DeclPtr);
+ // If this is a block variable, call _Block_object_destroy
+ // (on the unforwarded address).
+ if (emission.IsByRef &&
+ CGM.getLangOptions().getGCMode() != LangOptions::GCOnly)
+ EHStack.pushCleanup<CallBlockRelease>(NormalAndEHCleanup, emission.Address);
}
/// Emit an alloca (or GlobalValue depending on target)
@@ -933,6 +1004,24 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg) {
// FIXME: Why isn't ImplicitParamDecl a ParmVarDecl?
assert((isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D)) &&
"Invalid argument to EmitParmDecl");
+
+ Arg->setName(D.getName());
+
+ // Use better IR generation for certain implicit parameters.
+ if (isa<ImplicitParamDecl>(D)) {
+ // The only implicit argument a block has is its literal.
+ if (BlockInfo) {
+ LocalDeclMap[&D] = Arg;
+
+ if (CGDebugInfo *DI = getDebugInfo()) {
+ DI->setLocation(D.getLocation());
+ DI->EmitDeclareOfBlockLiteralArgVariable(*BlockInfo, Arg, Builder);
+ }
+
+ return;
+ }
+ }
+
QualType Ty = D.getType();
llvm::Value *DeclPtr;
@@ -949,7 +1038,6 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg) {
getContext().getDeclAlign(&D).getQuantity(), Ty,
CGM.getTBAAInfo(Ty));
}
- Arg->setName(D.getName());
llvm::Value *&DMEntry = LocalDeclMap[&D];
assert(DMEntry == 0 && "Decl already exists in localdeclmap!");
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp
index 6181965..4bce081 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp
@@ -1086,14 +1086,14 @@ static void BeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *S) {
// 3. Enter __cxa_end_catch cleanup
// 4. Enter dtor cleanup
//
- // We do this by initializing the exception variable with a
- // "special initializer", InitCatchParam. Delegation sequence:
+ // We do this by using a slightly abnormal initialization process.
+ // Delegation sequence:
// - ExitCXXTryStmt opens a RunCleanupsScope
- // - EmitLocalBlockVarDecl creates the variable and debug info
+ // - EmitAutoVarAlloca creates the variable and debug info
// - InitCatchParam initializes the variable from the exception
- // - CallBeginCatch calls __cxa_begin_catch
- // - CallBeginCatch enters the __cxa_end_catch cleanup
- // - EmitLocalBlockVarDecl enters the variable destructor cleanup
+ // - CallBeginCatch calls __cxa_begin_catch
+ // - CallBeginCatch enters the __cxa_end_catch cleanup
+ // - EmitAutoVarCleanups enters the variable destructor cleanup
// - EmitCXXTryStmt emits the code for the catch body
// - EmitCXXTryStmt close the RunCleanupsScope
@@ -1105,7 +1105,9 @@ static void BeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *S) {
}
// Emit the local.
- CGF.EmitAutoVarDecl(*CatchParam, &InitCatchParam);
+ CodeGenFunction::AutoVarEmission var = CGF.EmitAutoVarAlloca(*CatchParam);
+ InitCatchParam(CGF, *CatchParam, var.getObjectAddress(CGF));
+ CGF.EmitAutoVarCleanups(var);
}
namespace {
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp
index 1b7e7a0..2abaadf 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp
@@ -260,6 +260,10 @@ EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E,
}
}
+ if (const OpaqueValueExpr *opaque = dyn_cast<OpaqueValueExpr>(E))
+ if (opaque->getType()->isRecordType())
+ return CGF.EmitOpaqueValueLValue(opaque).getAddress();
+
// Nothing changed.
break;
}
@@ -1606,39 +1610,67 @@ LValue CodeGenFunction::EmitLValueForAnonRecordField(llvm::Value *BaseValue,
}
}
-LValue CodeGenFunction::EmitLValueForField(llvm::Value *BaseValue,
- const FieldDecl *Field,
- unsigned CVRQualifiers) {
- if (Field->isBitField())
- return EmitLValueForBitfield(BaseValue, Field, CVRQualifiers);
+LValue CodeGenFunction::EmitLValueForField(llvm::Value *baseAddr,
+ const FieldDecl *field,
+ unsigned cvr) {
+ if (field->isBitField())
+ return EmitLValueForBitfield(baseAddr, field, cvr);
- const CGRecordLayout &RL =
- CGM.getTypes().getCGRecordLayout(Field->getParent());
- unsigned idx = RL.getLLVMFieldNo(Field);
- llvm::Value *V = Builder.CreateStructGEP(BaseValue, idx, "tmp");
+ const RecordDecl *rec = field->getParent();
+ QualType type = field->getType();
+
+ bool mayAlias = rec->hasAttr<MayAliasAttr>();
- // Match union field type.
- if (Field->getParent()->isUnion()) {
- const llvm::Type *FieldTy =
- CGM.getTypes().ConvertTypeForMem(Field->getType());
- const llvm::PointerType *BaseTy =
- cast<llvm::PointerType>(BaseValue->getType());
- unsigned AS = BaseTy->getAddressSpace();
- V = Builder.CreateBitCast(V,
- llvm::PointerType::get(FieldTy, AS),
- "tmp");
+ llvm::Value *addr;
+ if (rec->isUnion()) {
+ // For unions, we just cast to the appropriate type.
+ assert(!type->isReferenceType() && "union has reference member");
+
+ const llvm::Type *llvmType = CGM.getTypes().ConvertTypeForMem(type);
+ unsigned AS =
+ cast<llvm::PointerType>(baseAddr->getType())->getAddressSpace();
+ addr = Builder.CreateBitCast(baseAddr, llvmType->getPointerTo(AS),
+ field->getName());
+ } else {
+ // For structs, we GEP to the field that the record layout suggests.
+ unsigned idx = CGM.getTypes().getCGRecordLayout(rec).getLLVMFieldNo(field);
+ addr = Builder.CreateStructGEP(baseAddr, idx, field->getName());
+
+ // If this is a reference field, load the reference right now.
+ if (const ReferenceType *refType = type->getAs<ReferenceType>()) {
+ llvm::LoadInst *load = Builder.CreateLoad(addr, "ref");
+ if (cvr & Qualifiers::Volatile) load->setVolatile(true);
+
+ if (CGM.shouldUseTBAA()) {
+ llvm::MDNode *tbaa;
+ if (mayAlias)
+ tbaa = CGM.getTBAAInfo(getContext().CharTy);
+ else
+ tbaa = CGM.getTBAAInfo(type);
+ CGM.DecorateInstruction(load, tbaa);
+ }
+
+ addr = load;
+ mayAlias = false;
+ type = refType->getPointeeType();
+ cvr = 0; // qualifiers don't recursively apply to referencee
+ }
}
- if (Field->getType()->isReferenceType())
- V = Builder.CreateLoad(V, "tmp");
- unsigned Alignment = getContext().getDeclAlign(Field).getQuantity();
- LValue LV = MakeAddrLValue(V, Field->getType(), Alignment);
- LV.getQuals().addCVRQualifiers(CVRQualifiers);
+ unsigned alignment = getContext().getDeclAlign(field).getQuantity();
+ LValue LV = MakeAddrLValue(addr, type, alignment);
+ LV.getQuals().addCVRQualifiers(cvr);
// __weak attribute on a field is ignored.
if (LV.getQuals().getObjCGCAttr() == Qualifiers::Weak)
LV.getQuals().removeObjCGCAttr();
-
+
+ // Fields of may_alias structs act like 'char' for TBAA purposes.
+ // FIXME: this should get propagated down through anonymous structs
+ // and unions.
+ if (mayAlias && LV.getTBAAInfo())
+ LV.setTBAAInfo(CGM.getTBAAInfo(getContext().CharTy));
+
return LV;
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp
index 08c458b..5d34907 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp
@@ -663,6 +663,11 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
return;
}
+ // The local variable comes into scope immediately.
+ AutoVarEmission variable = AutoVarEmission::invalid();
+ if (const DeclStmt *SD = dyn_cast<DeclStmt>(S.getElement()))
+ variable = EmitAutoVarAlloca(*cast<VarDecl>(SD->getSingleDecl()));
+
CGDebugInfo *DI = getDebugInfo();
if (DI) {
DI->setLocation(S.getSourceRange().getBegin());
@@ -799,22 +804,23 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
// Initialize the element variable.
RunCleanupsScope elementVariableScope(*this);
- bool elementIsDecl;
+ bool elementIsVariable;
LValue elementLValue;
QualType elementType;
if (const DeclStmt *SD = dyn_cast<DeclStmt>(S.getElement())) {
- EmitStmt(SD);
- const VarDecl* D = cast<VarDecl>(SD->getSingleDecl());
+ // Initialize the variable, in case it's a __block variable or something.
+ EmitAutoVarInit(variable);
+ const VarDecl* D = cast<VarDecl>(SD->getSingleDecl());
DeclRefExpr tempDRE(const_cast<VarDecl*>(D), D->getType(),
VK_LValue, SourceLocation());
elementLValue = EmitLValue(&tempDRE);
elementType = D->getType();
- elementIsDecl = true;
+ elementIsVariable = true;
} else {
elementLValue = LValue(); // suppress warning
elementType = cast<Expr>(S.getElement())->getType();
- elementIsDecl = false;
+ elementIsVariable = false;
}
const llvm::Type *convertedElementType = ConvertType(elementType);
@@ -837,11 +843,16 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
// Make sure we have an l-value. Yes, this gets evaluated every
// time through the loop.
- if (!elementIsDecl)
+ if (!elementIsVariable)
elementLValue = EmitLValue(cast<Expr>(S.getElement()));
EmitStoreThroughLValue(RValue::get(CurrentItem), elementLValue, elementType);
+ // If we do have an element variable, this assignment is the end of
+ // its initialization.
+ if (elementIsVariable)
+ EmitAutoVarCleanups(variable);
+
// Perform the loop body, setting up break and continue labels.
BreakContinueStack.push_back(BreakContinue(LoopEnd, AfterBody));
{
@@ -891,7 +902,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
// No more elements.
EmitBlock(EmptyBB);
- if (!elementIsDecl) {
+ if (!elementIsVariable) {
// If the element was not a declaration, set it to be null.
llvm::Value *null = llvm::Constant::getNullValue(convertedElementType);
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp
index d481e77..5f19dc6 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp
@@ -949,7 +949,12 @@ llvm::Constant *CGObjCGNU::GenerateClassStructure(
Elements.push_back(MakeConstantString(Name, ".class_name"));
Elements.push_back(Zero);
Elements.push_back(llvm::ConstantInt::get(LongTy, info));
- Elements.push_back(InstanceSize);
+ if (isMeta) {
+ llvm::TargetData td(&TheModule);
+ Elements.push_back(llvm::ConstantInt::get(LongTy,
+ td.getTypeSizeInBits(ClassTy)/8));
+ } else
+ Elements.push_back(InstanceSize);
Elements.push_back(IVars);
Elements.push_back(Methods);
Elements.push_back(NULLPtr);
@@ -1831,9 +1836,9 @@ llvm::Function *CGObjCGNU::GetPropertyGetFunction() {
std::vector<const llvm::Type*> Params;
Params.push_back(IdTy);
Params.push_back(SelectorTy);
- Params.push_back(IntTy);
+ Params.push_back(SizeTy);
Params.push_back(BoolTy);
- // void objc_getProperty (id, SEL, int, bool)
+ // void objc_getProperty (id, SEL, ptrdiff_t, bool)
const llvm::FunctionType *FTy =
llvm::FunctionType::get(IdTy, Params, false);
return cast<llvm::Function>(CGM.CreateRuntimeFunction(FTy,
@@ -1844,11 +1849,11 @@ llvm::Function *CGObjCGNU::GetPropertySetFunction() {
std::vector<const llvm::Type*> Params;
Params.push_back(IdTy);
Params.push_back(SelectorTy);
- Params.push_back(IntTy);
+ Params.push_back(SizeTy);
Params.push_back(IdTy);
Params.push_back(BoolTy);
Params.push_back(BoolTy);
- // void objc_setProperty (id, SEL, int, id, bool, bool)
+ // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool)
const llvm::FunctionType *FTy =
llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Params, false);
return cast<llvm::Function>(CGM.CreateRuntimeFunction(FTy,
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp
index 7c679b9..8dbd85f 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp
@@ -46,6 +46,15 @@ using namespace CodeGen;
// don't belong in CGObjCRuntime either so we will live with it for
// now.
+static void EmitNullReturnInitialization(CodeGenFunction &CGF,
+ ReturnValueSlot &returnSlot,
+ QualType resultType) {
+ // Force the return slot to exist.
+ if (!returnSlot.getValue())
+ returnSlot = ReturnValueSlot(CGF.CreateMemTemp(resultType), false);
+ CGF.EmitNullInitialization(returnSlot.getValue(), resultType);
+}
+
static uint64_t LookupFieldBitOffset(CodeGen::CodeGenModule &CGM,
const ObjCInterfaceDecl *OID,
const ObjCImplementationDecl *ID,
@@ -1639,6 +1648,7 @@ CGObjCCommonMac::EmitLegacyMessageSend(CodeGen::CodeGenFunction &CGF,
llvm::Constant *Fn = NULL;
if (CGM.ReturnTypeUsesSRet(FnInfo)) {
+ EmitNullReturnInitialization(CGF, Return, ResultType);
Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
: ObjCTypes.getSendStretFn(IsSuper);
} else if (CGM.ReturnTypeUsesFPRet(ResultType)) {
@@ -5629,6 +5639,7 @@ CodeGen::RValue CGObjCNonFragileABIMac::EmitMessageSend(
llvm::Constant *Fn = 0;
std::string Name("\01l_");
if (CGM.ReturnTypeUsesSRet(FnInfo)) {
+ EmitNullReturnInitialization(CGF, Return, ResultType);
if (IsSuper) {
Fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
Name += "objc_msgSendSuper2_stret_fixup";
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
index 4b19aef..ceae66f 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -207,8 +207,9 @@ CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types,
uint64_t ContainingTypeSizeInBits,
unsigned ContainingTypeAlign) {
const llvm::Type *Ty = Types.ConvertTypeForMemRecursive(FD->getType());
- uint64_t TypeSizeInBytes = Types.getTargetData().getTypeAllocSize(Ty);
- uint64_t TypeSizeInBits = TypeSizeInBytes * 8;
+ CharUnits TypeSizeInBytes =
+ CharUnits::fromQuantity(Types.getTargetData().getTypeAllocSize(Ty));
+ uint64_t TypeSizeInBits = Types.getContext().toBits(TypeSizeInBytes);
bool IsSigned = FD->getType()->isSignedIntegerType();
@@ -249,7 +250,7 @@ CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types,
uint64_t AccessStart = FieldOffset - (FieldOffset % AccessWidth);
// Adjust initial access size to fit within record.
- while (AccessWidth > 8 &&
+ while (AccessWidth > Types.getTarget().getCharWidth() &&
AccessStart + AccessWidth > ContainingTypeSizeInBits) {
AccessWidth >>= 1;
AccessStart = FieldOffset - (FieldOffset % AccessWidth);
@@ -262,7 +263,8 @@ CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types,
if (AccessStart + AccessWidth > ContainingTypeSizeInBits) {
// If so, reduce access size to the next smaller power-of-two and retry.
AccessWidth >>= 1;
- assert(AccessWidth >= 8 && "Cannot access under byte size!");
+ assert(AccessWidth >= Types.getTarget().getCharWidth()
+ && "Cannot access under byte size!");
continue;
}
@@ -329,7 +331,7 @@ void CGRecordLayoutBuilder::LayoutBitField(const FieldDecl *D,
if (fieldSize == 0)
return;
- uint64_t nextFieldOffsetInBits = NextFieldOffset.getQuantity() * 8;
+ uint64_t nextFieldOffsetInBits = Types.getContext().toBits(NextFieldOffset);
unsigned numBytesToAppend;
if (fieldOffset < nextFieldOffsetInBits) {
@@ -378,8 +380,10 @@ bool CGRecordLayoutBuilder::LayoutField(const FieldDecl *D,
CheckZeroInitializable(D->getType());
- assert(fieldOffset % 8 == 0 && "FieldOffset is not on a byte boundary!");
- CharUnits fieldOffsetInBytes = CharUnits::fromQuantity(fieldOffset / 8);
+ assert(fieldOffset % Types.getTarget().getCharWidth() == 0
+ && "field offset is not on a byte boundary!");
+ CharUnits fieldOffsetInBytes
+ = Types.getContext().toCharUnitsFromBits(fieldOffset);
const llvm::Type *Ty = Types.ConvertTypeForMemRecursive(D->getType());
CharUnits typeAlignment = getTypeAlignment(Ty);
@@ -396,7 +400,7 @@ bool CGRecordLayoutBuilder::LayoutField(const FieldDecl *D,
const RecordDecl *RD = cast<RecordDecl>(RT->getDecl());
if (const MaxFieldAlignmentAttr *MFAA =
RD->getAttr<MaxFieldAlignmentAttr>()) {
- if (MFAA->getAlignment() != typeAlignment.getQuantity() * 8)
+ if (MFAA->getAlignment() != Types.getContext().toBits(typeAlignment))
return false;
}
}
@@ -728,7 +732,8 @@ bool CGRecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
void CGRecordLayoutBuilder::AppendTailPadding(uint64_t RecordSize) {
assert(RecordSize % 8 == 0 && "Invalid record size!");
- CharUnits RecordSizeInBytes = CharUnits::fromQuantity(RecordSize / 8);
+ CharUnits RecordSizeInBytes =
+ Types.getContext().toCharUnitsFromBits(RecordSize);
assert(NextFieldOffset <= RecordSizeInBytes && "Size mismatch!");
CharUnits AlignedNextFieldOffset =
@@ -920,7 +925,8 @@ CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D) {
// Verify that every component access is within the structure.
uint64_t FieldOffset = SL->getElementOffsetInBits(AI.FieldIndex);
- uint64_t AccessBitOffset = FieldOffset + AI.FieldByteOffset * 8;
+ uint64_t AccessBitOffset = FieldOffset +
+ getContext().toBits(CharUnits::fromQuantity(AI.FieldByteOffset));
assert(AccessBitOffset + AI.AccessWidth <= TypeSizeInBits &&
"Invalid bit-field access (out of range)!");
}
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h
index 67ef414..be646fb 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h
@@ -1555,7 +1555,55 @@ public:
/// EmitAutoVarDecl - Emit an auto variable declaration.
///
/// This function can be called with a null (unreachable) insert point.
- void EmitAutoVarDecl(const VarDecl &D, SpecialInitFn *SpecialInit = 0);
+ void EmitAutoVarDecl(const VarDecl &D);
+
+ class AutoVarEmission {
+ friend class CodeGenFunction;
+
+ const VarDecl *Variable;
+
+ /// The alignment of the variable.
+ CharUnits Alignment;
+
+ /// The address of the alloca. Null if the variable was emitted
+ /// as a global constant.
+ llvm::Value *Address;
+
+ llvm::Value *NRVOFlag;
+
+ /// True if the variable is a __block variable.
+ bool IsByRef;
+
+ /// True if the variable is of aggregate type and has a constant
+ /// initializer.
+ bool IsConstantAggregate;
+
+ struct Invalid {};
+ AutoVarEmission(Invalid) : Variable(0) {}
+
+ AutoVarEmission(const VarDecl &variable)
+ : Variable(&variable), Address(0), NRVOFlag(0),
+ IsByRef(false), IsConstantAggregate(false) {}
+
+ bool wasEmittedAsGlobal() const { return Address == 0; }
+
+ public:
+ static AutoVarEmission invalid() { return AutoVarEmission(Invalid()); }
+
+ /// Returns the address of the object within this declaration.
+ /// Note that this does not chase the forwarding pointer for
+ /// __block decls.
+ llvm::Value *getObjectAddress(CodeGenFunction &CGF) const {
+ if (!IsByRef) return Address;
+
+ return CGF.Builder.CreateStructGEP(Address,
+ CGF.getByRefValueLLVMField(Variable),
+ Variable->getNameAsString());
+ }
+ };
+ AutoVarEmission EmitAutoVarAlloca(const VarDecl &var);
+ void EmitAutoVarInit(const AutoVarEmission &emission);
+ void EmitAutoVarCleanups(const AutoVarEmission &emission);
void EmitStaticVarDecl(const VarDecl &D,
llvm::GlobalValue::LinkageTypes Linkage);
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp
index 9e5d7cf..a8453c3 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp
@@ -97,6 +97,8 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO,
Int32Ty = llvm::Type::getInt32Ty(LLVMContext);
Int64Ty = llvm::Type::getInt64Ty(LLVMContext);
PointerWidthInBits = C.Target.getPointerWidth(0);
+ PointerAlignInBytes =
+ C.toCharUnitsFromBits(C.Target.getPointerAlign(0)).getQuantity();
IntTy = llvm::IntegerType::get(LLVMContext, C.Target.getIntWidth());
IntPtrTy = llvm::IntegerType::get(LLVMContext, PointerWidthInBits);
Int8PtrTy = Int8Ty->getPointerTo(0);
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h
index b6bd37c..73e6ece 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h
@@ -120,8 +120,11 @@ namespace CodeGen {
const llvm::PointerType *Int8PtrPtrTy;
};
- /// The width of an address-zero pointer.
+ /// The width of a pointer into the generic address space.
unsigned char PointerWidthInBits;
+
+ /// The alignment of a pointer into the generic address space.
+ unsigned char PointerAlignInBytes;
};
/// CodeGenModule - This class organizes the cross-function state that is used
@@ -292,6 +295,8 @@ public:
const TargetCodeGenInfo &getTargetCodeGenInfo();
bool isTargetDarwin() const;
+ bool shouldUseTBAA() const { return TBAA != 0; }
+
llvm::MDNode *getTBAAInfo(QualType QTy);
static void DecorateInstruction(llvm::Instruction *Inst,
@@ -386,8 +391,8 @@ public:
unsigned Align,
const VarDecl *variable);
- /// getGlobalUniqueCount - Fetches the global unique block count.
- int getGlobalUniqueCount() { return ++Block.GlobalUniqueCount; }
+ /// getUniqueBlockCount - Fetches the global unique block count.
+ int getUniqueBlockCount() { return ++Block.GlobalUniqueCount; }
/// getBlockDescriptorType - Fetches the type of a generic block
/// descriptor.
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp b/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp
index d74b3f3..2ffc840 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp
@@ -2105,8 +2105,15 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty) const {
RT->getDecl()->hasFlexibleArrayMember())
return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
- // FIXME: mingw64-gcc emits 128-bit struct as i128
- if (Size <= 128 &&
+ // FIXME: mingw-w64-gcc emits 128-bit struct as i128
+ if (Size == 128 &&
+ getContext().Target.getTriple().getOS() == llvm::Triple::MinGW32)
+ return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(),
+ Size));
+
+ // MS x64 ABI requirement: "Any argument that doesn't fit in 8 bytes, or is
+ // not 1, 2, 4, or 8 bytes, must be passed by reference."
+ if (Size <= 64 &&
(Size & (Size - 1)) == 0)
return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(),
Size));
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp
index e4051a1..e305683 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp
@@ -198,7 +198,8 @@ void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &Args,
switch (Type) {
case ToolChain::CST_Libcxx:
- CmdArgs.push_back("-cxx-system-include");
+ CmdArgs.push_back("-nostdinc++");
+ CmdArgs.push_back("-cxx-isystem");
CmdArgs.push_back("/usr/include/c++/v1");
break;
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp
index d94de20..422c572 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp
@@ -46,7 +46,7 @@ Darwin::Darwin(const HostInfo &Host, const llvm::Triple& Triple)
// Compute the initial Darwin version based on the host.
bool HadExtra;
std::string OSName = Triple.getOSName();
- if (!Driver::GetReleaseVersion(&OSName[6],
+ if (!Driver::GetReleaseVersion(&OSName.c_str()[6],
DarwinVersion[0], DarwinVersion[1],
DarwinVersion[2], HadExtra))
getDriver().Diag(clang::diag::err_drv_invalid_darwin_version) << OSName;
@@ -1271,6 +1271,7 @@ Tool &AuroraUX::SelectTool(const Compilation &C, const JobAction &JA) const {
/// Linux toolchain (very bare-bones at the moment).
enum LinuxDistro {
+ ArchLinux,
DebianLenny,
DebianSqueeze,
Exherbo,
@@ -1367,6 +1368,9 @@ static LinuxDistro DetectLinuxDistro(llvm::Triple::ArchType Arch) {
if (!llvm::sys::fs::exists("/etc/exherbo-release", Exists) && Exists)
return Exherbo;
+ if (!llvm::sys::fs::exists("/etc/arch-release", Exists) && Exists)
+ return ArchLinux;
+
return UnknownDistro;
}
@@ -1436,8 +1440,9 @@ Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple)
GccTriple = "i586-suse-linux";
}
- const char* GccVersions[] = {"4.5.1", "4.5", "4.4.5", "4.4.4", "4.4.3", "4.4",
- "4.3.4", "4.3.3", "4.3.2"};
+ const char* GccVersions[] = {"4.5.2", "4.5.1", "4.5", "4.4.5", "4.4.4",
+ "4.4.3", "4.4", "4.3.4", "4.3.3", "4.3.2",
+ "4.3"};
std::string Base = "";
for (unsigned i = 0; i < sizeof(GccVersions)/sizeof(char*); ++i) {
std::string Suffix = GccTriple + "/" + GccVersions[i];
@@ -1498,6 +1503,9 @@ Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple)
Distro == UbuntuKarmic)
ExtraOpts.push_back("--build-id");
+ if (Distro == ArchLinux)
+ Lib = "lib";
+
Paths.push_back(Base + Suffix);
if (HasMultilib(Arch, Distro)) {
if (IsOpenSuse(Distro) && Is32Bits)
diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp
index 0697d54..a2c95fc 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp
@@ -1552,10 +1552,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fobjc-default-synthesize-properties");
}
- // -fobjc-exceptions is default.
- if (!Args.hasFlag(options::OPT_fobjc_exceptions,
- options::OPT_fno_objc_exceptions))
- CmdArgs.push_back("-fno-objc-exceptions");
+ // -fno-objc-exceptions is default.
+ if (IsRewriter || Args.hasFlag(options::OPT_fobjc_exceptions,
+ options::OPT_fno_objc_exceptions))
+ CmdArgs.push_back("-fobjc-exceptions");
}
if (!Args.hasFlag(options::OPT_fassume_sane_operator_new,
@@ -3091,7 +3091,7 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-lgcc");
if (Args.hasArg(options::OPT_pthread))
- CmdArgs.push_back("-pthread");
+ CmdArgs.push_back("-lpthread");
if (!Args.hasArg(options::OPT_shared))
CmdArgs.push_back("-lc");
CmdArgs.push_back("-lgcc");
diff --git a/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp b/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp
index 4a5a51d..a7942e6 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp
@@ -389,7 +389,8 @@ public:
virtual bool ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers,
llvm::StringRef OriginalFileName,
- std::string &SuggestedPredefines) {
+ std::string &SuggestedPredefines,
+ FileManager &FileMgr) {
Predefines = Buffers[0].Data;
for (unsigned I = 1, N = Buffers.size(); I != N; ++I) {
Predefines += Buffers[I].Data;
diff --git a/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp b/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp
index beb5ad2..4b44c48 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp
@@ -78,6 +78,8 @@ static void AnalyzerOptsToArgs(const AnalyzerOptions &Opts,
std::vector<std::string> &Res) {
for (unsigned i = 0, e = Opts.AnalysisList.size(); i != e; ++i)
Res.push_back(getAnalysisName(Opts.AnalysisList[i]));
+ if (Opts.ShowCheckerHelp)
+ Res.push_back("-analyzer-checker-help");
if (Opts.AnalysisStoreOpt != BasicStoreModel) {
Res.push_back("-analyzer-store");
Res.push_back(getAnalysisStoreName(Opts.AnalysisStoreOpt));
@@ -114,8 +116,6 @@ static void AnalyzerOptsToArgs(const AnalyzerOptions &Opts,
Res.push_back("-analyzer-viz-egraph-ubigraph");
if (Opts.EnableExperimentalChecks)
Res.push_back("-analyzer-experimental-checks");
- if (Opts.EnableExperimentalInternalChecks)
- Res.push_back("-analyzer-experimental-internal-checks");
if (Opts.BufferOverflows)
Res.push_back("-analyzer-check-buffer-overflows");
@@ -473,11 +473,6 @@ static void HeaderSearchOptsToArgs(const HeaderSearchOptions &Opts,
Res.push_back(Opts.Sysroot);
}
- for (unsigned i = 0, e = Opts.CXXSystemIncludes.size(); i != e; ++i) {
- Res.push_back("-cxx-system-include");
- Res.push_back(Opts.CXXSystemIncludes[i]);
- }
-
/// User specified include entries.
for (unsigned i = 0, e = Opts.UserEntries.size(); i != e; ++i) {
const HeaderSearchOptions::Entry &E = Opts.UserEntries[i];
@@ -490,6 +485,8 @@ static void HeaderSearchOptsToArgs(const HeaderSearchOptions &Opts,
Res.push_back("-iquote");
} else if (E.Group == frontend::System) {
Res.push_back("-isystem");
+ } else if (E.Group == frontend::CXXSystem) {
+ Res.push_back("-cxx-isystem");
} else {
assert(E.Group == frontend::Angled && "Invalid group!");
Res.push_back(E.IsFramework ? "-F" : "-I");
@@ -588,10 +585,12 @@ static void LangOptsToArgs(const LangOptions &Opts,
Res.push_back("-faltivec");
if (Opts.Exceptions)
Res.push_back("-fexceptions");
+ if (Opts.ObjCExceptions)
+ Res.push_back("-fobjc-exceptions");
+ if (Opts.CXXExceptions)
+ Res.push_back("-fcxx-exceptions");
if (Opts.SjLjExceptions)
Res.push_back("-fsjlj-exceptions");
- if (!Opts.ObjCExceptions)
- Res.push_back("-fno-objc-exceptions");
if (!Opts.RTTI)
Res.push_back("-fno-rtti");
if (Opts.MSBitfields)
@@ -864,6 +863,7 @@ static void ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
Opts.AnalysisDiagOpt = Value;
}
+ Opts.ShowCheckerHelp = Args.hasArg(OPT_analyzer_checker_help);
Opts.VisualizeEGDot = Args.hasArg(OPT_analyzer_viz_egraph_graphviz);
Opts.VisualizeEGUbi = Args.hasArg(OPT_analyzer_viz_egraph_ubigraph);
Opts.AnalyzeAll = Args.hasArg(OPT_analyzer_opt_analyze_headers);
@@ -878,8 +878,6 @@ static void ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
Opts.CFGAddImplicitDtors = Args.hasArg(OPT_analysis_CFGAddImplicitDtors);
Opts.CFGAddInitializers = Args.hasArg(OPT_analysis_CFGAddInitializers);
Opts.EnableExperimentalChecks = Args.hasArg(OPT_analyzer_experimental_checks);
- Opts.EnableExperimentalInternalChecks =
- Args.hasArg(OPT_analyzer_experimental_internal_checks);
Opts.TrimGraph = Args.hasArg(OPT_trim_egraph);
Opts.MaxNodes = Args.getLastArgIntValue(OPT_analyzer_max_nodes, 150000,Diags);
Opts.MaxLoop = Args.getLastArgIntValue(OPT_analyzer_max_loop, 4, Diags);
@@ -894,8 +892,13 @@ static void ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
const Arg *A = *it;
A->claim();
bool enable = (A->getOption().getID() == OPT_analyzer_checker);
- Opts.CheckersControlList.push_back(std::make_pair(A->getValue(Args),
- enable));
+ // We can have a list of comma separated checker names, e.g:
+ // '-analyzer-checker=cocoa,unix'
+ llvm::StringRef checkerList = A->getValue(Args);
+ llvm::SmallVector<llvm::StringRef, 4> checkers;
+ checkerList.split(checkers, ",");
+ for (unsigned i = 0, e = checkers.size(); i != e; ++i)
+ Opts.CheckersControlList.push_back(std::make_pair(checkers[i], enable));
}
}
@@ -1238,7 +1241,6 @@ std::string CompilerInvocation::GetResourcesPath(const char *Argv0,
static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) {
using namespace cc1options;
- Opts.CXXSystemIncludes = Args.getAllArgValues(OPT_cxx_system_include);
Opts.Sysroot = Args.getLastArgValue(OPT_isysroot, "/");
Opts.Verbose = Args.hasArg(OPT_v);
Opts.UseBuiltinIncludes = !Args.hasArg(OPT_nobuiltininc);
@@ -1274,10 +1276,12 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) {
for (arg_iterator it = Args.filtered_begin(OPT_iquote),
ie = Args.filtered_end(); it != ie; ++it)
Opts.AddPath((*it)->getValue(Args), frontend::Quoted, true, false, true);
- for (arg_iterator it = Args.filtered_begin(OPT_isystem, OPT_iwithsysroot),
- ie = Args.filtered_end(); it != ie; ++it)
- Opts.AddPath((*it)->getValue(Args), frontend::System, true, false,
- (*it)->getOption().matches(OPT_iwithsysroot));
+ for (arg_iterator it = Args.filtered_begin(OPT_cxx_isystem, OPT_isystem,
+ OPT_iwithsysroot), ie = Args.filtered_end(); it != ie; ++it)
+ Opts.AddPath((*it)->getValue(Args),
+ ((*it)->getOption().matches(OPT_cxx_isystem) ?
+ frontend::CXXSystem : frontend::System),
+ true, false, (*it)->getOption().matches(OPT_iwithsysroot));
// FIXME: Need options for the various environment variables!
}
@@ -1459,7 +1463,10 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
if (Args.hasArg(OPT_fno_threadsafe_statics))
Opts.ThreadsafeStatics = 0;
Opts.Exceptions = Args.hasArg(OPT_fexceptions);
- Opts.ObjCExceptions = !Args.hasArg(OPT_fno_objc_exceptions);
+ Opts.ObjCExceptions = Args.hasArg(OPT_fobjc_exceptions);
+ Opts.CXXExceptions = Args.hasArg(OPT_fcxx_exceptions);
+ Opts.SjLjExceptions = Args.hasArg(OPT_fsjlj_exceptions);
+
Opts.RTTI = !Args.hasArg(OPT_fno_rtti);
Opts.Blocks = Args.hasArg(OPT_fblocks);
Opts.CharIsSigned = !Args.hasArg(OPT_fno_signed_char);
@@ -1489,8 +1496,6 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.CatchUndefined = Args.hasArg(OPT_fcatch_undefined_behavior);
Opts.EmitAllDecls = Args.hasArg(OPT_femit_all_decls);
Opts.PICLevel = Args.getLastArgIntValue(OPT_pic_level, 0, Diags);
- Opts.SjLjExceptions = Args.hasArg(OPT_fsjlj_exceptions);
- Opts.ObjCExceptions = !Args.hasArg(OPT_fno_objc_exceptions);
Opts.Static = Args.hasArg(OPT_static_define);
Opts.DumpRecordLayouts = Args.hasArg(OPT_fdump_record_layouts);
Opts.DumpVTableLayouts = Args.hasArg(OPT_fdump_vtable_layouts);
@@ -1661,8 +1666,11 @@ void CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
InputKind DashX = ParseFrontendArgs(Res.getFrontendOpts(), *Args, Diags);
ParseCodeGenArgs(Res.getCodeGenOpts(), *Args, DashX, Diags);
ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), *Args);
- if (DashX != IK_AST && DashX != IK_LLVM_IR)
+ if (DashX != IK_AST && DashX != IK_LLVM_IR) {
ParseLangArgs(Res.getLangOpts(), *Args, DashX, Diags);
+ if (Res.getFrontendOpts().ProgramAction == frontend::RewriteObjC)
+ Res.getLangOpts().ObjCExceptions = 1;
+ }
// FIXME: ParsePreprocessorArgs uses the FileManager to read the contents of
// PCH file and find the original header name. Remove the need to do that in
// ParsePreprocessorArgs and remove the FileManager
diff --git a/contrib/llvm/tools/clang/lib/Frontend/DocumentXML.cpp b/contrib/llvm/tools/clang/lib/Frontend/DocumentXML.cpp
index b24ece5..a09db0b 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/DocumentXML.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/DocumentXML.cpp
@@ -14,6 +14,7 @@
#include "clang/Frontend/DocumentXML.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/ASTContext.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/StringExtras.h"
@@ -218,6 +219,10 @@ void DocumentXML::addPtrAttribute(const char* pAttributeName,
addPtrAttribute(pAttributeName, pNNS->getAsNamespace());
break;
}
+ case NestedNameSpecifier::NamespaceAlias: {
+ addPtrAttribute(pAttributeName, pNNS->getAsNamespaceAlias());
+ break;
+ }
case NestedNameSpecifier::TypeSpec: {
addPtrAttribute(pAttributeName, pNNS->getAsType());
break;
diff --git a/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp b/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp
index 69199e2..566b96c 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp
@@ -46,7 +46,9 @@ namespace {
/// a HeaderSearch object. InitHeaderSearch stores several search path lists
/// internally, which can be sent to a HeaderSearch object in one swoop.
class InitHeaderSearch {
- std::vector<DirectoryLookup> IncludeGroup[4];
+ std::vector<std::pair<IncludeDirGroup, DirectoryLookup> > IncludePath;
+ typedef std::vector<std::pair<IncludeDirGroup,
+ DirectoryLookup> >::const_iterator path_iterator;
HeaderSearch& Headers;
bool Verbose;
std::string IncludeSysroot;
@@ -98,7 +100,7 @@ public:
/// Realize - Merges all search path lists into one list and send it to
/// HeaderSearch.
- void Realize();
+ void Realize(const LangOptions &Lang);
};
}
@@ -135,8 +137,8 @@ void InitHeaderSearch::AddPath(const llvm::Twine &Path,
// If the directory exists, add it.
if (const DirectoryEntry *DE = FM.getDirectory(MappedPathStr)) {
- IncludeGroup[Group].push_back(DirectoryLookup(DE, Type, isUserSupplied,
- isFramework));
+ IncludePath.push_back(std::make_pair(Group, DirectoryLookup(DE, Type,
+ isUserSupplied, isFramework)));
return;
}
@@ -146,7 +148,8 @@ void InitHeaderSearch::AddPath(const llvm::Twine &Path,
if (const FileEntry *FE = FM.getFile(MappedPathStr)) {
if (const HeaderMap *HM = Headers.CreateHeaderMap(FE)) {
// It is a headermap, add it to the search path.
- IncludeGroup[Group].push_back(DirectoryLookup(HM, Type,isUserSupplied));
+ IncludePath.push_back(std::make_pair(Group, DirectoryLookup(HM, Type,
+ isUserSupplied)));
return;
}
}
@@ -183,29 +186,29 @@ void InitHeaderSearch::AddGnuCPlusPlusIncludePaths(llvm::StringRef Base,
llvm::StringRef Dir64,
const llvm::Triple &triple) {
// Add the base dir
- AddPath(Base, System, true, false, false);
+ AddPath(Base, CXXSystem, true, false, false);
// Add the multilib dirs
llvm::Triple::ArchType arch = triple.getArch();
bool is64bit = arch == llvm::Triple::ppc64 || arch == llvm::Triple::x86_64;
if (is64bit)
- AddPath(Base + "/" + ArchDir + "/" + Dir64, System, true, false, false);
+ AddPath(Base + "/" + ArchDir + "/" + Dir64, CXXSystem, true, false, false);
else
- AddPath(Base + "/" + ArchDir + "/" + Dir32, System, true, false, false);
+ AddPath(Base + "/" + ArchDir + "/" + Dir32, CXXSystem, true, false, false);
// Add the backward dir
- AddPath(Base + "/backward", System, true, false, false);
+ AddPath(Base + "/backward", CXXSystem, true, false, false);
}
void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(llvm::StringRef Base,
llvm::StringRef Arch,
llvm::StringRef Version) {
AddPath(Base + "/" + Arch + "/" + Version + "/include/c++",
- System, true, false, false);
+ CXXSystem, true, false, false);
AddPath(Base + "/" + Arch + "/" + Version + "/include/c++/" + Arch,
- System, true, false, false);
+ CXXSystem, true, false, false);
AddPath(Base + "/" + Arch + "/" + Version + "/include/c++/backward",
- System, true, false, false);
+ CXXSystem, true, false, false);
}
// FIXME: This probably should goto to some platform utils place.
@@ -576,13 +579,17 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) {
break;
case llvm::Triple::MinGW32:
// mingw-w64-20110207
- AddPath("c:/MinGW/include/c++/4.5.3", System, true, false, false);
- AddPath("c:/MinGW/include/c++/4.5.3/x86_64-w64-mingw32", System, true, false, false);
- AddPath("c:/MinGW/include/c++/4.5.3/backward", System, true, false, false);
+ AddPath("c:/MinGW/include/c++/4.5.3", CXXSystem, true, false, false);
+ AddPath("c:/MinGW/include/c++/4.5.3/x86_64-w64-mingw32", CXXSystem, true,
+ false, false);
+ AddPath("c:/MinGW/include/c++/4.5.3/backward", CXXSystem, true, false,
+ false);
// mingw-w64-20101129
- AddPath("c:/MinGW/include/c++/4.5.2", System, true, false, false);
- AddPath("c:/MinGW/include/c++/4.5.2/x86_64-w64-mingw32", System, true, false, false);
- AddPath("c:/MinGW/include/c++/4.5.2/backward", System, true, false, false);
+ AddPath("c:/MinGW/include/c++/4.5.2", CXXSystem, true, false, false);
+ AddPath("c:/MinGW/include/c++/4.5.2/x86_64-w64-mingw32", CXXSystem, true,
+ false, false);
+ AddPath("c:/MinGW/include/c++/4.5.2/backward", CXXSystem, true, false,
+ false);
// Try gcc 4.5.0
AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.5.0");
// Try gcc 4.4.0
@@ -622,7 +629,7 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) {
}
break;
case llvm::Triple::DragonFly:
- AddPath("/usr/include/c++/4.1", System, true, false, false);
+ AddPath("/usr/include/c++/4.1", CXXSystem, true, false, false);
break;
case llvm::Triple::Linux:
//===------------------------------------------------------------------===//
@@ -821,13 +828,8 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) {
void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang,
const llvm::Triple &triple,
const HeaderSearchOptions &HSOpts) {
- if (Lang.CPlusPlus && HSOpts.UseStandardCXXIncludes) {
- if (!HSOpts.CXXSystemIncludes.empty()) {
- for (unsigned i = 0, e = HSOpts.CXXSystemIncludes.size(); i != e; ++i)
- AddPath(HSOpts.CXXSystemIncludes[i], System, true, false, false);
- } else
- AddDefaultCPlusPlusIncludePaths(triple);
- }
+ if (Lang.CPlusPlus && HSOpts.UseStandardCXXIncludes)
+ AddDefaultCPlusPlusIncludePaths(triple);
AddDefaultCIncludePaths(triple, HSOpts);
@@ -841,11 +843,11 @@ void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang,
/// RemoveDuplicates - If there are duplicate directory entries in the specified
/// search list, remove the later (dead) ones.
static void RemoveDuplicates(std::vector<DirectoryLookup> &SearchList,
- bool Verbose) {
+ unsigned First, bool Verbose) {
llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenDirs;
llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenFrameworkDirs;
llvm::SmallPtrSet<const HeaderMap *, 8> SeenHeaderMaps;
- for (unsigned i = 0; i != SearchList.size(); ++i) {
+ for (unsigned i = First; i != SearchList.size(); ++i) {
unsigned DirToRemove = i;
const DirectoryLookup &CurEntry = SearchList[i];
@@ -920,32 +922,49 @@ static void RemoveDuplicates(std::vector<DirectoryLookup> &SearchList,
}
-void InitHeaderSearch::Realize() {
+void InitHeaderSearch::Realize(const LangOptions &Lang) {
// Concatenate ANGLE+SYSTEM+AFTER chains together into SearchList.
std::vector<DirectoryLookup> SearchList;
- SearchList = IncludeGroup[Angled];
- SearchList.insert(SearchList.end(), IncludeGroup[System].begin(),
- IncludeGroup[System].end());
- SearchList.insert(SearchList.end(), IncludeGroup[After].begin(),
- IncludeGroup[After].end());
- RemoveDuplicates(SearchList, Verbose);
- RemoveDuplicates(IncludeGroup[Quoted], Verbose);
+ SearchList.reserve(IncludePath.size());
+
+ /* Quoted arguments go first. */
+ for (path_iterator it = IncludePath.begin(), ie = IncludePath.end();
+ it != ie; ++it) {
+ if (it->first == Quoted)
+ SearchList.push_back(it->second);
+ }
+ /* Deduplicate and remember index */
+ RemoveDuplicates(SearchList, 0, Verbose);
+ unsigned quoted = SearchList.size();
+
+ for (path_iterator it = IncludePath.begin(), ie = IncludePath.end();
+ it != ie; ++it) {
+ if (it->first == Angled)
+ SearchList.push_back(it->second);
+ }
- // Prepend QUOTED list on the search list.
- SearchList.insert(SearchList.begin(), IncludeGroup[Quoted].begin(),
- IncludeGroup[Quoted].end());
+ for (path_iterator it = IncludePath.begin(), ie = IncludePath.end();
+ it != ie; ++it) {
+ if (it->first == System || (Lang.CPlusPlus && it->first == CXXSystem))
+ SearchList.push_back(it->second);
+ }
+
+ for (path_iterator it = IncludePath.begin(), ie = IncludePath.end();
+ it != ie; ++it) {
+ if (it->first == After)
+ SearchList.push_back(it->second);
+ }
+ RemoveDuplicates(SearchList, quoted, Verbose);
bool DontSearchCurDir = false; // TODO: set to true if -I- is set?
- Headers.SetSearchPaths(SearchList, IncludeGroup[Quoted].size(),
- DontSearchCurDir);
+ Headers.SetSearchPaths(SearchList, quoted, DontSearchCurDir);
// If verbose, print the list of directories that will be searched.
if (Verbose) {
llvm::errs() << "#include \"...\" search starts here:\n";
- unsigned QuotedIdx = IncludeGroup[Quoted].size();
for (unsigned i = 0, e = SearchList.size(); i != e; ++i) {
- if (i == QuotedIdx)
+ if (i == quoted)
llvm::errs() << "#include <...> search starts here:\n";
const char *Name = SearchList[i].getName();
const char *Suffix;
@@ -990,5 +1009,5 @@ void clang::ApplyHeaderSearchOptions(HeaderSearch &HS,
if (HSOpts.UseStandardIncludes)
Init.AddDefaultSystemIncludePaths(Lang, Triple, HSOpts);
- Init.Realize();
+ Init.Realize(Lang);
}
diff --git a/contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp b/contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp
index d0111a5..91b5280 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp
@@ -48,12 +48,13 @@ static void DefineBuiltinMacro(MacroBuilder &Builder, llvm::StringRef Macro,
}
}
-std::string clang::NormalizeDashIncludePath(llvm::StringRef File) {
+std::string clang::NormalizeDashIncludePath(llvm::StringRef File,
+ FileManager &FileMgr) {
// Implicit include paths should be resolved relative to the current
// working directory first, and then use the regular header search
// mechanism. The proper way to handle this is to have the
// predefines buffer located at the current working directory, but
- // it has not file entry. For now, workaround this by using an
+ // it has no file entry. For now, workaround this by using an
// absolute path if we find the file here, and otherwise letting
// header search handle it.
llvm::SmallString<128> Path(File);
@@ -61,21 +62,25 @@ std::string clang::NormalizeDashIncludePath(llvm::StringRef File) {
bool exists;
if (llvm::sys::fs::exists(Path.str(), exists) || !exists)
Path = File;
+ else if (exists)
+ FileMgr.getFile(File);
return Lexer::Stringify(Path.str());
}
/// AddImplicitInclude - Add an implicit #include of the specified file to the
/// predefines buffer.
-static void AddImplicitInclude(MacroBuilder &Builder, llvm::StringRef File) {
+static void AddImplicitInclude(MacroBuilder &Builder, llvm::StringRef File,
+ FileManager &FileMgr) {
Builder.append("#include \"" +
- llvm::Twine(NormalizeDashIncludePath(File)) + "\"");
+ llvm::Twine(NormalizeDashIncludePath(File, FileMgr)) + "\"");
}
static void AddImplicitIncludeMacros(MacroBuilder &Builder,
- llvm::StringRef File) {
+ llvm::StringRef File,
+ FileManager &FileMgr) {
Builder.append("#__include_macros \"" +
- llvm::Twine(NormalizeDashIncludePath(File)) + "\"");
+ llvm::Twine(NormalizeDashIncludePath(File, FileMgr)) + "\"");
// Marker token to stop the __include_macros fetch loop.
Builder.append("##"); // ##?
}
@@ -94,7 +99,7 @@ static void AddImplicitIncludePTH(MacroBuilder &Builder, Preprocessor &PP,
return;
}
- AddImplicitInclude(Builder, OriginalFile);
+ AddImplicitInclude(Builder, OriginalFile, PP.getFileManager());
}
/// PickFP - This is used to pick a value based on the FP semantics of the
@@ -169,15 +174,10 @@ static void DefineFloatMacros(MacroBuilder &Builder, llvm::StringRef Prefix,
/// signedness of 'isSigned' and with a value suffix of 'ValSuffix' (e.g. LL).
static void DefineTypeSize(llvm::StringRef MacroName, unsigned TypeWidth,
llvm::StringRef ValSuffix, bool isSigned,
- MacroBuilder& Builder) {
- long long MaxVal;
- if (isSigned) {
- assert(TypeWidth != 1);
- MaxVal = ~0ULL >> (65-TypeWidth);
- } else
- MaxVal = ~0ULL >> (64-TypeWidth);
-
- Builder.defineMacro(MacroName, llvm::Twine(MaxVal) + ValSuffix);
+ MacroBuilder &Builder) {
+ llvm::APInt MaxVal = isSigned ? llvm::APInt::getSignedMaxValue(TypeWidth)
+ : llvm::APInt::getMaxValue(TypeWidth);
+ Builder.defineMacro(MacroName, MaxVal.toString(10, isSigned) + ValSuffix);
}
/// DefineTypeSize - An overloaded helper that uses TargetInfo to determine
@@ -590,7 +590,8 @@ void clang::InitializePreprocessor(Preprocessor &PP,
// If -imacros are specified, include them now. These are processed before
// any -include directives.
for (unsigned i = 0, e = InitOpts.MacroIncludes.size(); i != e; ++i)
- AddImplicitIncludeMacros(Builder, InitOpts.MacroIncludes[i]);
+ AddImplicitIncludeMacros(Builder, InitOpts.MacroIncludes[i],
+ PP.getFileManager());
// Process -include directives.
for (unsigned i = 0, e = InitOpts.Includes.size(); i != e; ++i) {
@@ -598,7 +599,7 @@ void clang::InitializePreprocessor(Preprocessor &PP,
if (Path == InitOpts.ImplicitPTHInclude)
AddImplicitIncludePTH(Builder, PP, Path);
else
- AddImplicitInclude(Builder, Path);
+ AddImplicitInclude(Builder, Path, PP.getFileManager());
}
// Exit the command line and go back to <built-in> (2 is LC_LEAVE).
diff --git a/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticPrinter.cpp b/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticPrinter.cpp
index 04c6a68..0849153 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticPrinter.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticPrinter.cpp
@@ -905,9 +905,21 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
std::string OptionName;
if (DiagOpts->ShowOptionNames) {
+ // Was this a warning mapped to an error using -Werror or pragma?
+ if (Level == Diagnostic::Error &&
+ DiagnosticIDs::isBuiltinWarningOrExtension(Info.getID())) {
+ diag::Mapping mapping = diag::MAP_IGNORE;
+ Info.getDiags()->getDiagnosticLevel(Info.getID(), Info.getLocation(),
+ &mapping);
+ if (mapping == diag::MAP_WARNING)
+ OptionName += "-Werror";
+ }
+
if (const char *
Opt = DiagnosticIDs::getWarningOptionForDiag(Info.getID())) {
- OptionName = "-W";
+ if (!OptionName.empty())
+ OptionName += ',';
+ OptionName += "-W";
OptionName += Opt;
} else if (Info.getID() == diag::fatal_too_many_errors) {
OptionName = "-ferror-limit=";
diff --git a/contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticsClient.cpp b/contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticsClient.cpp
index 51b351f..fff417e 100644
--- a/contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticsClient.cpp
+++ b/contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticsClient.cpp
@@ -369,7 +369,7 @@ static unsigned PrintProblem(Diagnostic &Diags, SourceManager *SourceMgr,
if (I->first.isInvalid() || !SourceMgr)
OS << "\n (frontend)";
else
- OS << "\n Line " << SourceMgr->getInstantiationLineNumber(I->first);
+ OS << "\n Line " << SourceMgr->getPresumedLineNumber(I->first);
OS << ": " << I->second;
}
@@ -391,7 +391,7 @@ static unsigned PrintProblem(Diagnostic &Diags, SourceManager *SourceMgr,
if (D.Location.isInvalid() || !SourceMgr)
OS << "\n (frontend)";
else
- OS << "\n Line " << SourceMgr->getInstantiationLineNumber(D.Location);
+ OS << "\n Line " << SourceMgr->getPresumedLineNumber(D.Location);
OS << ": " << D.Text;
}
@@ -413,12 +413,12 @@ static unsigned CheckLists(Diagnostic &Diags, SourceManager &SourceMgr,
for (DirectiveList::iterator I = Left.begin(), E = Left.end(); I != E; ++I) {
Directive& D = **I;
- unsigned LineNo1 = SourceMgr.getInstantiationLineNumber(D.Location);
+ unsigned LineNo1 = SourceMgr.getPresumedLineNumber(D.Location);
for (unsigned i = 0; i < D.Count; ++i) {
DiagList::iterator II, IE;
for (II = Right.begin(), IE = Right.end(); II != IE; ++II) {
- unsigned LineNo2 = SourceMgr.getInstantiationLineNumber(II->first);
+ unsigned LineNo2 = SourceMgr.getPresumedLineNumber(II->first);
if (LineNo1 != LineNo2)
continue;
diff --git a/contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index 4bb85e7..65fad6d 100644
--- a/contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -108,6 +108,12 @@ bool clang::ExecuteCompilerInvocation(CompilerInstance *Clang) {
return 0;
}
+ // Honor -analyzer-checker-help.
+ if (Clang->getAnalyzerOpts().ShowCheckerHelp) {
+ ento::printCheckerHelp(llvm::outs());
+ return 0;
+ }
+
// Honor -version.
//
// FIXME: Use a better -version message?
diff --git a/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp b/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp
index 0f0d25b..3e871ae 100644
--- a/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp
@@ -86,6 +86,7 @@ void Preprocessor::DiscardUntilEndOfDirective() {
Token Tmp;
do {
LexUnexpandedToken(Tmp);
+ assert(Tmp.isNot(tok::eof) && "EOF seen while discarding directive tokens");
} while (Tmp.isNot(tok::eom));
}
@@ -167,10 +168,12 @@ void Preprocessor::CheckEndOfDirective(const char *DirType, bool EnableMacros) {
if (Tmp.isNot(tok::eom)) {
// Add a fixit in GNU/C99/C++ mode. Don't offer a fixit for strict-C89,
- // because it is more trouble than it is worth to insert /**/ and check that
- // there is no /**/ in the range also.
+ // or if this is a macro-style preprocessing directive, because it is more
+ // trouble than it is worth to insert /**/ and check that there is no /**/
+ // in the range also.
FixItHint Hint;
- if (Features.GNUMode || Features.C99 || Features.CPlusPlus)
+ if ((Features.GNUMode || Features.C99 || Features.CPlusPlus) &&
+ !CurTokenLexer)
Hint = FixItHint::CreateInsertion(Tmp.getLocation(),"//");
Diag(Tmp, diag::ext_pp_extra_tokens_at_eol) << DirType << Hint;
DiscardUntilEndOfDirective();
diff --git a/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp b/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp
index f0475bc..80d3bb1 100644
--- a/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp
@@ -110,7 +110,8 @@ void Preprocessor::HandlePragmaDirective(unsigned Introducer) {
PragmaHandlers->HandlePragma(*this, PragmaIntroducerKind(Introducer), Tok);
// If the pragma handler didn't read the rest of the line, consume it now.
- if (CurPPLexer && CurPPLexer->ParsingPreprocessorDirective)
+ if ((CurTokenLexer && CurTokenLexer->isParsingPreprocessorDirective())
+ || (CurPPLexer && CurPPLexer->ParsingPreprocessorDirective))
DiscardUntilEndOfDirective();
}
@@ -174,7 +175,22 @@ void Preprocessor::Handle_Pragma(Token &Tok) {
}
}
- Handle_Pragma(PIK__Pragma, StrVal, PragmaLoc, RParenLoc);
+ // Plop the string (including the newline and trailing null) into a buffer
+ // where we can lex it.
+ Token TmpTok;
+ TmpTok.startToken();
+ CreateString(&StrVal[0], StrVal.size(), TmpTok);
+ SourceLocation TokLoc = TmpTok.getLocation();
+
+ // Make and enter a lexer object so that we lex and expand the tokens just
+ // like any others.
+ Lexer *TL = Lexer::Create_PragmaLexer(TokLoc, PragmaLoc, RParenLoc,
+ StrVal.size(), *this);
+
+ EnterSourceFileWithLexer(TL, 0);
+
+ // With everything set up, lex this as a #pragma directive.
+ HandlePragmaDirective(PIK__Pragma);
// Finally, return whatever came after the pragma directive.
return Lex(Tok);
@@ -193,16 +209,16 @@ void Preprocessor::HandleMicrosoft__pragma(Token &Tok) {
return;
}
- // Get the tokens enclosed within the __pragma().
+ // Get the tokens enclosed within the __pragma(), as well as the final ')'.
llvm::SmallVector<Token, 32> PragmaToks;
int NumParens = 0;
Lex(Tok);
while (Tok.isNot(tok::eof)) {
+ PragmaToks.push_back(Tok);
if (Tok.is(tok::l_paren))
NumParens++;
else if (Tok.is(tok::r_paren) && NumParens-- == 0)
break;
- PragmaToks.push_back(Tok);
Lex(Tok);
}
@@ -211,45 +227,23 @@ void Preprocessor::HandleMicrosoft__pragma(Token &Tok) {
return;
}
- // Build the pragma string.
- std::string StrVal = " ";
- for (llvm::SmallVector<Token, 32>::iterator I =
- PragmaToks.begin(), E = PragmaToks.end(); I != E; ++I) {
- StrVal += getSpelling(*I);
- }
-
- SourceLocation RParenLoc = Tok.getLocation();
-
- Handle_Pragma(PIK___pragma, StrVal, PragmaLoc, RParenLoc);
+ PragmaToks.front().setFlag(Token::LeadingSpace);
- // Finally, return whatever came after the pragma directive.
- return Lex(Tok);
-}
+ // Replace the ')' with an EOM to mark the end of the pragma.
+ PragmaToks.back().setKind(tok::eom);
-void Preprocessor::Handle_Pragma(unsigned Introducer,
- const std::string &StrVal,
- SourceLocation PragmaLoc,
- SourceLocation RParenLoc) {
+ Token *TokArray = new Token[PragmaToks.size()];
+ std::copy(PragmaToks.begin(), PragmaToks.end(), TokArray);
- // Plop the string (including the newline and trailing null) into a buffer
- // where we can lex it.
- Token TmpTok;
- TmpTok.startToken();
- CreateString(&StrVal[0], StrVal.size(), TmpTok);
- SourceLocation TokLoc = TmpTok.getLocation();
-
- // Make and enter a lexer object so that we lex and expand the tokens just
- // like any others.
- Lexer *TL = Lexer::Create_PragmaLexer(TokLoc, PragmaLoc, RParenLoc,
- StrVal.size(), *this);
-
- EnterSourceFileWithLexer(TL, 0);
+ // Push the tokens onto the stack.
+ EnterTokenStream(TokArray, PragmaToks.size(), true, true);
// With everything set up, lex this as a #pragma directive.
- HandlePragmaDirective(Introducer);
-}
-
+ HandlePragmaDirective(PIK___pragma);
+ // Finally, return whatever came after the pragma directive.
+ return Lex(Tok);
+}
/// HandlePragmaOnce - Handle #pragma once. OnceTok is the 'once'.
///
diff --git a/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp b/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp
index ea39b47..caa44bf 100644
--- a/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp
@@ -543,6 +543,11 @@ unsigned TokenLexer::isNextTokenLParen() const {
return Tokens[CurToken].is(tok::l_paren);
}
+/// isParsingPreprocessorDirective - Return true if we are in the middle of a
+/// preprocessor directive.
+bool TokenLexer::isParsingPreprocessorDirective() const {
+ return Tokens[NumTokens-1].is(tok::eom) && !isAtEnd();
+}
/// HandleMicrosoftCommentPaste - In microsoft compatibility mode, /##/ pastes
/// together to form a comment that comments out everything in the current
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp
index 5a7fc7e..077edd7 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp
@@ -667,6 +667,8 @@ Decl *Parser::ParseDeclarationAfterDeclarator(Declarator &D,
Actions.ActOnUninitializedDecl(ThisDecl, TypeContainsAuto);
}
+ Actions.FinalizeDeclaration(ThisDecl);
+
return ThisDecl;
}
@@ -954,8 +956,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
goto DoneWithDeclSpec;
CXXScopeSpec SS;
- SS.setScopeRep((NestedNameSpecifier*) Tok.getAnnotationValue());
- SS.setRange(Tok.getAnnotationRange());
+ Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(),
+ Tok.getAnnotationRange(),
+ SS);
// We are looking for a qualified typename.
Token Next = NextToken();
@@ -1244,9 +1247,18 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
DiagID, getLang());
break;
case tok::kw_auto:
- if (getLang().CPlusPlus0x)
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec,
- DiagID);
+ if (getLang().CPlusPlus0x || getLang().ObjC2) {
+ if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) {
+ isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, Loc, PrevSpec,
+ DiagID, getLang());
+ if (!isInvalid)
+ Diag(Tok, diag::auto_storage_class)
+ << FixItHint::CreateRemoval(DS.getStorageClassSpecLoc());
+ }
+ else
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec,
+ DiagID);
+ }
else
isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, Loc, PrevSpec,
DiagID, getLang());
@@ -1459,6 +1471,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
else
Diag(Tok, DiagID) << PrevSpec;
}
+
DS.SetRangeEnd(Tok.getLocation());
ConsumeToken();
}
@@ -1973,6 +1986,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
}
}
+ bool AllowFixedUnderlyingType = getLang().CPlusPlus0x || getLang().Microsoft;
bool IsScopedEnum = false;
bool IsScopedUsingClassTag = false;
@@ -1984,7 +1998,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
}
// Must have either 'enum name' or 'enum {...}'.
- if (Tok.isNot(tok::identifier) && Tok.isNot(tok::l_brace)) {
+ if (Tok.isNot(tok::identifier) && Tok.isNot(tok::l_brace) &&
+ (AllowFixedUnderlyingType && Tok.isNot(tok::colon))) {
Diag(Tok, diag::err_expected_ident_lbrace);
// Skip the rest of this declarator, up until the comma or semicolon.
@@ -2011,7 +2026,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
TypeResult BaseType;
// Parse the fixed underlying type.
- if (getLang().CPlusPlus0x && Tok.is(tok::colon)) {
+ if (AllowFixedUnderlyingType && Tok.is(tok::colon)) {
bool PossibleBitfield = false;
if (getCurScope()->getFlags() & Scope::ClassScope) {
// If we're in class scope, this can either be an enum declaration with
@@ -2043,7 +2058,9 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
// Consume the ':'.
ConsumeToken();
- if (isCXXDeclarationSpecifier() != TPResult::True()) {
+ if ((getLang().CPlusPlus &&
+ isCXXDeclarationSpecifier() != TPResult::True()) ||
+ (!getLang().CPlusPlus && !isDeclarationSpecifier(true))) {
// We'll parse this as a bitfield later.
PossibleBitfield = true;
TPA.Revert();
@@ -2060,6 +2077,10 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
if (!PossibleBitfield) {
SourceRange Range;
BaseType = ParseTypeName(&Range);
+
+ if (!getLang().CPlusPlus0x)
+ Diag(StartLoc, diag::ext_ms_enum_fixed_underlying_type)
+ << Range;
}
}
@@ -2090,6 +2111,14 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
return;
}
+ if (!Name && TUK != Sema::TUK_Definition) {
+ Diag(Tok, diag::err_enumerator_unnamed_no_def);
+
+ // Skip the rest of this declarator, up until the comma or semicolon.
+ SkipUntil(tok::comma, true);
+ return;
+ }
+
bool Owned = false;
bool IsDependent = false;
SourceLocation TSTLoc = NameLoc.isValid()? NameLoc : StartLoc;
@@ -2734,6 +2763,9 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
if (Kind == tok::star)
// Remember that we parsed a pointer type, and remember the type-quals.
D.AddTypeInfo(DeclaratorChunk::getPointer(DS.getTypeQualifiers(), Loc,
+ DS.getConstSpecLoc(),
+ DS.getVolatileSpecLoc(),
+ DS.getRestrictSpecLoc(),
DS.takeAttributes()),
SourceLocation());
else
@@ -3730,4 +3762,3 @@ bool Parser::TryAltiVecTokenOutOfLine(DeclSpec &DS, SourceLocation Loc,
}
return false;
}
-
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp
index e73578f..d8db711 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp
@@ -65,8 +65,9 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
"Call sites of this function should be guarded by checking for C++");
if (Tok.is(tok::annot_cxxscope)) {
- SS.setScopeRep(static_cast<NestedNameSpecifier*>(Tok.getAnnotationValue()));
- SS.setRange(Tok.getAnnotationRange());
+ Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(),
+ Tok.getAnnotationRange(),
+ SS);
ConsumeToken();
return false;
}
@@ -80,10 +81,9 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
return false;
// '::' - Global scope qualifier.
- SourceLocation CCLoc = ConsumeToken();
- SS.setBeginLoc(CCLoc);
- SS.setScopeRep(Actions.ActOnCXXGlobalScopeSpecifier(getCurScope(), CCLoc));
- SS.setEndLoc(CCLoc);
+ if (Actions.ActOnCXXGlobalScopeSpecifier(getCurScope(), ConsumeToken(), SS))
+ return true;
+
HasScopeSpecifier = true;
}
@@ -208,20 +208,20 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
SourceLocation CCLoc = ConsumeToken();
- if (!HasScopeSpecifier) {
- SS.setBeginLoc(TypeToken.getLocation());
+ if (!HasScopeSpecifier)
HasScopeSpecifier = true;
- }
if (ParsedType T = getTypeAnnotation(TypeToken)) {
- CXXScopeTy *Scope =
- Actions.ActOnCXXNestedNameSpecifier(getCurScope(), SS, T,
- TypeToken.getAnnotationRange(),
- CCLoc);
- SS.setScopeRep(Scope);
- } else
- SS.setScopeRep(0);
- SS.setEndLoc(CCLoc);
+ if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(), T, CCLoc, SS))
+ SS.SetInvalid(SourceRange(SS.getBeginLoc(), CCLoc));
+
+ continue;
+ } else {
+ SourceLocation Start = SS.getBeginLoc().isValid()? SS.getBeginLoc()
+ : CCLoc;
+ SS.SetInvalid(SourceRange(Start, CCLoc));
+ }
+
continue;
}
@@ -245,7 +245,9 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
// If we get foo:bar, this is almost certainly a typo for foo::bar. Recover
// and emit a fixit hint for it.
if (Next.is(tok::colon) && !ColonIsSacred) {
- if (Actions.IsInvalidUnlessNestedName(getCurScope(), SS, II, ObjectType,
+ if (Actions.IsInvalidUnlessNestedName(getCurScope(), SS, II,
+ Tok.getLocation(),
+ Next.getLocation(), ObjectType,
EnteringContext) &&
// If the token after the colon isn't an identifier, it's still an
// error, but they probably meant something else strange so don't
@@ -274,16 +276,11 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
"NextToken() not working properly!");
SourceLocation CCLoc = ConsumeToken();
- if (!HasScopeSpecifier) {
- SS.setBeginLoc(IdLoc);
- HasScopeSpecifier = true;
- }
-
- if (!SS.isInvalid())
- SS.setScopeRep(
- Actions.ActOnCXXNestedNameSpecifier(getCurScope(), SS, IdLoc, CCLoc, II,
- ObjectType, EnteringContext));
- SS.setEndLoc(CCLoc);
+ HasScopeSpecifier = true;
+ if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(), II, IdLoc, CCLoc,
+ ObjectType, EnteringContext, SS))
+ SS.SetInvalid(SourceRange(IdLoc, CCLoc));
+
continue;
}
@@ -836,6 +833,8 @@ bool Parser::ParseCXXCondition(ExprResult &ExprOut,
// FIXME: Build a reference to this declaration? Convert it to bool?
// (This is currently handled by Sema).
+
+ Actions.FinalizeDeclaration(DeclOut);
return false;
}
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp
index 8387c88..59ced8b 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp
@@ -829,7 +829,7 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
TemplateId->RAngleLoc = RAngleLoc;
ParsedTemplateArgument *Args = TemplateId->getTemplateArgs();
for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); Arg != ArgEnd; ++Arg)
- Args[Arg] = TemplateArgs[Arg];
+ Args[Arg] = ParsedTemplateArgument(TemplateArgs[Arg]);
Tok.setAnnotationValue(TemplateId);
if (TemplateKWLoc.isValid())
Tok.setLocation(TemplateKWLoc);
diff --git a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp
index a50763a..07e592c 100644
--- a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp
+++ b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp
@@ -296,6 +296,10 @@ bool Parser::SkipUntil(const tok::TokenKind *Toks, unsigned NumToks,
case tok::wide_string_literal:
ConsumeStringToken();
break;
+
+ case tok::at:
+ return false;
+
case tok::semi:
if (StopAtSemi)
return false;
@@ -1159,7 +1163,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
else
PP.EnterToken(Tok);
Tok.setKind(tok::annot_cxxscope);
- Tok.setAnnotationValue(SS.getScopeRep());
+ Tok.setAnnotationValue(Actions.SaveNestedNameSpecifierAnnotation(SS));
Tok.setAnnotationRange(SS.getRange());
// In case the tokens were cached, have Preprocessor replace them
@@ -1196,7 +1200,7 @@ bool Parser::TryAnnotateCXXScopeToken(bool EnteringContext) {
else
PP.EnterToken(Tok);
Tok.setKind(tok::annot_cxxscope);
- Tok.setAnnotationValue(SS.getScopeRep());
+ Tok.setAnnotationValue(Actions.SaveNestedNameSpecifierAnnotation(SS));
Tok.setAnnotationRange(SS.getRange());
// In case the tokens were cached, have Preprocessor replace them with the
diff --git a/contrib/llvm/tools/clang/lib/Rewrite/RewriteObjC.cpp b/contrib/llvm/tools/clang/lib/Rewrite/RewriteObjC.cpp
index 875a0c7..0263f65 100644
--- a/contrib/llvm/tools/clang/lib/Rewrite/RewriteObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/Rewrite/RewriteObjC.cpp
@@ -298,6 +298,7 @@ namespace {
Stmt *RewriteObjCThrowStmt(ObjCAtThrowStmt *S);
Stmt *RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
SourceLocation OrigEnd);
+ bool IsDeclStmtInForeachHeader(DeclStmt *DS);
CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,
Expr **args, unsigned nargs,
SourceLocation StartLoc=SourceLocation(),
@@ -1348,13 +1349,13 @@ Stmt *RewriteObjC::RewritePropertyOrImplicitGetter(Expr *PropOrGetterRefExpr) {
MsgExpr = ObjCMessageExpr::Create(*Context,
Ty.getNonReferenceType(),
Expr::getValueKindForType(Ty),
- /*FIXME?*/SourceLocation(),
+ PropOrGetterRefExpr->getLocStart(),
SuperLocation,
/*IsInstanceSuper=*/true,
SuperTy,
Sel, SelectorLoc, OMD,
0, 0,
- /*FIXME:*/SourceLocation());
+ PropOrGetterRefExpr->getLocEnd());
else {
assert (Receiver && "RewritePropertyOrImplicitGetter - Receiver is null");
if (Expr *Exp = dyn_cast<Expr>(Receiver))
@@ -1364,14 +1365,15 @@ Stmt *RewriteObjC::RewritePropertyOrImplicitGetter(Expr *PropOrGetterRefExpr) {
MsgExpr = ObjCMessageExpr::Create(*Context,
Ty.getNonReferenceType(),
Expr::getValueKindForType(Ty),
- /*FIXME:*/SourceLocation(),
+ PropOrGetterRefExpr->getLocStart(),
cast<Expr>(Receiver),
Sel, SelectorLoc, OMD,
0, 0,
- /*FIXME:*/SourceLocation());
+ PropOrGetterRefExpr->getLocEnd());
}
- Stmt *ReplacingStmt = SynthMessageExpr(MsgExpr);
+ Stmt *ReplacingStmt = SynthMessageExpr(MsgExpr, MsgExpr->getLocStart(),
+ MsgExpr->getLocEnd());
if (!PropParentMap)
PropParentMap = new ParentMap(CurrentBody);
@@ -2986,9 +2988,9 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
// Make all implicit casts explicit...ICE comes in handy:-)
if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(userExpr)) {
// Reuse the ICE type, it is exactly what the doctor ordered.
- QualType type = ICE->getType()->isObjCQualifiedIdType()
- ? Context->getObjCIdType()
- : ICE->getType();
+ QualType type = ICE->getType();
+ if (needToScanForQualifiers(type))
+ type = Context->getObjCIdType();
// Make sure we convert "type (^)(...)" to "type (*)(...)".
(void)convertBlockPointerToFunctionPointer(type);
userExpr = NoTypeInfoCStyleCastExpr(Context, type, CK_BitCast,
@@ -5459,6 +5461,13 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
return NewRep;
}
+bool RewriteObjC::IsDeclStmtInForeachHeader(DeclStmt *DS) {
+ if (const ObjCForCollectionStmt * CS =
+ dyn_cast<ObjCForCollectionStmt>(Stmts.back()))
+ return CS->getElement() == DS;
+ return false;
+}
+
//===----------------------------------------------------------------------===//
// Function Body / Expression rewriting
//===----------------------------------------------------------------------===//
@@ -5681,7 +5690,7 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
// for (id <FooProtocol> index in someArray) ;
// This is because RewriteObjCForCollectionStmt() does textual rewriting
// and it depends on the original text locations/positions.
- if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
+ if (Stmts.empty() || !IsDeclStmtInForeachHeader(DS))
RewriteObjCQualifiedInterfaceTypes(*DS->decl_begin());
// Blocks rewrite rules.
diff --git a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 63f561d..6a42224 100644
--- a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -15,6 +15,7 @@
#include "clang/Sema/AnalysisBasedWarnings.h"
#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/ScopeInfo.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/AST/DeclObjC.h"
@@ -26,6 +27,8 @@
#include "clang/Analysis/AnalysisContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/Analyses/ReachableCode.h"
+#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
+#include "clang/Analysis/CFGStmtMap.h"
#include "clang/Analysis/Analyses/UninitializedValuesV2.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/Support/Casting.h"
@@ -289,7 +292,7 @@ struct CheckFallThroughDiagnostics {
/// of a noreturn function. We assume that functions and blocks not marked
/// noreturn will return.
static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
- QualType BlockTy,
+ const BlockExpr *blkExpr,
const CheckFallThroughDiagnostics& CD,
AnalysisContext &AC) {
@@ -306,6 +309,7 @@ static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
HasNoReturn = MD->hasAttr<NoReturnAttr>();
}
else if (isa<BlockDecl>(D)) {
+ QualType BlockTy = blkExpr->getType();
if (const FunctionType *FT =
BlockTy->getPointeeType()->getAs<FunctionType>()) {
if (FT->getResultType()->isVoidType())
@@ -477,11 +481,20 @@ clang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s) : S(s) {
Diagnostic::Ignored);
}
+static void flushDiagnostics(Sema &S, sema::FunctionScopeInfo *fscope) {
+ for (llvm::SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator
+ i = fscope->PossiblyUnreachableDiags.begin(),
+ e = fscope->PossiblyUnreachableDiags.end();
+ i != e; ++i) {
+ const sema::PossiblyUnreachableDiag &D = *i;
+ S.Diag(D.Loc, D.PD);
+ }
+}
+
void clang::sema::
AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
- const Decl *D, QualType BlockTy) {
-
- assert(BlockTy.isNull() || isa<BlockDecl>(D));
+ sema::FunctionScopeInfo *fscope,
+ const Decl *D, const BlockExpr *blkExpr) {
// We avoid doing analysis-based warnings when there are errors for
// two reasons:
@@ -491,9 +504,6 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
// time.
Diagnostic &Diags = S.getDiagnostics();
- if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred())
- return;
-
// Do not do any analysis for declarations in system headers if we are
// going to just ignore them.
if (Diags.getSuppressSystemWarnings() &&
@@ -504,6 +514,12 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
if (cast<DeclContext>(D)->isDependentContext())
return;
+ if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred()) {
+ // Flush out any possibly unreachable diagnostics.
+ flushDiagnostics(S, fscope);
+ return;
+ }
+
const Stmt *Body = D->getBody();
assert(Body);
@@ -512,12 +528,40 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
AnalysisContext AC(D, 0, /*useUnoptimizedCFG=*/false, /*addehedges=*/false,
/*addImplicitDtors=*/true, /*addInitializers=*/true);
+ // Emit delayed diagnostics.
+ if (!fscope->PossiblyUnreachableDiags.empty()) {
+ bool analyzed = false;
+ if (CFGReachabilityAnalysis *cra = AC.getCFGReachablityAnalysis())
+ if (CFGStmtMap *csm = AC.getCFGStmtMap()) {
+ analyzed = true;
+ for (llvm::SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator
+ i = fscope->PossiblyUnreachableDiags.begin(),
+ e = fscope->PossiblyUnreachableDiags.end();
+ i != e; ++i) {
+ const sema::PossiblyUnreachableDiag &D = *i;
+ if (const CFGBlock *blk = csm->getBlock(D.stmt)) {
+ // Can this block be reached from the entrance?
+ if (cra->isReachable(&AC.getCFG()->getEntry(), blk))
+ S.Diag(D.Loc, D.PD);
+ }
+ else {
+ // Emit the warning anyway if we cannot map to a basic block.
+ S.Diag(D.Loc, D.PD);
+ }
+ }
+ }
+
+ if (!analyzed)
+ flushDiagnostics(S, fscope);
+ }
+
+
// Warning: check missing 'return'
if (P.enableCheckFallThrough) {
const CheckFallThroughDiagnostics &CD =
(isa<BlockDecl>(D) ? CheckFallThroughDiagnostics::MakeForBlock()
: CheckFallThroughDiagnostics::MakeForFunction(D));
- CheckFallThroughForBody(S, D, Body, BlockTy, CD, AC);
+ CheckFallThroughForBody(S, D, Body, blkExpr, CD, AC);
}
// Warning: check for unreachable code
@@ -550,21 +594,3 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
}
}
}
-
-void clang::sema::
-AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
- const BlockExpr *E) {
- return IssueWarnings(P, E->getBlockDecl(), E->getType());
-}
-
-void clang::sema::
-AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
- const ObjCMethodDecl *D) {
- return IssueWarnings(P, D, QualType());
-}
-
-void clang::sema::
-AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
- const FunctionDecl *D) {
- return IssueWarnings(P, D, QualType());
-}
diff --git a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp
index bc289ec..037594a 100644
--- a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp
@@ -14,6 +14,9 @@
#include "clang/Parse/ParseDiagnostic.h" // FIXME: remove this back-dependency!
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ParsedTemplate.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/TypeLoc.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/LangOptions.h"
#include "llvm/ADT/STLExtras.h"
@@ -44,6 +47,239 @@ void UnqualifiedId::setConstructorTemplateId(TemplateIdAnnotation *TemplateId) {
EndLocation = TemplateId->RAngleLoc;
}
+CXXScopeSpec::CXXScopeSpec(const CXXScopeSpec &Other)
+ : Range(Other.Range), ScopeRep(Other.ScopeRep), Buffer(0),
+ BufferSize(Other.BufferSize), BufferCapacity(Other.BufferSize)
+{
+ if (BufferSize) {
+ Buffer = static_cast<char *>(malloc(BufferSize));
+ memcpy(Buffer, Other.Buffer, BufferSize);
+ }
+}
+
+CXXScopeSpec &CXXScopeSpec::operator=(const CXXScopeSpec &Other) {
+ Range = Other.Range;
+ ScopeRep = Other.ScopeRep;
+ if (Buffer && Other.Buffer && BufferCapacity >= Other.BufferSize) {
+ // Re-use our storage.
+ BufferSize = Other.BufferSize;
+ memcpy(Buffer, Other.Buffer, BufferSize);
+ return *this;
+ }
+
+ if (BufferCapacity)
+ free(Buffer);
+ if (Other.Buffer) {
+ BufferSize = Other.BufferSize;
+ BufferCapacity = BufferSize;
+ Buffer = static_cast<char *>(malloc(BufferSize));
+ memcpy(Buffer, Other.Buffer, BufferSize);
+ } else {
+ Buffer = 0;
+ BufferSize = 0;
+ BufferCapacity = 0;
+ }
+ return *this;
+}
+
+CXXScopeSpec::~CXXScopeSpec() {
+ if (BufferCapacity)
+ free(Buffer);
+}
+
+namespace {
+ void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize,
+ unsigned &BufferCapacity) {
+ if (BufferSize + (End - Start) > BufferCapacity) {
+ // Reallocate the buffer.
+ unsigned NewCapacity
+ = std::max((unsigned)(BufferCapacity? BufferCapacity * 2
+ : sizeof(void*) * 2),
+ (unsigned)(BufferSize + (End - Start)));
+ char *NewBuffer = static_cast<char *>(malloc(NewCapacity));
+ memcpy(NewBuffer, Buffer, BufferSize);
+
+ if (BufferCapacity)
+ free(Buffer);
+ Buffer = NewBuffer;
+ BufferCapacity = NewCapacity;
+ }
+
+ memcpy(Buffer + BufferSize, Start, End - Start);
+ BufferSize += End-Start;
+ }
+
+ /// \brief Save a source location to the given buffer.
+ void SaveSourceLocation(SourceLocation Loc, char *&Buffer,
+ unsigned &BufferSize, unsigned &BufferCapacity) {
+ unsigned Raw = Loc.getRawEncoding();
+ Append(reinterpret_cast<char *>(&Raw),
+ reinterpret_cast<char *>(&Raw) + sizeof(unsigned),
+ Buffer, BufferSize, BufferCapacity);
+ }
+
+ /// \brief Save a pointer to the given buffer.
+ void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize,
+ unsigned &BufferCapacity) {
+ Append(reinterpret_cast<char *>(&Ptr),
+ reinterpret_cast<char *>(&Ptr) + sizeof(void *),
+ Buffer, BufferSize, BufferCapacity);
+ }
+}
+void CXXScopeSpec::Extend(ASTContext &Context, SourceLocation TemplateKWLoc,
+ TypeLoc TL, SourceLocation ColonColonLoc) {
+ ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep,
+ TemplateKWLoc.isValid(),
+ TL.getTypePtr());
+ if (Range.getBegin().isInvalid())
+ Range.setBegin(TL.getBeginLoc());
+ Range.setEnd(ColonColonLoc);
+
+ // Push source-location info into the buffer.
+ SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity);
+ SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
+
+ assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() &&
+ "NestedNameSpecifierLoc range computation incorrect");
+}
+
+void CXXScopeSpec::Extend(ASTContext &Context, IdentifierInfo *Identifier,
+ SourceLocation IdentifierLoc,
+ SourceLocation ColonColonLoc) {
+ ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, Identifier);
+ if (Range.getBegin().isInvalid())
+ Range.setBegin(IdentifierLoc);
+ Range.setEnd(ColonColonLoc);
+
+ // Push source-location info into the buffer.
+ SaveSourceLocation(IdentifierLoc, Buffer, BufferSize, BufferCapacity);
+ SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
+
+ assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() &&
+ "NestedNameSpecifierLoc range computation incorrect");
+}
+
+void CXXScopeSpec::Extend(ASTContext &Context, NamespaceDecl *Namespace,
+ SourceLocation NamespaceLoc,
+ SourceLocation ColonColonLoc) {
+ ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, Namespace);
+ if (Range.getBegin().isInvalid())
+ Range.setBegin(NamespaceLoc);
+ Range.setEnd(ColonColonLoc);
+
+ // Push source-location info into the buffer.
+ SaveSourceLocation(NamespaceLoc, Buffer, BufferSize, BufferCapacity);
+ SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
+
+ assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() &&
+ "NestedNameSpecifierLoc range computation incorrect");
+}
+
+void CXXScopeSpec::Extend(ASTContext &Context, NamespaceAliasDecl *Alias,
+ SourceLocation AliasLoc,
+ SourceLocation ColonColonLoc) {
+ ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, Alias);
+ if (Range.getBegin().isInvalid())
+ Range.setBegin(AliasLoc);
+ Range.setEnd(ColonColonLoc);
+
+ // Push source-location info into the buffer.
+ SaveSourceLocation(AliasLoc, Buffer, BufferSize, BufferCapacity);
+ SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
+
+ assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() &&
+ "NestedNameSpecifierLoc range computation incorrect");
+}
+
+void CXXScopeSpec::MakeGlobal(ASTContext &Context,
+ SourceLocation ColonColonLoc) {
+ assert(!ScopeRep && "Already have a nested-name-specifier!?");
+ ScopeRep = NestedNameSpecifier::GlobalSpecifier(Context);
+ Range = SourceRange(ColonColonLoc);
+
+ // Push source-location info into the buffer.
+ SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
+
+ assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() &&
+ "NestedNameSpecifierLoc range computation incorrect");
+}
+
+void CXXScopeSpec::MakeTrivial(ASTContext &Context,
+ NestedNameSpecifier *Qualifier, SourceRange R) {
+ ScopeRep = Qualifier;
+ Range = R;
+
+ // Construct bogus (but well-formed) source information for the
+ // nested-name-specifier.
+ BufferSize = 0;
+ llvm::SmallVector<NestedNameSpecifier *, 4> Stack;
+ for (NestedNameSpecifier *NNS = Qualifier; NNS; NNS = NNS->getPrefix())
+ Stack.push_back(NNS);
+ while (!Stack.empty()) {
+ NestedNameSpecifier *NNS = Stack.back();
+ Stack.pop_back();
+ switch (NNS->getKind()) {
+ case NestedNameSpecifier::Identifier:
+ case NestedNameSpecifier::Namespace:
+ case NestedNameSpecifier::NamespaceAlias:
+ SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity);
+ break;
+
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate: {
+ TypeSourceInfo *TSInfo
+ = Context.getTrivialTypeSourceInfo(QualType(NNS->getAsType(), 0),
+ R.getBegin());
+ SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize,
+ BufferCapacity);
+ break;
+ }
+
+ case NestedNameSpecifier::Global:
+ break;
+ }
+
+ // Save the location of the '::'.
+ SaveSourceLocation(Stack.empty()? R.getEnd() : R.getBegin(),
+ Buffer, BufferSize, BufferCapacity);
+ }
+}
+
+void CXXScopeSpec::Adopt(NestedNameSpecifierLoc Other) {
+ if (!Other) {
+ Range = SourceRange();
+ ScopeRep = 0;
+ return;
+ }
+
+ if (BufferCapacity)
+ free(Buffer);
+
+ // Rather than copying the data (which is wasteful), "adopt" the
+ // pointer (which points into the ASTContext) but set the capacity to zero to
+ // indicate that we don't own it.
+ Range = Other.getSourceRange();
+ ScopeRep = Other.getNestedNameSpecifier();
+ Buffer = static_cast<char *>(Other.getOpaqueData());
+ BufferSize = Other.getDataLength();
+ BufferCapacity = 0;
+}
+
+NestedNameSpecifierLoc
+CXXScopeSpec::getWithLocInContext(ASTContext &Context) const {
+ if (isEmpty() || isInvalid())
+ return NestedNameSpecifierLoc();
+
+ // If we adopted our data pointer from elsewhere in the AST context, there's
+ // no need to copy the memory.
+ if (BufferCapacity == 0)
+ return NestedNameSpecifierLoc(ScopeRep, Buffer);
+
+ void *Mem = Context.Allocate(BufferSize, llvm::alignOf<void *>());
+ memcpy(Mem, Buffer, BufferSize);
+ return NestedNameSpecifierLoc(ScopeRep, Mem);
+}
+
/// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function.
/// "TheDeclarator" is the declarator that this will be added to.
DeclaratorChunk DeclaratorChunk::getFunction(const ParsedAttributes &attrs,
diff --git a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp
index 23a3c24..0c39e13 100644
--- a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp
@@ -48,6 +48,7 @@ void FunctionScopeInfo::Clear() {
SwitchStack.clear();
Returns.clear();
ErrorTrap.reset();
+ PossiblyUnreachableDiags.clear();
}
BlockScopeInfo::~BlockScopeInfo() { }
@@ -466,6 +467,12 @@ void Sema::ActOnEndOfTranslationUnit() {
checkUndefinedInternals(*this);
}
+ // Check we've noticed that we're no longer parsing the initializer for every
+ // variable. If we miss cases, then at best we have a performance issue and
+ // at worst a rejects-valid bug.
+ assert(ParsingInitForAutoVars.empty() &&
+ "Didn't unmark var as having its initializer parsed");
+
TUScope = 0;
}
@@ -625,11 +632,27 @@ void Sema::PushBlockScope(Scope *BlockScope, BlockDecl *Block) {
BlockScope, Block));
}
-void Sema::PopFunctionOrBlockScope() {
- FunctionScopeInfo *Scope = FunctionScopes.pop_back_val();
+void Sema::PopFunctionOrBlockScope(const AnalysisBasedWarnings::Policy *WP,
+ const Decl *D, const BlockExpr *blkExpr) {
+ FunctionScopeInfo *Scope = FunctionScopes.pop_back_val();
assert(!FunctionScopes.empty() && "mismatched push/pop!");
- if (FunctionScopes.back() != Scope)
+
+ // Issue any analysis-based warnings.
+ if (WP && D)
+ AnalysisWarnings.IssueWarnings(*WP, Scope, D, blkExpr);
+ else {
+ for (llvm::SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator
+ i = Scope->PossiblyUnreachableDiags.begin(),
+ e = Scope->PossiblyUnreachableDiags.end();
+ i != e; ++i) {
+ const sema::PossiblyUnreachableDiag &D = *i;
+ Diag(D.Loc, D.PD);
+ }
+ }
+
+ if (FunctionScopes.back() != Scope) {
delete Scope;
+ }
}
/// \brief Determine whether any errors occurred within this function/method/
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp
index aa0efcd..7ad4b45 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -19,6 +19,7 @@
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Sema/DeclSpec.h"
+#include "TypeLocBuilder.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -138,6 +139,9 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS,
case NestedNameSpecifier::Namespace:
return NNS->getAsNamespace();
+ case NestedNameSpecifier::NamespaceAlias:
+ return NNS->getAsNamespaceAlias()->getNamespace();
+
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate: {
const TagType *Tag = NNS->getAsType()->getAs<TagType>();
@@ -219,7 +223,7 @@ bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS,
Context.getTypeDeclType(Tag),
PDiag(diag::err_incomplete_nested_name_spec)
<< SS.getRange())) {
- SS.setScopeRep(0); // Mark the ScopeSpec invalid.
+ SS.SetInvalid(SS.getRange());
return true;
}
}
@@ -227,11 +231,10 @@ bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS,
return false;
}
-/// ActOnCXXGlobalScopeSpecifier - Return the object that represents the
-/// global scope ('::').
-Sema::CXXScopeTy *Sema::ActOnCXXGlobalScopeSpecifier(Scope *S,
- SourceLocation CCLoc) {
- return NestedNameSpecifier::GlobalSpecifier(Context);
+bool Sema::ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc,
+ CXXScopeSpec &SS) {
+ SS.MakeGlobal(Context, CCLoc);
+ return false;
}
/// \brief Determines whether the given declaration is an valid acceptable
@@ -352,22 +355,21 @@ bool Sema::isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS,
///
/// If ErrorRecoveryLookup is true, then this call is used to improve error
/// recovery. This means that it should not emit diagnostics, it should
-/// just return null on failure. It also means it should only return a valid
+/// just return true on failure. It also means it should only return a valid
/// scope if it *knows* that the result is correct. It should not return in a
-/// dependent context, for example.
-Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
- CXXScopeSpec &SS,
- SourceLocation IdLoc,
- SourceLocation CCLoc,
- IdentifierInfo &II,
- QualType ObjectType,
- NamedDecl *ScopeLookupResult,
- bool EnteringContext,
- bool ErrorRecoveryLookup) {
- NestedNameSpecifier *Prefix
- = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
-
- LookupResult Found(*this, &II, IdLoc, LookupNestedNameSpecifierName);
+/// dependent context, for example. Nor will it extend \p SS with the scope
+/// specifier.
+bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
+ IdentifierInfo &Identifier,
+ SourceLocation IdentifierLoc,
+ SourceLocation CCLoc,
+ QualType ObjectType,
+ bool EnteringContext,
+ CXXScopeSpec &SS,
+ NamedDecl *ScopeLookupResult,
+ bool ErrorRecoveryLookup) {
+ LookupResult Found(*this, &Identifier, IdentifierLoc,
+ LookupNestedNameSpecifierName);
// Determine where to perform name lookup
DeclContext *LookupCtx = 0;
@@ -397,7 +399,7 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
// The declaration context must be complete.
if (!LookupCtx->isDependentContext() &&
RequireCompleteDeclContext(SS, LookupCtx))
- return 0;
+ return true;
LookupQualifiedName(Found, LookupCtx);
@@ -442,16 +444,14 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
!cast<CXXRecordDecl>(LookupCtx)->hasAnyDependentBases()))) {
// Don't speculate if we're just trying to improve error recovery.
if (ErrorRecoveryLookup)
- return 0;
+ return true;
// We were not able to compute the declaration context for a dependent
// base object type or prior nested-name-specifier, so this
// nested-name-specifier refers to an unknown specialization. Just build
// a dependent nested-name-specifier.
- if (!Prefix)
- return NestedNameSpecifier::Create(Context, &II);
-
- return NestedNameSpecifier::Create(Context, Prefix, &II);
+ SS.Extend(Context, &Identifier, IdentifierLoc, CCLoc);
+ return false;
}
// FIXME: Deal with ambiguities cleanly.
@@ -480,7 +480,7 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
<< ND->getDeclName();
} else {
Found.clear();
- Found.setLookupName(&II);
+ Found.setLookupName(&Identifier);
}
}
@@ -497,7 +497,8 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
// scope, reconstruct the result from the template instantiation itself.
NamedDecl *OuterDecl;
if (S) {
- LookupResult FoundOuter(*this, &II, IdLoc, LookupNestedNameSpecifierName);
+ LookupResult FoundOuter(*this, &Identifier, IdentifierLoc,
+ LookupNestedNameSpecifierName);
LookupName(FoundOuter, S);
OuterDecl = FoundOuter.getAsSingle<NamedDecl>();
} else
@@ -509,39 +510,72 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
!Context.hasSameType(
Context.getTypeDeclType(cast<TypeDecl>(OuterDecl)),
Context.getTypeDeclType(cast<TypeDecl>(SD))))) {
- if (ErrorRecoveryLookup)
- return 0;
-
- Diag(IdLoc, diag::err_nested_name_member_ref_lookup_ambiguous)
- << &II;
- Diag(SD->getLocation(), diag::note_ambig_member_ref_object_type)
- << ObjectType;
- Diag(OuterDecl->getLocation(), diag::note_ambig_member_ref_scope);
-
- // Fall through so that we'll pick the name we found in the object
- // type, since that's probably what the user wanted anyway.
- }
+ if (ErrorRecoveryLookup)
+ return true;
+
+ Diag(IdentifierLoc,
+ diag::err_nested_name_member_ref_lookup_ambiguous)
+ << &Identifier;
+ Diag(SD->getLocation(), diag::note_ambig_member_ref_object_type)
+ << ObjectType;
+ Diag(OuterDecl->getLocation(), diag::note_ambig_member_ref_scope);
+
+ // Fall through so that we'll pick the name we found in the object
+ // type, since that's probably what the user wanted anyway.
+ }
}
- if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(SD))
- return NestedNameSpecifier::Create(Context, Prefix, Namespace);
+ // If we're just performing this lookup for error-recovery purposes,
+ // don't extend the nested-name-specifier. Just return now.
+ if (ErrorRecoveryLookup)
+ return false;
+
+ if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(SD)) {
+ SS.Extend(Context, Namespace, IdentifierLoc, CCLoc);
+ return false;
+ }
- // FIXME: It would be nice to maintain the namespace alias name, then
- // see through that alias when resolving the nested-name-specifier down to
- // a declaration context.
- if (NamespaceAliasDecl *Alias = dyn_cast<NamespaceAliasDecl>(SD))
- return NestedNameSpecifier::Create(Context, Prefix,
- Alias->getNamespace());
+ if (NamespaceAliasDecl *Alias = dyn_cast<NamespaceAliasDecl>(SD)) {
+ SS.Extend(Context, Alias, IdentifierLoc, CCLoc);
+ return false;
+ }
QualType T = Context.getTypeDeclType(cast<TypeDecl>(SD));
- return NestedNameSpecifier::Create(Context, Prefix, false,
- T.getTypePtr());
+ TypeLocBuilder TLB;
+ if (isa<InjectedClassNameType>(T)) {
+ InjectedClassNameTypeLoc InjectedTL
+ = TLB.push<InjectedClassNameTypeLoc>(T);
+ InjectedTL.setNameLoc(IdentifierLoc);
+ } else if (isa<RecordDecl>(SD)) {
+ RecordTypeLoc RecordTL = TLB.push<RecordTypeLoc>(T);
+ RecordTL.setNameLoc(IdentifierLoc);
+ } else if (isa<TypedefDecl>(SD)) {
+ TypedefTypeLoc TypedefTL = TLB.push<TypedefTypeLoc>(T);
+ TypedefTL.setNameLoc(IdentifierLoc);
+ } else if (isa<EnumDecl>(SD)) {
+ EnumTypeLoc EnumTL = TLB.push<EnumTypeLoc>(T);
+ EnumTL.setNameLoc(IdentifierLoc);
+ } else if (isa<TemplateTypeParmDecl>(SD)) {
+ TemplateTypeParmTypeLoc TemplateTypeTL
+ = TLB.push<TemplateTypeParmTypeLoc>(T);
+ TemplateTypeTL.setNameLoc(IdentifierLoc);
+ } else {
+ assert(isa<UnresolvedUsingTypenameDecl>(SD) &&
+ "Unhandled TypeDecl node in nested-name-specifier");
+ UnresolvedUsingTypeLoc UnresolvedTL
+ = TLB.push<UnresolvedUsingTypeLoc>(T);
+ UnresolvedTL.setNameLoc(IdentifierLoc);
+ }
+
+ SS.Extend(Context, SourceLocation(), TLB.getTypeLocInContext(Context, T),
+ CCLoc);
+ return false;
}
// Otherwise, we have an error case. If we don't want diagnostics, just
// return an error now.
if (ErrorRecoveryLookup)
- return 0;
+ return true;
// If we didn't find anything during our lookup, try again with
// ordinary name lookup, which can help us produce better error
@@ -555,36 +589,34 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
if (!Found.empty())
DiagID = diag::err_expected_class_or_namespace;
else if (SS.isSet()) {
- Diag(IdLoc, diag::err_no_member) << &II << LookupCtx << SS.getRange();
- return 0;
+ Diag(IdentifierLoc, diag::err_no_member)
+ << &Identifier << LookupCtx << SS.getRange();
+ return true;
} else
DiagID = diag::err_undeclared_var_use;
if (SS.isSet())
- Diag(IdLoc, DiagID) << &II << SS.getRange();
+ Diag(IdentifierLoc, DiagID) << &Identifier << SS.getRange();
else
- Diag(IdLoc, DiagID) << &II;
+ Diag(IdentifierLoc, DiagID) << &Identifier;
- return 0;
+ return true;
}
-/// ActOnCXXNestedNameSpecifier - Called during parsing of a
-/// nested-name-specifier. e.g. for "foo::bar::" we parsed "foo::" and now
-/// we want to resolve "bar::". 'SS' is empty or the previously parsed
-/// nested-name part ("foo::"), 'IdLoc' is the source location of 'bar',
-/// 'CCLoc' is the location of '::' and 'II' is the identifier for 'bar'.
-/// Returns a CXXScopeTy* object representing the C++ scope.
-Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
- CXXScopeSpec &SS,
- SourceLocation IdLoc,
- SourceLocation CCLoc,
- IdentifierInfo &II,
- ParsedType ObjectTypePtr,
- bool EnteringContext) {
- return BuildCXXNestedNameSpecifier(S, SS, IdLoc, CCLoc, II,
- GetTypeFromParser(ObjectTypePtr),
- /*ScopeLookupResult=*/0, EnteringContext,
- false);
+bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
+ IdentifierInfo &Identifier,
+ SourceLocation IdentifierLoc,
+ SourceLocation CCLoc,
+ ParsedType ObjectType,
+ bool EnteringContext,
+ CXXScopeSpec &SS) {
+ if (SS.isInvalid())
+ return true;
+
+ return BuildCXXNestedNameSpecifier(S, Identifier, IdentifierLoc, CCLoc,
+ GetTypeFromParser(ObjectType),
+ EnteringContext, SS,
+ /*ScopeLookupResult=*/0, false);
}
/// IsInvalidUnlessNestedName - This method is used for error recovery
@@ -594,23 +626,71 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
///
/// The arguments are the same as those passed to ActOnCXXNestedNameSpecifier.
bool Sema::IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS,
- IdentifierInfo &II, ParsedType ObjectType,
+ IdentifierInfo &Identifier,
+ SourceLocation IdentifierLoc,
+ SourceLocation ColonLoc,
+ ParsedType ObjectType,
bool EnteringContext) {
- return BuildCXXNestedNameSpecifier(S, SS, SourceLocation(), SourceLocation(),
- II, GetTypeFromParser(ObjectType),
- /*ScopeLookupResult=*/0, EnteringContext,
- true);
+ if (SS.isInvalid())
+ return false;
+
+ return !BuildCXXNestedNameSpecifier(S, Identifier, IdentifierLoc, ColonLoc,
+ GetTypeFromParser(ObjectType),
+ EnteringContext, SS,
+ /*ScopeLookupResult=*/0, true);
}
-Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
- const CXXScopeSpec &SS,
- ParsedType Ty,
- SourceRange TypeRange,
- SourceLocation CCLoc) {
- NestedNameSpecifier *Prefix = SS.getScopeRep();
- QualType T = GetTypeFromParser(Ty);
- return NestedNameSpecifier::Create(Context, Prefix, /*FIXME:*/false,
- T.getTypePtr());
+bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
+ ParsedType Type,
+ SourceLocation CCLoc,
+ CXXScopeSpec &SS) {
+ if (SS.isInvalid())
+ return true;
+
+ TypeSourceInfo *TSInfo;
+ QualType T = GetTypeFromParser(Type, &TSInfo);
+ if (T.isNull())
+ return true;
+
+ assert(TSInfo && "Not TypeSourceInfo in nested-name-specifier?");
+ // FIXME: location of the 'template' keyword?
+ SS.Extend(Context, SourceLocation(), TSInfo->getTypeLoc(), CCLoc);
+ return false;
+}
+
+namespace {
+ /// \brief A structure that stores a nested-name-specifier annotation,
+ /// including both the nested-name-specifier
+ struct NestedNameSpecifierAnnotation {
+ NestedNameSpecifier *NNS;
+ };
+}
+
+void *Sema::SaveNestedNameSpecifierAnnotation(CXXScopeSpec &SS) {
+ if (SS.isEmpty() || SS.isInvalid())
+ return 0;
+
+ void *Mem = Context.Allocate((sizeof(NestedNameSpecifierAnnotation) +
+ SS.location_size()),
+ llvm::alignOf<NestedNameSpecifierAnnotation>());
+ NestedNameSpecifierAnnotation *Annotation
+ = new (Mem) NestedNameSpecifierAnnotation;
+ Annotation->NNS = SS.getScopeRep();
+ memcpy(Annotation + 1, SS.location_data(), SS.location_size());
+ return Annotation;
+}
+
+void Sema::RestoreNestedNameSpecifierAnnotation(void *AnnotationPtr,
+ SourceRange AnnotationRange,
+ CXXScopeSpec &SS) {
+ if (!AnnotationPtr) {
+ SS.SetInvalid(AnnotationRange);
+ return;
+ }
+
+ NestedNameSpecifierAnnotation *Annotation
+ = static_cast<NestedNameSpecifierAnnotation *>(AnnotationPtr);
+ SS.Adopt(NestedNameSpecifierLoc(Annotation->NNS, Annotation + 1));
}
bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
@@ -636,6 +716,7 @@ bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
switch (Qualifier->getKind()) {
case NestedNameSpecifier::Global:
case NestedNameSpecifier::Namespace:
+ case NestedNameSpecifier::NamespaceAlias:
// These are always namespace scopes. We never want to enter a
// namespace scope from anything but a file context.
return CurContext->getRedeclContext()->isFileContext();
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
index 24cdaef..3ffa748 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp
@@ -66,6 +66,26 @@ bool Sema::CheckablePrintfAttr(const FormatAttr *Format, CallExpr *TheCall) {
return false;
}
+/// Checks that a call expression's argument count is the desired number.
+/// This is useful when doing custom type-checking. Returns true on error.
+static bool checkArgCount(Sema &S, CallExpr *call, unsigned desiredArgCount) {
+ unsigned argCount = call->getNumArgs();
+ if (argCount == desiredArgCount) return false;
+
+ if (argCount < desiredArgCount)
+ return S.Diag(call->getLocEnd(), diag::err_typecheck_call_too_few_args)
+ << 0 /*function call*/ << desiredArgCount << argCount
+ << call->getSourceRange();
+
+ // Highlight all the excess arguments.
+ SourceRange range(call->getArg(desiredArgCount)->getLocStart(),
+ call->getArg(argCount - 1)->getLocEnd());
+
+ return S.Diag(range.getBegin(), diag::err_typecheck_call_too_many_args)
+ << 0 /*function call*/ << desiredArgCount << argCount
+ << call->getArg(1)->getSourceRange();
+}
+
ExprResult
Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
ExprResult TheCallResult(Owned(TheCall));
@@ -137,15 +157,14 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
if (SemaBuiltinLongjmp(TheCall))
return ExprError();
break;
+
+ case Builtin::BI__builtin_classify_type:
+ if (checkArgCount(*this, TheCall, 1)) return true;
+ TheCall->setType(Context.IntTy);
+ break;
case Builtin::BI__builtin_constant_p:
- if (TheCall->getNumArgs() == 0)
- return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args)
- << 0 /*function call*/ << 1 << 0 << TheCall->getSourceRange();
- if (TheCall->getNumArgs() > 1)
- return Diag(TheCall->getArg(1)->getLocStart(),
- diag::err_typecheck_call_too_many_args)
- << 0 /*function call*/ << 1 << TheCall->getNumArgs()
- << TheCall->getArg(1)->getSourceRange();
+ if (checkArgCount(*this, TheCall, 1)) return true;
+ TheCall->setType(Context.IntTy);
break;
case Builtin::BI__sync_fetch_and_add:
case Builtin::BI__sync_fetch_and_sub:
@@ -875,7 +894,7 @@ bool Sema::SemaBuiltinLongjmp(CallExpr *TheCall) {
return false;
}
-// Handle i > 1 ? "x" : "y", recursivelly
+// Handle i > 1 ? "x" : "y", recursively.
bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall,
bool HasVAListArg,
unsigned format_idx, unsigned firstDataArg,
@@ -918,6 +937,12 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall,
}
return false;
+ case Stmt::PredefinedExprClass:
+ // While __func__, etc., are technically not string literals, they
+ // cannot contain format specifiers and thus are not a security
+ // liability.
+ return true;
+
case Stmt::DeclRefExprClass: {
const DeclRefExpr *DR = cast<DeclRefExpr>(E);
@@ -2896,6 +2921,17 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
return DiagnoseImpCast(S, E, T, CC, DiagID);
}
+ // Diagnose conversions between different enumeration types.
+ if (const EnumType *SourceEnum = Source->getAs<EnumType>())
+ if (const EnumType *TargetEnum = Target->getAs<EnumType>())
+ if ((SourceEnum->getDecl()->getIdentifier() ||
+ SourceEnum->getDecl()->getTypedefForAnonDecl()) &&
+ (TargetEnum->getDecl()->getIdentifier() ||
+ TargetEnum->getDecl()->getTypedefForAnonDecl()) &&
+ SourceEnum != TargetEnum)
+ return DiagnoseImpCast(S, E, T, CC,
+ diag::warn_impcast_different_enum_types);
+
return;
}
@@ -3147,7 +3183,7 @@ void Sema::CheckArrayAccess(const clang::ArraySubscriptExpr *E) {
if (!IndexExpr->isIntegerConstantExpr(index, Context))
return;
- if (!index.isNegative()) {
+ if (index.isUnsigned() || !index.isNegative()) {
llvm::APInt size = ArrayTy->getSize();
if (!size.isStrictlyPositive())
return;
@@ -3159,12 +3195,15 @@ void Sema::CheckArrayAccess(const clang::ArraySubscriptExpr *E) {
if (index.slt(size))
return;
- Diag(E->getBase()->getLocStart(), diag::warn_array_index_exceeds_bounds)
- << index.toString(10, true) << size.toString(10, true)
- << IndexExpr->getSourceRange();
+ DiagRuntimeBehavior(E->getBase()->getLocStart(), BaseExpr,
+ PDiag(diag::warn_array_index_exceeds_bounds)
+ << index.toString(10, true) << size.toString(10, true)
+ << IndexExpr->getSourceRange());
} else {
- Diag(E->getBase()->getLocStart(), diag::warn_array_index_precedes_bounds)
- << index.toString(10, true) << IndexExpr->getSourceRange();
+ DiagRuntimeBehavior(E->getBase()->getLocStart(), BaseExpr,
+ PDiag(diag::warn_array_index_precedes_bounds)
+ << index.toString(10, true)
+ << IndexExpr->getSourceRange());
}
const NamedDecl *ND = NULL;
@@ -3173,7 +3212,8 @@ void Sema::CheckArrayAccess(const clang::ArraySubscriptExpr *E) {
if (const MemberExpr *ME = dyn_cast<MemberExpr>(BaseExpr))
ND = dyn_cast<NamedDecl>(ME->getMemberDecl());
if (ND)
- Diag(ND->getLocStart(), diag::note_array_index_out_of_bounds)
- << ND->getDeclName();
+ DiagRuntimeBehavior(ND->getLocStart(), BaseExpr,
+ PDiag(diag::note_array_index_out_of_bounds)
+ << ND->getDeclName());
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp
index dd30c12..d6efd7a 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp
@@ -2895,8 +2895,7 @@ isOutOfScopePreviousDeclaration(NamedDecl *PrevDecl, DeclContext *DC,
static void SetNestedNameSpecifier(DeclaratorDecl *DD, Declarator &D) {
CXXScopeSpec &SS = D.getCXXScopeSpec();
if (!SS.isSet()) return;
- DD->setQualifierInfo(static_cast<NestedNameSpecifier*>(SS.getScopeRep()),
- SS.getRange());
+ DD->setQualifierInfo(SS.getWithLocInContext(DD->getASTContext()));
}
NamedDecl*
@@ -3026,11 +3025,11 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(),
II, R, TInfo, SC, SCAsWritten);
- // If this decl has an auto type in need of deduction, mark the VarDecl so
- // we can diagnose uses of it in its own initializer.
- if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto) {
- NewVD->setParsingAutoInit(R->getContainedAutoType());
- }
+ // If this decl has an auto type in need of deduction, make a note of the
+ // Decl so we can diagnose uses of it in its own initializer.
+ if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto &&
+ R->getContainedAutoType())
+ ParsingInitForAutoVars.insert(NewVD);
if (D.isInvalidType() || Invalid)
NewVD->setInvalidDecl();
@@ -4534,8 +4533,6 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
// C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) {
- VDecl->setParsingAutoInit(false);
-
QualType DeducedType;
if (!DeduceAutoType(VDecl->getType(), Init, DeducedType)) {
Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure)
@@ -4800,9 +4797,8 @@ void Sema::ActOnInitializerError(Decl *D) {
if (!VD) return;
// Auto types are meaningless if we can't make sense of the initializer.
- if (VD->isParsingAutoInit()) {
- VD->setParsingAutoInit(false);
- VD->setInvalidDecl();
+ if (ParsingInitForAutoVars.count(D)) {
+ D->setInvalidDecl();
return;
}
@@ -4840,8 +4836,6 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl,
// C++0x [dcl.spec.auto]p3
if (TypeMayContainAuto && Type->getContainedAutoType()) {
- Var->setParsingAutoInit(false);
-
Diag(Var->getLocation(), diag::err_auto_var_requires_init)
<< Var->getDeclName() << Type;
Var->setInvalidDecl();
@@ -5044,6 +5038,14 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
FinalizeVarWithDestructor(var, recordType);
}
+/// FinalizeDeclaration - called by ParseDeclarationAfterDeclarator to perform
+/// any semantic actions necessary after any initializer has been attached.
+void
+Sema::FinalizeDeclaration(Decl *ThisDecl) {
+ // Note that we are no longer parsing the initializer for this declaration.
+ ParsingInitForAutoVars.erase(ThisDecl);
+}
+
Sema::DeclGroupPtrTy
Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
Decl **Group, unsigned NumDecls) {
@@ -5052,6 +5054,19 @@ Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
if (DS.isTypeSpecOwned())
Decls.push_back(DS.getRepAsDecl());
+ for (unsigned i = 0; i != NumDecls; ++i)
+ if (Decl *D = Group[i])
+ Decls.push_back(D);
+
+ return BuildDeclaratorGroup(Decls.data(), Decls.size(),
+ DS.getTypeSpecType() == DeclSpec::TST_auto);
+}
+
+/// BuildDeclaratorGroup - convert a list of declarations into a declaration
+/// group, performing any necessary semantic checking.
+Sema::DeclGroupPtrTy
+Sema::BuildDeclaratorGroup(Decl **Group, unsigned NumDecls,
+ bool TypeMayContainAuto) {
// C++0x [dcl.spec.auto]p7:
// If the type deduced for the template parameter U is not the same in each
// deduction, the program is ill-formed.
@@ -5059,14 +5074,16 @@ Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
// between the deduced type U and the deduced type which 'auto' stands for.
// auto a = 0, b = { 1, 2, 3 };
// is legal because the deduced type U is 'int' in both cases.
- bool TypeContainsAuto = DS.getTypeSpecType() == DeclSpec::TST_auto;
- if (TypeContainsAuto && NumDecls > 1) {
+ if (TypeMayContainAuto && NumDecls > 1) {
QualType Deduced;
CanQualType DeducedCanon;
VarDecl *DeducedDecl = 0;
for (unsigned i = 0; i != NumDecls; ++i) {
if (VarDecl *D = dyn_cast<VarDecl>(Group[i])) {
AutoType *AT = D->getType()->getContainedAutoType();
+ // Don't reissue diagnostics when instantiating a template.
+ if (AT && D->isInvalidDecl())
+ break;
if (AT && AT->isDeduced()) {
QualType U = AT->getDeducedType();
CanQualType UCanon = Context.getCanonicalType(U);
@@ -5075,11 +5092,13 @@ Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
DeducedCanon = UCanon;
DeducedDecl = D;
} else if (DeducedCanon != UCanon) {
- Diag(DS.getTypeSpecTypeLoc(), diag::err_auto_different_deductions)
+ Diag(D->getTypeSourceInfo()->getTypeLoc().getBeginLoc(),
+ diag::err_auto_different_deductions)
<< Deduced << DeducedDecl->getDeclName()
<< U << D->getDeclName()
<< DeducedDecl->getInit()->getSourceRange()
<< D->getInit()->getSourceRange();
+ D->setInvalidDecl();
break;
}
}
@@ -5087,12 +5106,7 @@ Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
}
}
- for (unsigned i = 0; i != NumDecls; ++i)
- if (Decl *D = Group[i])
- Decls.push_back(D);
-
- return DeclGroupPtrTy::make(DeclGroupRef::Create(Context,
- Decls.data(), Decls.size()));
+ return DeclGroupPtrTy::make(DeclGroupRef::Create(Context, Group, NumDecls));
}
@@ -5537,6 +5551,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
FD = dyn_cast_or_null<FunctionDecl>(dcl);
sema::AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy();
+ sema::AnalysisBasedWarnings::Policy *ActivePolicy = 0;
if (FD) {
FD->setBody(Body);
@@ -5605,13 +5620,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
else if (!isa<FunctionTemplateDecl>(dcl)) {
// Since the body is valid, issue any analysis-based warnings that are
// enabled.
- QualType ResultType;
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(dcl)) {
- AnalysisWarnings.IssueWarnings(WP, FD);
- } else {
- ObjCMethodDecl *MD = cast<ObjCMethodDecl>(dcl);
- AnalysisWarnings.IssueWarnings(WP, MD);
- }
+ ActivePolicy = &WP;
}
assert(ExprTemporaries.empty() && "Leftover temporaries in function");
@@ -5620,7 +5629,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
if (!IsInstantiation)
PopDeclContext();
- PopFunctionOrBlockScope();
+ PopFunctionOrBlockScope(ActivePolicy, dcl);
// If any errors have occurred, clear out any temporaries that may have
// been leftover. This ensures that these temporaries won't be picked up for
@@ -6435,9 +6444,7 @@ CreateNewDecl:
// Maybe add qualifier info.
if (SS.isNotEmpty()) {
if (SS.isSet()) {
- NestedNameSpecifier *NNS
- = static_cast<NestedNameSpecifier*>(SS.getScopeRep());
- New->setQualifierInfo(NNS, SS.getRange());
+ New->setQualifierInfo(SS.getWithLocInContext(Context));
if (NumMatchedTemplateParamLists > 0) {
New->setTemplateParameterListsInfo(Context,
NumMatchedTemplateParamLists,
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp
index cbc940f..893cf6a 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp
@@ -1014,54 +1014,48 @@ static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
}
static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
- // check the attribute arguments.
- int noArgs = Attr.getNumArgs();
- if (noArgs > 1) {
+ unsigned NumArgs = Attr.getNumArgs();
+ if (NumArgs > 1) {
S.Diag(Attr.getLoc(),
diag::err_attribute_wrong_number_arguments) << "0 or 1";
return;
}
+
// Handle the case where deprecated attribute has a text message.
- StringLiteral *SE;
- if (noArgs == 1) {
- Expr *ArgExpr = Attr.getArg(0);
- SE = dyn_cast<StringLiteral>(ArgExpr);
+ llvm::StringRef Str;
+ if (NumArgs == 1) {
+ StringLiteral *SE = dyn_cast<StringLiteral>(Attr.getArg(0));
if (!SE) {
- S.Diag(ArgExpr->getLocStart(),
- diag::err_attribute_not_string) << "deprecated";
+ S.Diag(Attr.getArg(0)->getLocStart(), diag::err_attribute_not_string)
+ << "deprecated";
return;
}
+ Str = SE->getString();
}
- else
- SE = StringLiteral::CreateEmpty(S.Context, 1);
- d->addAttr(::new (S.Context) DeprecatedAttr(Attr.getLoc(), S.Context,
- SE->getString()));
+ d->addAttr(::new (S.Context) DeprecatedAttr(Attr.getLoc(), S.Context, Str));
}
static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) {
- // check the attribute arguments.
- int noArgs = Attr.getNumArgs();
- if (noArgs > 1) {
+ unsigned NumArgs = Attr.getNumArgs();
+ if (NumArgs > 1) {
S.Diag(Attr.getLoc(),
diag::err_attribute_wrong_number_arguments) << "0 or 1";
return;
}
+
// Handle the case where unavailable attribute has a text message.
- StringLiteral *SE;
- if (noArgs == 1) {
- Expr *ArgExpr = Attr.getArg(0);
- SE = dyn_cast<StringLiteral>(ArgExpr);
+ llvm::StringRef Str;
+ if (NumArgs == 1) {
+ StringLiteral *SE = dyn_cast<StringLiteral>(Attr.getArg(0));
if (!SE) {
- S.Diag(ArgExpr->getLocStart(),
+ S.Diag(Attr.getArg(0)->getLocStart(),
diag::err_attribute_not_string) << "unavailable";
return;
}
+ Str = SE->getString();
}
- else
- SE = StringLiteral::CreateEmpty(S.Context, 1);
- d->addAttr(::new (S.Context) UnavailableAttr(Attr.getLoc(), S.Context,
- SE->getString()));
+ d->addAttr(::new (S.Context) UnavailableAttr(Attr.getLoc(), S.Context, Str));
}
static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -2847,7 +2841,7 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II) {
FD->getType(), FD->getTypeSourceInfo());
if (FD->getQualifier()) {
FunctionDecl *NewFD = cast<FunctionDecl>(NewD);
- NewFD->setQualifierInfo(FD->getQualifier(), FD->getQualifierRange());
+ NewFD->setQualifierInfo(FD->getQualifierLoc());
}
} else if (VarDecl *VD = dyn_cast<VarDecl>(ND)) {
NewD = VarDecl::Create(VD->getASTContext(), VD->getDeclContext(),
@@ -2857,7 +2851,7 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II) {
VD->getStorageClassAsWritten());
if (VD->getQualifier()) {
VarDecl *NewVD = cast<VarDecl>(NewD);
- NewVD->setQualifierInfo(VD->getQualifier(), VD->getQualifierRange());
+ NewVD->setQualifierInfo(VD->getQualifierLoc());
}
}
return NewD;
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
index e8abab8..f483262 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp
@@ -1078,6 +1078,8 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
if (Deleted) // FIXME: Source location is not very good.
SetDeclDeleted(Member, D.getSourceRange().getBegin());
+ FinalizeDeclaration(Member);
+
if (isInstField)
FieldCollector->Add(cast<FieldDecl>(Member));
return Member;
@@ -2586,6 +2588,9 @@ struct CheckAbstractUsage {
void Check(FunctionProtoTypeLoc TL, Sema::AbstractDiagSelID Sel) {
Visit(TL.getResultLoc(), Sema::AbstractReturnType);
for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) {
+ if (!TL.getArg(I))
+ continue;
+
TypeSourceInfo *TSI = TL.getArg(I)->getTypeSourceInfo();
if (TSI) Visit(TSI->getTypeLoc(), Sema::AbstractParamType);
}
@@ -3618,8 +3623,7 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
= UsingDirectiveDecl::Create(Context, CurContext,
/* 'using' */ LBrace,
/* 'namespace' */ SourceLocation(),
- /* qualifier */ SourceRange(),
- /* NNS */ NULL,
+ /* qualifier */ NestedNameSpecifierLoc(),
/* identifier */ SourceLocation(),
Namespc,
/* Ancestor */ CurContext);
@@ -3763,8 +3767,7 @@ Decl *Sema::ActOnUsingDirective(Scope *S,
CommonAncestor = CommonAncestor->getParent();
UDir = UsingDirectiveDecl::Create(Context, CurContext, UsingLoc, NamespcLoc,
- SS.getRange(),
- (NestedNameSpecifier *)SS.getScopeRep(),
+ SS.getWithLocInContext(Context),
IdentLoc, Named, CommonAncestor);
PushUsingDirective(S, UDir);
} else {
@@ -3914,16 +3917,16 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
if (OrigDC == CurContext) {
Diag(Using->getLocation(),
diag::err_using_decl_nested_name_specifier_is_current_class)
- << Using->getNestedNameRange();
+ << Using->getQualifierLoc().getSourceRange();
Diag(Orig->getLocation(), diag::note_using_decl_target);
return true;
}
- Diag(Using->getNestedNameRange().getBegin(),
+ Diag(Using->getQualifierLoc().getBeginLoc(),
diag::err_using_decl_nested_name_specifier_is_not_base_class)
- << Using->getTargetNestedNameDecl()
+ << Using->getQualifier()
<< cast<CXXRecordDecl>(CurContext)
- << Using->getNestedNameRange();
+ << Using->getQualifierLoc().getSourceRange();
Diag(Orig->getLocation(), diag::note_using_decl_target);
return true;
}
@@ -4129,8 +4132,6 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
LookupQualifiedName(Previous, CurContext);
}
- NestedNameSpecifier *NNS = SS.getScopeRep();
-
// Check for invalid redeclarations.
if (CheckUsingDeclRedeclaration(UsingLoc, IsTypeName, SS, IdentLoc, Previous))
return 0;
@@ -4141,22 +4142,21 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
DeclContext *LookupContext = computeDeclContext(SS);
NamedDecl *D;
+ NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
if (!LookupContext) {
if (IsTypeName) {
// FIXME: not all declaration name kinds are legal here
D = UnresolvedUsingTypenameDecl::Create(Context, CurContext,
UsingLoc, TypenameLoc,
- SS.getRange(), NNS,
+ QualifierLoc,
IdentLoc, NameInfo.getName());
} else {
- D = UnresolvedUsingValueDecl::Create(Context, CurContext,
- UsingLoc, SS.getRange(),
- NNS, NameInfo);
+ D = UnresolvedUsingValueDecl::Create(Context, CurContext, UsingLoc,
+ QualifierLoc, NameInfo);
}
} else {
- D = UsingDecl::Create(Context, CurContext,
- SS.getRange(), UsingLoc, NNS, NameInfo,
- IsTypeName);
+ D = UsingDecl::Create(Context, CurContext, UsingLoc, QualifierLoc,
+ NameInfo, IsTypeName);
}
D->setAccess(AS);
CurContext->addDecl(D);
@@ -4247,7 +4247,7 @@ bool Sema::CheckInheritedConstructorUsingDecl(UsingDecl *UD) {
return true;
}
- const Type *SourceType = UD->getTargetNestedNameDecl()->getAsType();
+ const Type *SourceType = UD->getQualifier()->getAsType();
assert(SourceType &&
"Using decl naming constructor doesn't have type in scope spec.");
CXXRecordDecl *TargetClass = cast<CXXRecordDecl>(CurContext);
@@ -4304,15 +4304,15 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
NestedNameSpecifier *DQual;
if (UsingDecl *UD = dyn_cast<UsingDecl>(D)) {
DTypename = UD->isTypeName();
- DQual = UD->getTargetNestedNameDecl();
+ DQual = UD->getQualifier();
} else if (UnresolvedUsingValueDecl *UD
= dyn_cast<UnresolvedUsingValueDecl>(D)) {
DTypename = false;
- DQual = UD->getTargetNestedNameSpecifier();
+ DQual = UD->getQualifier();
} else if (UnresolvedUsingTypenameDecl *UD
= dyn_cast<UnresolvedUsingTypenameDecl>(D)) {
DTypename = true;
- DQual = UD->getTargetNestedNameSpecifier();
+ DQual = UD->getQualifier();
} else continue;
// using decls differ if one says 'typename' and the other doesn't.
@@ -4542,8 +4542,7 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S,
NamespaceAliasDecl *AliasDecl =
NamespaceAliasDecl::Create(Context, CurContext, NamespaceLoc, AliasLoc,
- Alias, SS.getRange(),
- (NestedNameSpecifier *)SS.getScopeRep(),
+ Alias, SS.getWithLocInContext(Context),
IdentLoc, R.getFoundDecl());
PushOnScopeChains(AliasDecl, S);
@@ -5080,9 +5079,10 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T,
// reference to operator=; this is required to suppress the virtual
// call mechanism.
CXXScopeSpec SS;
- SS.setRange(Loc);
- SS.setScopeRep(NestedNameSpecifier::Create(S.Context, 0, false,
- T.getTypePtr()));
+ SS.MakeTrivial(S.Context,
+ NestedNameSpecifier::Create(S.Context, 0, false,
+ T.getTypePtr()),
+ Loc);
// Create the reference to operator=.
ExprResult OpEqualRef
@@ -5972,8 +5972,6 @@ void Sema::AddCXXDirectInitializerToDecl(Decl *RealDecl,
// C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) {
- VDecl->setParsingAutoInit(false);
-
// FIXME: n3225 doesn't actually seem to indicate this is ill-formed
if (Exprs.size() > 1) {
Diag(Exprs.get()[1]->getSourceRange().getBegin(),
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp
index 66f6f2b..652318f 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp
@@ -856,9 +856,21 @@ static SourceRange getTypeRange(TypeSourceInfo *TSI) {
static void CheckMethodOverrideReturn(Sema &S,
ObjCMethodDecl *MethodImpl,
- ObjCMethodDecl *MethodIface) {
+ ObjCMethodDecl *MethodDecl,
+ bool IsProtocolMethodDecl) {
+ if (IsProtocolMethodDecl &&
+ (MethodDecl->getObjCDeclQualifier() !=
+ MethodImpl->getObjCDeclQualifier())) {
+ S.Diag(MethodImpl->getLocation(),
+ diag::warn_conflicting_ret_type_modifiers)
+ << MethodImpl->getDeclName()
+ << getTypeRange(MethodImpl->getResultTypeSourceInfo());
+ S.Diag(MethodDecl->getLocation(), diag::note_previous_declaration)
+ << getTypeRange(MethodDecl->getResultTypeSourceInfo());
+ }
+
if (S.Context.hasSameUnqualifiedType(MethodImpl->getResultType(),
- MethodIface->getResultType()))
+ MethodDecl->getResultType()))
return;
unsigned DiagID = diag::warn_conflicting_ret_types;
@@ -868,7 +880,7 @@ static void CheckMethodOverrideReturn(Sema &S,
if (const ObjCObjectPointerType *ImplPtrTy =
MethodImpl->getResultType()->getAs<ObjCObjectPointerType>()) {
if (const ObjCObjectPointerType *IfacePtrTy =
- MethodIface->getResultType()->getAs<ObjCObjectPointerType>()) {
+ MethodDecl->getResultType()->getAs<ObjCObjectPointerType>()) {
// Allow non-matching return types as long as they don't violate
// the principle of substitutability. Specifically, we permit
// return types that are subclasses of the declared return type,
@@ -882,20 +894,33 @@ static void CheckMethodOverrideReturn(Sema &S,
S.Diag(MethodImpl->getLocation(), DiagID)
<< MethodImpl->getDeclName()
- << MethodIface->getResultType()
+ << MethodDecl->getResultType()
<< MethodImpl->getResultType()
<< getTypeRange(MethodImpl->getResultTypeSourceInfo());
- S.Diag(MethodIface->getLocation(), diag::note_previous_definition)
- << getTypeRange(MethodIface->getResultTypeSourceInfo());
+ S.Diag(MethodDecl->getLocation(), diag::note_previous_definition)
+ << getTypeRange(MethodDecl->getResultTypeSourceInfo());
}
static void CheckMethodOverrideParam(Sema &S,
ObjCMethodDecl *MethodImpl,
- ObjCMethodDecl *MethodIface,
+ ObjCMethodDecl *MethodDecl,
ParmVarDecl *ImplVar,
- ParmVarDecl *IfaceVar) {
+ ParmVarDecl *IfaceVar,
+ bool IsProtocolMethodDecl) {
+ if (IsProtocolMethodDecl &&
+ (ImplVar->getObjCDeclQualifier() !=
+ IfaceVar->getObjCDeclQualifier())) {
+ S.Diag(ImplVar->getLocation(),
+ diag::warn_conflicting_param_modifiers)
+ << getTypeRange(ImplVar->getTypeSourceInfo())
+ << MethodImpl->getDeclName();
+ S.Diag(IfaceVar->getLocation(), diag::note_previous_declaration)
+ << getTypeRange(IfaceVar->getTypeSourceInfo());
+ }
+
QualType ImplTy = ImplVar->getType();
QualType IfaceTy = IfaceVar->getType();
+
if (S.Context.hasSameUnqualifiedType(ImplTy, IfaceTy))
return;
@@ -927,17 +952,20 @@ static void CheckMethodOverrideParam(Sema &S,
void Sema::WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethodDecl,
- ObjCMethodDecl *IntfMethodDecl) {
- CheckMethodOverrideReturn(*this, ImpMethodDecl, IntfMethodDecl);
+ ObjCMethodDecl *MethodDecl,
+ bool IsProtocolMethodDecl) {
+ CheckMethodOverrideReturn(*this, ImpMethodDecl, MethodDecl,
+ IsProtocolMethodDecl);
for (ObjCMethodDecl::param_iterator IM = ImpMethodDecl->param_begin(),
- IF = IntfMethodDecl->param_begin(), EM = ImpMethodDecl->param_end();
+ IF = MethodDecl->param_begin(), EM = ImpMethodDecl->param_end();
IM != EM; ++IM, ++IF)
- CheckMethodOverrideParam(*this, ImpMethodDecl, IntfMethodDecl, *IM, *IF);
+ CheckMethodOverrideParam(*this, ImpMethodDecl, MethodDecl, *IM, *IF,
+ IsProtocolMethodDecl);
- if (ImpMethodDecl->isVariadic() != IntfMethodDecl->isVariadic()) {
+ if (ImpMethodDecl->isVariadic() != MethodDecl->isVariadic()) {
Diag(ImpMethodDecl->getLocation(), diag::warn_conflicting_variadic);
- Diag(IntfMethodDecl->getLocation(), diag::note_previous_declaration);
+ Diag(MethodDecl->getLocation(), diag::note_previous_declaration);
}
}
@@ -1061,13 +1089,14 @@ void Sema::MatchAllMethodDeclarations(const llvm::DenseSet<Selector> &InsMap,
} else {
ObjCMethodDecl *ImpMethodDecl =
IMPDecl->getInstanceMethod((*I)->getSelector());
- ObjCMethodDecl *IntfMethodDecl =
+ ObjCMethodDecl *MethodDecl =
CDecl->getInstanceMethod((*I)->getSelector());
- assert(IntfMethodDecl &&
- "IntfMethodDecl is null in ImplMethodsVsClassMethods");
+ assert(MethodDecl &&
+ "MethodDecl is null in ImplMethodsVsClassMethods");
// ImpMethodDecl may be null as in a @dynamic property.
if (ImpMethodDecl)
- WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl);
+ WarnConflictingTypedMethods(ImpMethodDecl, MethodDecl,
+ isa<ObjCProtocolDecl>(CDecl));
}
}
@@ -1085,9 +1114,10 @@ void Sema::MatchAllMethodDeclarations(const llvm::DenseSet<Selector> &InsMap,
} else {
ObjCMethodDecl *ImpMethodDecl =
IMPDecl->getClassMethod((*I)->getSelector());
- ObjCMethodDecl *IntfMethodDecl =
+ ObjCMethodDecl *MethodDecl =
CDecl->getClassMethod((*I)->getSelector());
- WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl);
+ WarnConflictingTypedMethods(ImpMethodDecl, MethodDecl,
+ isa<ObjCProtocolDecl>(CDecl));
}
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
index 65b57c3..415ab3f 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp
@@ -76,12 +76,10 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
}
// See if this is an auto-typed variable whose initializer we are parsing.
- if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
- if (VD->isParsingAutoInit()) {
- Diag(Loc, diag::err_auto_variable_cannot_appear_in_own_initializer)
- << D->getDeclName();
- return true;
- }
+ if (ParsingInitForAutoVars.count(D)) {
+ Diag(Loc, diag::err_auto_variable_cannot_appear_in_own_initializer)
+ << D->getDeclName();
+ return true;
}
// See if the decl is deprecated.
@@ -389,13 +387,13 @@ bool Sema::DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT,
return false;
if (Expr->getType()->isObjCObjectType() &&
- DiagRuntimeBehavior(Expr->getLocStart(),
+ DiagRuntimeBehavior(Expr->getLocStart(), 0,
PDiag(diag::err_cannot_pass_objc_interface_to_vararg)
<< Expr->getType() << CT))
return true;
if (!Expr->getType()->isPODType() &&
- DiagRuntimeBehavior(Expr->getLocStart(),
+ DiagRuntimeBehavior(Expr->getLocStart(), 0,
PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg)
<< Expr->getType() << CT))
return true;
@@ -1675,20 +1673,6 @@ ExprResult Sema::ActOnIdExpression(Scope *S,
// This is guaranteed from this point on.
assert(!R.empty() || ADL);
- if (VarDecl *Var = R.getAsSingle<VarDecl>()) {
- if (getLangOptions().ObjCNonFragileABI && IvarLookupFollowUp &&
- !(getLangOptions().ObjCDefaultSynthProperties &&
- getLangOptions().ObjCNonFragileABI2) &&
- Var->isFileVarDecl()) {
- ObjCPropertyDecl *Property = canSynthesizeProvisionalIvar(II);
- if (Property) {
- Diag(NameLoc, diag::warn_ivar_variable_conflict) << Var->getDeclName();
- Diag(Property->getLocation(), diag::note_property_declare);
- Diag(Var->getLocation(), diag::note_global_declared_at);
- }
- }
- }
-
// Check whether this might be a C++ implicit instance member access.
// C++ [class.mfct.non-static]p3:
// When an id-expression that is not part of a class member access
@@ -3996,131 +3980,130 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
// Failure cases.
fail:
- // There's a possible road to recovery for function types.
- const FunctionType *Fun = 0;
- SourceLocation ParenInsertionLoc =
- PP.getLocForEndOfToken(BaseExpr->getLocEnd());
-
+ // Recover from dot accesses to pointers, e.g.:
+ // type *foo;
+ // foo.bar
+ // This is actually well-formed in two cases:
+ // - 'type' is an Objective C type
+ // - 'bar' is a pseudo-destructor name which happens to refer to
+ // the appropriate pointer type
if (const PointerType *Ptr = BaseType->getAs<PointerType>()) {
- if ((Fun = Ptr->getPointeeType()->getAs<FunctionType>())) {
- // fall out, handled below.
-
- // Recover from dot accesses to pointers, e.g.:
- // type *foo;
- // foo.bar
- // This is actually well-formed in two cases:
- // - 'type' is an Objective C type
- // - 'bar' is a pseudo-destructor name which happens to refer to
- // the appropriate pointer type
- } else if (!IsArrow && Ptr->getPointeeType()->isRecordType() &&
- MemberName.getNameKind() != DeclarationName::CXXDestructorName) {
+ if (!IsArrow && Ptr->getPointeeType()->isRecordType() &&
+ MemberName.getNameKind() != DeclarationName::CXXDestructorName) {
Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)
- << BaseType << int(IsArrow) << BaseExpr->getSourceRange()
- << FixItHint::CreateReplacement(OpLoc, "->");
+ << BaseType << int(IsArrow) << BaseExpr->getSourceRange()
+ << FixItHint::CreateReplacement(OpLoc, "->");
// Recurse as an -> access.
IsArrow = true;
return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS,
ObjCImpDecl, HasTemplateArgs);
}
- } else {
- Fun = BaseType->getAs<FunctionType>();
- }
-
- // If the user is trying to apply -> or . to a function pointer
- // type, it's probably because they forgot parentheses to call that
- // function. Suggest the addition of those parentheses, build the
- // call, and continue on.
- if (Fun || BaseType == Context.OverloadTy) {
- bool TryCall;
- if (BaseType == Context.OverloadTy) {
- // Plunder the overload set for something that would make the member
- // expression valid.
- const OverloadExpr *Overloads = cast<OverloadExpr>(BaseExpr);
- UnresolvedSet<4> CandidateOverloads;
- bool HasZeroArgCandidateOverload = false;
- for (OverloadExpr::decls_iterator it = Overloads->decls_begin(),
- DeclsEnd = Overloads->decls_end(); it != DeclsEnd; ++it) {
- const FunctionDecl *OverloadDecl = cast<FunctionDecl>(*it);
- QualType ResultTy = OverloadDecl->getResultType();
- if ((!IsArrow && ResultTy->isRecordType()) ||
- (IsArrow && ResultTy->isPointerType() &&
- ResultTy->getPointeeType()->isRecordType())) {
- CandidateOverloads.addDecl(*it);
- if (OverloadDecl->getNumParams() == 0) {
- HasZeroArgCandidateOverload = true;
- }
+ }
+
+ // If the user is trying to apply -> or . to a function name, it's probably
+ // because they forgot parentheses to call that function.
+ bool TryCall = false;
+ bool Overloaded = false;
+ UnresolvedSet<8> AllOverloads;
+ if (const OverloadExpr *Overloads = dyn_cast<OverloadExpr>(BaseExpr)) {
+ AllOverloads.append(Overloads->decls_begin(), Overloads->decls_end());
+ TryCall = true;
+ Overloaded = true;
+ } else if (DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(BaseExpr)) {
+ if (FunctionDecl* Fun = dyn_cast<FunctionDecl>(DeclRef->getDecl())) {
+ AllOverloads.addDecl(Fun);
+ TryCall = true;
+ }
+ }
+
+ if (TryCall) {
+ // Plunder the overload set for something that would make the member
+ // expression valid.
+ UnresolvedSet<4> ViableOverloads;
+ bool HasViableZeroArgOverload = false;
+ for (OverloadExpr::decls_iterator it = AllOverloads.begin(),
+ DeclsEnd = AllOverloads.end(); it != DeclsEnd; ++it) {
+ const FunctionDecl *OverloadDecl = cast<FunctionDecl>(*it);
+ QualType ResultTy = OverloadDecl->getResultType();
+ if ((!IsArrow && ResultTy->isRecordType()) ||
+ (IsArrow && ResultTy->isPointerType() &&
+ ResultTy->getPointeeType()->isRecordType())) {
+ ViableOverloads.addDecl(*it);
+ if (OverloadDecl->getMinRequiredArguments() == 0) {
+ HasViableZeroArgOverload = true;
}
}
- if (HasZeroArgCandidateOverload && CandidateOverloads.size() == 1) {
- // We have one reasonable overload, and there's only one way to call it,
- // so emit a fixit and try to recover
- Diag(ParenInsertionLoc, diag::err_member_reference_needs_call)
- << 1
- << BaseExpr->getSourceRange()
- << FixItHint::CreateInsertion(ParenInsertionLoc, "()");
- TryCall = true;
- } else {
- Diag(BaseExpr->getExprLoc(), diag::err_member_reference_needs_call)
- << 0
- << BaseExpr->getSourceRange();
- int CandidateOverloadCount = CandidateOverloads.size();
- int I;
- for (I = 0; I < CandidateOverloadCount; ++I) {
- // FIXME: Magic number for max shown overloads stolen from
- // OverloadCandidateSet::NoteCandidates.
- if (I >= 4 && Diags.getShowOverloads() == Diagnostic::Ovl_Best) {
- break;
- }
- Diag(CandidateOverloads[I].getDecl()->getSourceRange().getBegin(),
- diag::note_member_ref_possible_intended_overload);
- }
- if (I != CandidateOverloadCount) {
- Diag(BaseExpr->getExprLoc(), diag::note_ovl_too_many_candidates)
- << int(CandidateOverloadCount - I);
+ }
+
+ if (!HasViableZeroArgOverload || ViableOverloads.size() != 1) {
+ Diag(BaseExpr->getExprLoc(), diag::err_member_reference_needs_call)
+ << 1 << 0
+ << BaseExpr->getSourceRange();
+ int ViableOverloadCount = ViableOverloads.size();
+ int I;
+ for (I = 0; I < ViableOverloadCount; ++I) {
+ // FIXME: Magic number for max shown overloads stolen from
+ // OverloadCandidateSet::NoteCandidates.
+ if (I >= 4 && Diags.getShowOverloads() == Diagnostic::Ovl_Best) {
+ break;
}
- return ExprError();
+ Diag(ViableOverloads[I].getDecl()->getSourceRange().getBegin(),
+ diag::note_member_ref_possible_intended_overload);
}
- } else {
- if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(Fun)) {
- TryCall = (FPT->getNumArgs() == 0);
- } else {
- TryCall = true;
+ if (I != ViableOverloadCount) {
+ Diag(BaseExpr->getExprLoc(), diag::note_ovl_too_many_candidates)
+ << int(ViableOverloadCount - I);
}
-
- if (TryCall) {
- QualType ResultTy = Fun->getResultType();
- TryCall = (!IsArrow && ResultTy->isRecordType()) ||
- (IsArrow && ResultTy->isPointerType() &&
- ResultTy->getAs<PointerType>()->getPointeeType()->isRecordType());
+ return ExprError();
+ }
+ } else {
+ // We don't have an expression that's convenient to get a Decl from, but we
+ // can at least check if the type is "function of 0 arguments which returns
+ // an acceptable type".
+ const FunctionType *Fun = NULL;
+ if (const PointerType *Ptr = BaseType->getAs<PointerType>()) {
+ if ((Fun = Ptr->getPointeeType()->getAs<FunctionType>())) {
+ TryCall = true;
}
+ } else if ((Fun = BaseType->getAs<FunctionType>())) {
+ TryCall = true;
}
-
if (TryCall) {
- if (Fun) {
- Diag(BaseExpr->getExprLoc(),
- diag::err_member_reference_needs_call_zero_arg)
- << QualType(Fun, 0)
- << FixItHint::CreateInsertion(ParenInsertionLoc, "()");
+ if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(Fun)) {
+ if (FPT->getNumArgs() == 0) {
+ QualType ResultTy = Fun->getResultType();
+ TryCall = (!IsArrow && ResultTy->isRecordType()) ||
+ (IsArrow && ResultTy->isPointerType() &&
+ ResultTy->getPointeeType()->isRecordType());
+ }
}
-
- ExprResult NewBase
- = ActOnCallExpr(0, BaseExpr, ParenInsertionLoc,
- MultiExprArg(*this, 0, 0), ParenInsertionLoc);
- if (NewBase.isInvalid())
- return ExprError();
- BaseExpr = NewBase.takeAs<Expr>();
-
-
- DefaultFunctionArrayConversion(BaseExpr);
- BaseType = BaseExpr->getType();
-
- return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS,
- ObjCImpDecl, HasTemplateArgs);
}
}
+ if (TryCall) {
+ // At this point, we know BaseExpr looks like it's potentially callable with
+ // 0 arguments, and that it returns something of a reasonable type, so we
+ // can emit a fixit and carry on pretending that BaseExpr was actually a
+ // CallExpr.
+ SourceLocation ParenInsertionLoc =
+ PP.getLocForEndOfToken(BaseExpr->getLocEnd());
+ Diag(BaseExpr->getExprLoc(), diag::err_member_reference_needs_call)
+ << int(Overloaded) << 1
+ << BaseExpr->getSourceRange()
+ << FixItHint::CreateInsertion(ParenInsertionLoc, "()");
+ ExprResult NewBase = ActOnCallExpr(0, BaseExpr, ParenInsertionLoc,
+ MultiExprArg(*this, 0, 0),
+ ParenInsertionLoc);
+ if (NewBase.isInvalid())
+ return ExprError();
+ BaseExpr = NewBase.takeAs<Expr>();
+ DefaultFunctionArrayConversion(BaseExpr);
+ return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS,
+ ObjCImpDecl, HasTemplateArgs);
+ }
+
Diag(MemberLoc, diag::err_typecheck_member_reference_struct_union)
<< BaseType << BaseExpr->getSourceRange();
@@ -4298,6 +4281,13 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
const FunctionProtoType *Proto,
Expr **Args, unsigned NumArgs,
SourceLocation RParenLoc) {
+ // Bail out early if calling a builtin with custom typechecking.
+ // We don't need to do this in the
+ if (FDecl)
+ if (unsigned ID = FDecl->getBuiltinID())
+ if (Context.BuiltinInfo.hasCustomTypechecking(ID))
+ return false;
+
// C99 6.5.2.2p7 - the arguments are implicitly converted, as if by
// assignment, to the types of the corresponding parameter, ...
unsigned NumArgsInProto = Proto->getNumArgs();
@@ -4625,22 +4615,41 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
RParenLoc);
}
+ unsigned BuiltinID = (FDecl ? FDecl->getBuiltinID() : 0);
+
+ // Bail out early if calling a builtin with custom typechecking.
+ if (BuiltinID && Context.BuiltinInfo.hasCustomTypechecking(BuiltinID))
+ return CheckBuiltinFunctionCall(BuiltinID, TheCall);
+
const FunctionType *FuncT;
- if (!Fn->getType()->isBlockPointerType()) {
+ if (const PointerType *PT = Fn->getType()->getAs<PointerType>()) {
// C99 6.5.2.2p1 - "The expression that denotes the called function shall
// have type pointer to function".
- const PointerType *PT = Fn->getType()->getAs<PointerType>();
- if (PT == 0)
- return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function)
- << Fn->getType() << Fn->getSourceRange());
FuncT = PT->getPointeeType()->getAs<FunctionType>();
- } else { // This is a block call.
- FuncT = Fn->getType()->getAs<BlockPointerType>()->getPointeeType()->
- getAs<FunctionType>();
- }
- if (FuncT == 0)
+ if (FuncT == 0)
+ return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function)
+ << Fn->getType() << Fn->getSourceRange());
+ } else if (const BlockPointerType *BPT =
+ Fn->getType()->getAs<BlockPointerType>()) {
+ FuncT = BPT->getPointeeType()->castAs<FunctionType>();
+ } else {
return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function)
<< Fn->getType() << Fn->getSourceRange());
+ }
+
+ if (getLangOptions().CUDA) {
+ if (Config) {
+ // CUDA: Kernel calls must be to global functions
+ if (FDecl && !FDecl->hasAttr<CUDAGlobalAttr>())
+ return ExprError(Diag(LParenLoc,diag::err_kern_call_not_global_function)
+ << FDecl->getName() << Fn->getSourceRange());
+
+ // CUDA: Kernel function must have 'void' return type
+ if (!FuncT->getResultType()->isVoidType())
+ return ExprError(Diag(LParenLoc, diag::err_kern_type_not_void_return)
+ << Fn->getType() << Fn->getSourceRange());
+ }
+ }
// Check for a valid return type
if (CheckCallReturnType(FuncT->getResultType(),
@@ -4721,7 +4730,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
if (CheckFunctionCall(FDecl, TheCall))
return ExprError();
- if (unsigned BuiltinID = FDecl->getBuiltinID())
+ if (BuiltinID)
return CheckBuiltinFunctionCall(BuiltinID, TheCall);
} else if (NDecl) {
if (CheckBlockCall(NDecl, TheCall))
@@ -6372,8 +6381,8 @@ QualType Sema::CheckMultiplyDivideOperands(
// Check for division by zero.
if (isDiv &&
rex->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull))
- DiagRuntimeBehavior(Loc, PDiag(diag::warn_division_by_zero)
- << rex->getSourceRange());
+ DiagRuntimeBehavior(Loc, rex, PDiag(diag::warn_division_by_zero)
+ << rex->getSourceRange());
return compType;
}
@@ -6394,8 +6403,8 @@ QualType Sema::CheckRemainderOperands(
// Check for remainder by zero.
if (rex->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull))
- DiagRuntimeBehavior(Loc, PDiag(diag::warn_remainder_by_zero)
- << rex->getSourceRange());
+ DiagRuntimeBehavior(Loc, rex, PDiag(diag::warn_remainder_by_zero)
+ << rex->getSourceRange());
return compType;
}
@@ -6629,9 +6638,61 @@ static bool isScopedEnumerationType(QualType T) {
return false;
}
+static void DiagnoseBadShiftValues(Sema& S, Expr *&lex, Expr *&rex,
+ SourceLocation Loc, unsigned Opc,
+ QualType LHSTy) {
+ llvm::APSInt Right;
+ // Check right/shifter operand
+ if (rex->isValueDependent() || !rex->isIntegerConstantExpr(Right, S.Context))
+ return;
+
+ if (Right.isNegative()) {
+ S.Diag(Loc, diag::warn_shift_negative) << rex->getSourceRange();
+ return;
+ }
+ llvm::APInt LeftBits(Right.getBitWidth(),
+ S.Context.getTypeSize(lex->getType()));
+ if (Right.uge(LeftBits)) {
+ S.Diag(Loc, diag::warn_shift_gt_typewidth) << rex->getSourceRange();
+ return;
+ }
+ if (Opc != BO_Shl)
+ return;
+
+ // When left shifting an ICE which is signed, we can check for overflow which
+ // according to C++ has undefined behavior ([expr.shift] 5.8/2). Unsigned
+ // integers have defined behavior modulo one more than the maximum value
+ // representable in the result type, so never warn for those.
+ llvm::APSInt Left;
+ if (lex->isValueDependent() || !lex->isIntegerConstantExpr(Left, S.Context) ||
+ LHSTy->hasUnsignedIntegerRepresentation())
+ return;
+ llvm::APInt ResultBits =
+ static_cast<llvm::APInt&>(Right) + Left.getMinSignedBits();
+ if (LeftBits.uge(ResultBits))
+ return;
+ llvm::APSInt Result = Left.extend(ResultBits.getLimitedValue());
+ Result = Result.shl(Right);
+
+ // If we are only missing a sign bit, this is less likely to result in actual
+ // bugs -- if the result is cast back to an unsigned type, it will have the
+ // expected value. Thus we place this behind a different warning that can be
+ // turned off separately if needed.
+ if (LeftBits == ResultBits - 1) {
+ S.Diag(Loc, diag::warn_shift_result_overrides_sign_bit)
+ << Result.toString(10) << LHSTy
+ << lex->getSourceRange() << rex->getSourceRange();
+ return;
+ }
+
+ S.Diag(Loc, diag::warn_shift_result_gt_typewidth)
+ << Result.toString(10) << Result.getMinSignedBits() << LHSTy
+ << Left.getBitWidth() << lex->getSourceRange() << rex->getSourceRange();
+}
+
// C99 6.5.7
QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
- bool isCompAssign) {
+ unsigned Opc, bool isCompAssign) {
// C99 6.5.7p2: Each of the operands shall have integer type.
if (!lex->getType()->hasIntegerRepresentation() ||
!rex->getType()->hasIntegerRepresentation())
@@ -6662,19 +6723,7 @@ QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
UsualUnaryConversions(rex);
// Sanity-check shift operands
- llvm::APSInt Right;
- // Check right/shifter operand
- if (!rex->isValueDependent() &&
- rex->isIntegerConstantExpr(Right, Context)) {
- if (Right.isNegative())
- Diag(Loc, diag::warn_shift_negative) << rex->getSourceRange();
- else {
- llvm::APInt LeftBits(Right.getBitWidth(),
- Context.getTypeSize(lex->getType()));
- if (Right.uge(LeftBits))
- Diag(Loc, diag::warn_shift_gt_typewidth) << rex->getSourceRange();
- }
- }
+ DiagnoseBadShiftValues(*this, lex, rex, Loc, Opc, LHSTy);
// "The type of the result is that of the promoted left operand."
return LHSTy;
@@ -6738,7 +6787,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(RHSStripped)) {
if (DRL->getDecl() == DRR->getDecl() &&
!IsWithinTemplateSpecialization(DRL->getDecl())) {
- DiagRuntimeBehavior(Loc, PDiag(diag::warn_comparison_always)
+ DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always)
<< 0 // self-
<< (Opc == BO_EQ
|| Opc == BO_LE
@@ -6760,7 +6809,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
always_evals_to = 2; // e.g. array1 <= array2
break;
}
- DiagRuntimeBehavior(Loc, PDiag(diag::warn_comparison_always)
+ DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always)
<< 1 // array
<< always_evals_to);
}
@@ -6801,7 +6850,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
default: assert(false && "Invalid comparison operator");
}
- DiagRuntimeBehavior(Loc,
+ DiagRuntimeBehavior(Loc, 0,
PDiag(diag::warn_stringcompare)
<< isa<ObjCEncodeExpr>(literalStringStripped)
<< literalString->getSourceRange());
@@ -7111,7 +7160,7 @@ QualType Sema::CheckVectorCompareOperands(Expr *&lex, Expr *&rex,
if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(lex->IgnoreParens()))
if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(rex->IgnoreParens()))
if (DRL->getDecl() == DRR->getDecl())
- DiagRuntimeBehavior(Loc,
+ DiagRuntimeBehavior(Loc, 0,
PDiag(diag::warn_comparison_always)
<< 0 // self-
<< 2 // "a constant"
@@ -7372,9 +7421,11 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS,
UO->getSubExpr()->IgnoreParenCasts()->
isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull) &&
!UO->getType().isVolatileQualified()) {
- Diag(UO->getOperatorLoc(), diag::warn_indirection_through_null)
- << UO->getSubExpr()->getSourceRange();
- Diag(UO->getOperatorLoc(), diag::note_indirection_through_null);
+ DiagRuntimeBehavior(UO->getOperatorLoc(), UO,
+ PDiag(diag::warn_indirection_through_null)
+ << UO->getSubExpr()->getSourceRange());
+ DiagRuntimeBehavior(UO->getOperatorLoc(), UO,
+ PDiag(diag::note_indirection_through_null));
}
// Check for trivial buffer overflows.
@@ -7959,7 +8010,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
break;
case BO_Shl:
case BO_Shr:
- ResultTy = CheckShiftOperands(lhs, rhs, OpLoc);
+ ResultTy = CheckShiftOperands(lhs, rhs, OpLoc, Opc);
break;
case BO_LE:
case BO_LT:
@@ -8006,7 +8057,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
break;
case BO_ShlAssign:
case BO_ShrAssign:
- CompResultTy = CheckShiftOperands(lhs, rhs, OpLoc, true);
+ CompResultTy = CheckShiftOperands(lhs, rhs, OpLoc, Opc, true);
CompLHSTy = CompResultTy;
if (!CompResultTy.isNull())
ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
@@ -8563,7 +8614,7 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
// (clause 9).
if (CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) {
if (!CRD->isPOD() && !DidWarnAboutNonPOD &&
- DiagRuntimeBehavior(BuiltinLoc,
+ DiagRuntimeBehavior(BuiltinLoc, 0,
PDiag(diag::warn_offsetof_non_pod_type)
<< SourceRange(CompPtr[0].LocStart, OC.LocEnd)
<< CurrentType))
@@ -8907,12 +8958,8 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
BlockExpr *Result = new (Context) BlockExpr(BSI->TheDecl, BlockTy);
- // Issue any analysis-based warnings.
- const sema::AnalysisBasedWarnings::Policy &WP =
- AnalysisWarnings.getDefaultPolicy();
- AnalysisWarnings.IssueWarnings(WP, Result);
-
- PopFunctionOrBlockScope();
+ const AnalysisBasedWarnings::Policy &WP = AnalysisWarnings.getDefaultPolicy();
+ PopFunctionOrBlockScope(&WP, Result->getBlockDecl(), Result);
return Owned(Result);
}
@@ -9350,9 +9397,12 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
}
}
- // Keep track of used but undefined variables.
+ // Keep track of used but undefined variables. We make a hole in
+ // the warning for static const data members with in-line
+ // initializers.
if (Var->hasDefinition() == VarDecl::DeclarationOnly
- && Var->getLinkage() != ExternalLinkage) {
+ && Var->getLinkage() != ExternalLinkage
+ && !(Var->isStaticDataMember() && Var->hasInit())) {
SourceLocation &old = UndefinedInternals[Var->getCanonicalDecl()];
if (old.isInvalid()) old = Loc;
}
@@ -9484,7 +9534,7 @@ void Sema::MarkDeclarationsReferencedInExpr(Expr *E) {
/// behavior of a program, such as passing a non-POD value through an ellipsis.
/// Failure to do so will likely result in spurious diagnostics or failures
/// during overload resolution or within sizeof/alignof/typeof/typeid.
-bool Sema::DiagRuntimeBehavior(SourceLocation Loc,
+bool Sema::DiagRuntimeBehavior(SourceLocation Loc, const Stmt *stmt,
const PartialDiagnostic &PD) {
switch (ExprEvalContexts.back().Context ) {
case Unevaluated:
@@ -9493,7 +9543,13 @@ bool Sema::DiagRuntimeBehavior(SourceLocation Loc,
case PotentiallyEvaluated:
case PotentiallyEvaluatedIfUsed:
- Diag(Loc, PD);
+ if (stmt && getCurFunctionOrMethodDecl()) {
+ FunctionScopes.back()->PossiblyUnreachableDiags.
+ push_back(sema::PossiblyUnreachableDiag(PD, Loc, stmt));
+ }
+ else
+ Diag(Loc, PD);
+
return true;
case PotentiallyPotentiallyEvaluated:
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp
index f9c2c9a..6dd7aab 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp
@@ -107,7 +107,7 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc,
// Nothing left to do.
} else if (LookAtPrefix && (Prefix = NNS->getPrefix())) {
CXXScopeSpec PrefixSS;
- PrefixSS.setScopeRep(Prefix);
+ PrefixSS.Adopt(NestedNameSpecifierLoc(Prefix, SS.location_data()));
LookupCtx = computeDeclContext(PrefixSS, EnteringContext);
isDependent = isDependentScopeSpecifier(PrefixSS);
} else if (ObjectTypePtr) {
@@ -476,7 +476,9 @@ Sema::ActOnCXXNullPtrLiteral(SourceLocation Loc) {
/// ActOnCXXThrow - Parse throw expressions.
ExprResult
Sema::ActOnCXXThrow(SourceLocation OpLoc, Expr *Ex) {
- if (!getLangOptions().Exceptions)
+ // Don't report an error if 'throw' is used in system headers.
+ if (!getLangOptions().Exceptions &&
+ !getSourceManager().isInSystemHeader(OpLoc))
Diag(OpLoc, diag::err_exceptions_disabled) << "throw";
if (Ex && !Ex->isTypeDependent() && CheckCXXThrowOperand(OpLoc, Ex))
@@ -1347,6 +1349,7 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
case OR_Success: {
// Got one!
FunctionDecl *FnDecl = Best->Function;
+ MarkDeclarationReferenced(StartLoc, FnDecl);
// The first argument is size_t, and the first parameter must be size_t,
// too. This is checked on declaration and can be assumed. (It can't be
// asserted on, though, since invalid decls are left in there.)
@@ -1384,7 +1387,10 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
case OR_Deleted:
Diag(StartLoc, diag::err_ovl_deleted_call)
<< Best->Function->isDeleted()
- << Name << Range;
+ << Name
+ << Best->Function->getMessageUnavailableAttr(
+ !Best->Function->isDeleted())
+ << Range;
Candidates.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
return true;
}
@@ -2920,6 +2926,8 @@ static bool FindConditionalOverload(Sema &Self, Expr *&LHS, Expr *&RHS,
Self.PerformImplicitConversion(RHS, Best->BuiltinTypes.ParamTypes[1],
Best->Conversions[1], Sema::AA_Converting))
break;
+ if (Best->Function)
+ Self.MarkDeclarationReferenced(QuestionLoc, Best->Function);
return false;
case OR_No_Viable_Function:
@@ -3580,14 +3588,14 @@ ExprResult Sema::DiagnoseDtorReference(SourceLocation NameLoc,
}
ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- const CXXScopeSpec &SS,
- TypeSourceInfo *ScopeTypeInfo,
- SourceLocation CCLoc,
- SourceLocation TildeLoc,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ const CXXScopeSpec &SS,
+ TypeSourceInfo *ScopeTypeInfo,
+ SourceLocation CCLoc,
+ SourceLocation TildeLoc,
PseudoDestructorTypeStorage Destructed,
- bool HasTrailingLParen) {
+ bool HasTrailingLParen) {
TypeSourceInfo *DestructedTypeInfo = Destructed.getTypeSourceInfo();
// C++ [expr.pseudo]p2:
@@ -3662,7 +3670,7 @@ ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base,
Expr *Result
= new (Context) CXXPseudoDestructorExpr(Context, Base,
OpKind == tok::arrow, OpLoc,
- SS.getScopeRep(), SS.getRange(),
+ SS.getWithLocInContext(Context),
ScopeTypeInfo,
CCLoc,
TildeLoc,
@@ -3675,14 +3683,14 @@ ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base,
}
ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- CXXScopeSpec &SS,
- UnqualifiedId &FirstTypeName,
- SourceLocation CCLoc,
- SourceLocation TildeLoc,
- UnqualifiedId &SecondTypeName,
- bool HasTrailingLParen) {
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ CXXScopeSpec &SS,
+ UnqualifiedId &FirstTypeName,
+ SourceLocation CCLoc,
+ SourceLocation TildeLoc,
+ UnqualifiedId &SecondTypeName,
+ bool HasTrailingLParen) {
assert((FirstTypeName.getKind() == UnqualifiedId::IK_TemplateId ||
FirstTypeName.getKind() == UnqualifiedId::IK_Identifier) &&
"Invalid first type name in pseudo-destructor");
@@ -3714,8 +3722,8 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
// record types and dependent types matter.
ParsedType ObjectTypePtrForLookup;
if (!SS.isSet()) {
- if (const Type *T = ObjectType->getAs<RecordType>())
- ObjectTypePtrForLookup = ParsedType::make(QualType(T, 0));
+ if (ObjectType->isRecordType())
+ ObjectTypePtrForLookup = ParsedType::make(ObjectType);
else if (ObjectType->isDependentType())
ObjectTypePtrForLookup = ParsedType::make(Context.DependentTy);
}
@@ -3784,7 +3792,7 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
if (FirstTypeName.getKind() == UnqualifiedId::IK_Identifier) {
ParsedType T = getTypeName(*FirstTypeName.Identifier,
FirstTypeName.StartLocation,
- S, &SS, false, false, ObjectTypePtrForLookup);
+ S, &SS, true, false, ObjectTypePtrForLookup);
if (!T) {
Diag(FirstTypeName.StartLocation,
diag::err_pseudo_dtor_destructor_non_type)
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
index b9a6a57..5882da0 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
@@ -31,10 +31,8 @@ using namespace clang;
// Sema Initialization Checking
//===----------------------------------------------------------------------===//
-static Expr *IsStringInit(Expr *Init, QualType DeclType, ASTContext &Context) {
- const ArrayType *AT = Context.getAsArrayType(DeclType);
- if (!AT) return 0;
-
+static Expr *IsStringInit(Expr *Init, const ArrayType *AT,
+ ASTContext &Context) {
if (!isa<ConstantArrayType>(AT) && !isa<IncompleteArrayType>(AT))
return 0;
@@ -66,13 +64,20 @@ static Expr *IsStringInit(Expr *Init, QualType DeclType, ASTContext &Context) {
return 0;
}
-static void CheckStringInit(Expr *Str, QualType &DeclT, Sema &S) {
+static Expr *IsStringInit(Expr *init, QualType declType, ASTContext &Context) {
+ const ArrayType *arrayType = Context.getAsArrayType(declType);
+ if (!arrayType) return 0;
+
+ return IsStringInit(init, arrayType, Context);
+}
+
+static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT,
+ Sema &S) {
// Get the length of the string as parsed.
uint64_t StrLength =
cast<ConstantArrayType>(Str->getType())->getSize().getZExtValue();
- const ArrayType *AT = S.Context.getAsArrayType(DeclT);
if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(AT)) {
// C99 6.7.8p14. We have an array of character type with unknown size
// being initialized to a string literal.
@@ -651,82 +656,93 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
newStructuredList, newStructuredIndex);
++StructuredIndex;
++Index;
- } else if (Expr *Str = IsStringInit(expr, ElemType, SemaRef.Context)) {
- CheckStringInit(Str, ElemType, SemaRef);
- UpdateStructuredListElement(StructuredList, StructuredIndex, Str);
- ++Index;
+ return;
} else if (ElemType->isScalarType()) {
- CheckScalarType(Entity, IList, ElemType, Index,
- StructuredList, StructuredIndex);
+ return CheckScalarType(Entity, IList, ElemType, Index,
+ StructuredList, StructuredIndex);
} else if (ElemType->isReferenceType()) {
- CheckReferenceType(Entity, IList, ElemType, Index,
- StructuredList, StructuredIndex);
- } else {
- if (SemaRef.getLangOptions().CPlusPlus) {
- // C++ [dcl.init.aggr]p12:
- // All implicit type conversions (clause 4) are considered when
- // initializing the aggregate member with an ini- tializer from
- // an initializer-list. If the initializer can initialize a
- // member, the member is initialized. [...]
-
- // FIXME: Better EqualLoc?
- InitializationKind Kind =
- InitializationKind::CreateCopy(expr->getLocStart(), SourceLocation());
- InitializationSequence Seq(SemaRef, Entity, Kind, &expr, 1);
-
- if (Seq) {
- ExprResult Result =
- Seq.Perform(SemaRef, Entity, Kind, MultiExprArg(&expr, 1));
- if (Result.isInvalid())
- hadError = true;
-
- UpdateStructuredListElement(StructuredList, StructuredIndex,
- Result.takeAs<Expr>());
- ++Index;
- return;
- }
+ return CheckReferenceType(Entity, IList, ElemType, Index,
+ StructuredList, StructuredIndex);
+ }
- // Fall through for subaggregate initialization
- } else {
- // C99 6.7.8p13:
- //
- // The initializer for a structure or union object that has
- // automatic storage duration shall be either an initializer
- // list as described below, or a single expression that has
- // compatible structure or union type. In the latter case, the
- // initial value of the object, including unnamed members, is
- // that of the expression.
- if ((ElemType->isRecordType() || ElemType->isVectorType()) &&
- SemaRef.CheckSingleAssignmentConstraints(ElemType, expr)
- == Sema::Compatible) {
- SemaRef.DefaultFunctionArrayLvalueConversion(expr);
- UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
- ++Index;
- return;
- }
+ if (const ArrayType *arrayType = SemaRef.Context.getAsArrayType(ElemType)) {
+ // arrayType can be incomplete if we're initializing a flexible
+ // array member. There's nothing we can do with the completed
+ // type here, though.
- // Fall through for subaggregate initialization
+ if (Expr *Str = IsStringInit(expr, arrayType, SemaRef.Context)) {
+ CheckStringInit(Str, ElemType, arrayType, SemaRef);
+ UpdateStructuredListElement(StructuredList, StructuredIndex, Str);
+ ++Index;
+ return;
}
+ // Fall through for subaggregate initialization.
+
+ } else if (SemaRef.getLangOptions().CPlusPlus) {
// C++ [dcl.init.aggr]p12:
+ // All implicit type conversions (clause 4) are considered when
+ // initializing the aggregate member with an ini- tializer from
+ // an initializer-list. If the initializer can initialize a
+ // member, the member is initialized. [...]
+
+ // FIXME: Better EqualLoc?
+ InitializationKind Kind =
+ InitializationKind::CreateCopy(expr->getLocStart(), SourceLocation());
+ InitializationSequence Seq(SemaRef, Entity, Kind, &expr, 1);
+
+ if (Seq) {
+ ExprResult Result =
+ Seq.Perform(SemaRef, Entity, Kind, MultiExprArg(&expr, 1));
+ if (Result.isInvalid())
+ hadError = true;
+
+ UpdateStructuredListElement(StructuredList, StructuredIndex,
+ Result.takeAs<Expr>());
+ ++Index;
+ return;
+ }
+
+ // Fall through for subaggregate initialization
+ } else {
+ // C99 6.7.8p13:
//
- // [...] Otherwise, if the member is itself a non-empty
- // subaggregate, brace elision is assumed and the initializer is
- // considered for the initialization of the first member of
- // the subaggregate.
- if (ElemType->isAggregateType() || ElemType->isVectorType()) {
- CheckImplicitInitList(Entity, IList, ElemType, Index, StructuredList,
- StructuredIndex);
- ++StructuredIndex;
- } else {
- // We cannot initialize this element, so let
- // PerformCopyInitialization produce the appropriate diagnostic.
- SemaRef.PerformCopyInitialization(Entity, SourceLocation(),
- SemaRef.Owned(expr));
- hadError = true;
+ // The initializer for a structure or union object that has
+ // automatic storage duration shall be either an initializer
+ // list as described below, or a single expression that has
+ // compatible structure or union type. In the latter case, the
+ // initial value of the object, including unnamed members, is
+ // that of the expression.
+ if ((ElemType->isRecordType() || ElemType->isVectorType()) &&
+ SemaRef.CheckSingleAssignmentConstraints(ElemType, expr)
+ == Sema::Compatible) {
+ SemaRef.DefaultFunctionArrayLvalueConversion(expr);
+ UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
++Index;
- ++StructuredIndex;
+ return;
}
+
+ // Fall through for subaggregate initialization
+ }
+
+ // C++ [dcl.init.aggr]p12:
+ //
+ // [...] Otherwise, if the member is itself a non-empty
+ // subaggregate, brace elision is assumed and the initializer is
+ // considered for the initialization of the first member of
+ // the subaggregate.
+ if (ElemType->isAggregateType() || ElemType->isVectorType()) {
+ CheckImplicitInitList(Entity, IList, ElemType, Index, StructuredList,
+ StructuredIndex);
+ ++StructuredIndex;
+ } else {
+ // We cannot initialize this element, so let
+ // PerformCopyInitialization produce the appropriate diagnostic.
+ SemaRef.PerformCopyInitialization(Entity, SourceLocation(),
+ SemaRef.Owned(expr));
+ hadError = true;
+ ++Index;
+ ++StructuredIndex;
}
}
@@ -936,11 +952,13 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex) {
+ const ArrayType *arrayType = SemaRef.Context.getAsArrayType(DeclType);
+
// Check for the special-case of initializing an array with a string.
if (Index < IList->getNumInits()) {
- if (Expr *Str = IsStringInit(IList->getInit(Index), DeclType,
+ if (Expr *Str = IsStringInit(IList->getInit(Index), arrayType,
SemaRef.Context)) {
- CheckStringInit(Str, DeclType, SemaRef);
+ CheckStringInit(Str, DeclType, arrayType, SemaRef);
// We place the string literal directly into the resulting
// initializer list. This is the only place where the structure
// of the structured initializer list doesn't match exactly,
@@ -952,8 +970,7 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
return;
}
}
- if (const VariableArrayType *VAT =
- SemaRef.Context.getAsVariableArrayType(DeclType)) {
+ if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(arrayType)) {
// Check for VLAs; in standard C it would be possible to check this
// earlier, but I don't know where clang accepts VLAs (gcc accepts
// them in all sorts of strange places).
@@ -970,16 +987,14 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
llvm::APSInt maxElements(elementIndex.getBitWidth(),
elementIndex.isUnsigned());
bool maxElementsKnown = false;
- if (const ConstantArrayType *CAT =
- SemaRef.Context.getAsConstantArrayType(DeclType)) {
+ if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(arrayType)) {
maxElements = CAT->getSize();
elementIndex = elementIndex.extOrTrunc(maxElements.getBitWidth());
elementIndex.setIsUnsigned(maxElements.isUnsigned());
maxElementsKnown = true;
}
- QualType elementType = SemaRef.Context.getAsArrayType(DeclType)
- ->getElementType();
+ QualType elementType = arrayType->getElementType();
while (Index < IList->getNumInits()) {
Expr *Init = IList->getInit(Index);
if (DesignatedInitExpr *DIE = dyn_cast<DesignatedInitExpr>(Init)) {
@@ -2059,6 +2074,7 @@ void InitializationSequence::Step::Destroy() {
case SK_CAssignment:
case SK_StringInit:
case SK_ObjCObjectConversion:
+ case SK_ArrayInit:
break;
case SK_ConversionSequence:
@@ -2090,6 +2106,8 @@ bool InitializationSequence::isAmbiguous() const {
case FK_InitListBadDestinationType:
case FK_DefaultInitOfConst:
case FK_Incomplete:
+ case FK_ArrayTypeMismatch:
+ case FK_NonConstantArrayInit:
return false;
case FK_ReferenceInitOverloadFailed:
@@ -2232,6 +2250,13 @@ void InitializationSequence::AddObjCObjectConversionStep(QualType T) {
Steps.push_back(S);
}
+void InitializationSequence::AddArrayInitStep(QualType T) {
+ Step S;
+ S.Kind = SK_ArrayInit;
+ S.Type = T;
+ Steps.push_back(S);
+}
+
void InitializationSequence::SetOverloadFailure(FailureKind Failure,
OverloadingResult Result) {
SequenceKind = FailedSequence;
@@ -2416,6 +2441,10 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
FunctionDecl *Function = Best->Function;
+ // This is the overload that will actually be used for the initialization, so
+ // mark it as used.
+ S.MarkDeclarationReferenced(DeclLoc, Function);
+
// Compute the returned type of the conversion.
if (isa<CXXConversionDecl>(Function))
T2 = Function->getResultType();
@@ -3020,6 +3049,7 @@ static void TryUserDefinedConversion(Sema &S,
}
FunctionDecl *Function = Best->Function;
+ S.MarkDeclarationReferenced(DeclLoc, Function);
if (isa<CXXConstructorDecl>(Function)) {
// Add the user-defined conversion step. Any cv-qualification conversion is
@@ -3054,6 +3084,25 @@ static void TryUserDefinedConversion(Sema &S,
}
}
+/// \brief Determine whether we have compatible array types for the
+/// purposes of GNU by-copy array initialization.
+static bool hasCompatibleArrayTypes(ASTContext &Context,
+ const ArrayType *Dest,
+ const ArrayType *Source) {
+ // If the source and destination array types are equivalent, we're
+ // done.
+ if (Context.hasSameType(QualType(Dest, 0), QualType(Source, 0)))
+ return true;
+
+ // Make sure that the element types are the same.
+ if (!Context.hasSameType(Dest->getElementType(), Source->getElementType()))
+ return false;
+
+ // The only mismatch we allow is when the destination is an
+ // incomplete array type and the source is a constant array type.
+ return Source->isConstantArrayType() && Dest->isIncompleteArrayType();
+}
+
InitializationSequence::InitializationSequence(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
@@ -3109,14 +3158,6 @@ InitializationSequence::InitializationSequence(Sema &S,
return;
}
- // - If the destination type is an array of characters, an array of
- // char16_t, an array of char32_t, or an array of wchar_t, and the
- // initializer is a string literal, see 8.5.2.
- if (Initializer && IsStringInit(Initializer, DestType, Context)) {
- TryStringLiteralInitialization(S, Entity, Kind, Initializer, *this);
- return;
- }
-
// - If the initializer is (), the object is value-initialized.
if (Kind.getKind() == InitializationKind::IK_Value ||
(Kind.getKind() == InitializationKind::IK_Direct && NumArgs == 0)) {
@@ -3130,10 +3171,34 @@ InitializationSequence::InitializationSequence(Sema &S,
return;
}
+ // - If the destination type is an array of characters, an array of
+ // char16_t, an array of char32_t, or an array of wchar_t, and the
+ // initializer is a string literal, see 8.5.2.
// - Otherwise, if the destination type is an array, the program is
// ill-formed.
- if (const ArrayType *AT = Context.getAsArrayType(DestType)) {
- if (AT->getElementType()->isAnyCharacterType())
+ if (const ArrayType *DestAT = Context.getAsArrayType(DestType)) {
+ if (Initializer && IsStringInit(Initializer, DestAT, Context)) {
+ TryStringLiteralInitialization(S, Entity, Kind, Initializer, *this);
+ return;
+ }
+
+ // Note: as an GNU C extension, we allow initialization of an
+ // array from a compound literal that creates an array of the same
+ // type, so long as the initializer has no side effects.
+ if (!S.getLangOptions().CPlusPlus && Initializer &&
+ isa<CompoundLiteralExpr>(Initializer->IgnoreParens()) &&
+ Initializer->getType()->isArrayType()) {
+ const ArrayType *SourceAT
+ = Context.getAsArrayType(Initializer->getType());
+ if (!hasCompatibleArrayTypes(S.Context, DestAT, SourceAT))
+ SetFailed(FK_ArrayTypeMismatch);
+ else if (Initializer->HasSideEffects(S.Context))
+ SetFailed(FK_NonConstantArrayInit);
+ else {
+ setSequenceKind(ArrayInit);
+ AddArrayInitStep(DestType);
+ }
+ } else if (DestAT->getElementType()->isAnyCharacterType())
SetFailed(FK_ArrayNeedsInitListOrStringLiteral);
else
SetFailed(FK_ArrayNeedsInitList);
@@ -3482,6 +3547,8 @@ static ExprResult CopyObject(Sema &S,
return S.Owned(CurInitExpr);
}
+ S.MarkDeclarationReferenced(Loc, Constructor);
+
// Determine the arguments required to actually perform the
// constructor call (we might have derived-to-base conversions, or
// the copy constructor may have default arguments).
@@ -3616,7 +3683,8 @@ InitializationSequence::Perform(Sema &S,
case SK_ListInitialization:
case SK_CAssignment:
case SK_StringInit:
- case SK_ObjCObjectConversion: {
+ case SK_ObjCObjectConversion:
+ case SK_ArrayInit: {
assert(Args.size() == 1);
Expr *CurInitExpr = Args.get()[0];
if (!CurInitExpr) return ExprError();
@@ -4029,7 +4097,8 @@ InitializationSequence::Perform(Sema &S,
case SK_StringInit: {
QualType Ty = Step->Type;
- CheckStringInit(CurInitExpr, ResultType ? *ResultType : Ty, S);
+ CheckStringInit(CurInitExpr, ResultType ? *ResultType : Ty,
+ S.Context.getAsArrayType(Ty), S);
break;
}
@@ -4040,6 +4109,30 @@ InitializationSequence::Perform(Sema &S,
CurInit.release();
CurInit = S.Owned(CurInitExpr);
break;
+
+ case SK_ArrayInit:
+ // Okay: we checked everything before creating this step. Note that
+ // this is a GNU extension.
+ S.Diag(Kind.getLocation(), diag::ext_array_init_copy)
+ << Step->Type << CurInitExpr->getType()
+ << CurInitExpr->getSourceRange();
+
+ // If the destination type is an incomplete array type, update the
+ // type accordingly.
+ if (ResultType) {
+ if (const IncompleteArrayType *IncompleteDest
+ = S.Context.getAsIncompleteArrayType(Step->Type)) {
+ if (const ConstantArrayType *ConstantSource
+ = S.Context.getAsConstantArrayType(CurInitExpr->getType())) {
+ *ResultType = S.Context.getConstantArrayType(
+ IncompleteDest->getElementType(),
+ ConstantSource->getSize(),
+ ArrayType::Normal, 0);
+ }
+ }
+ }
+
+ break;
}
}
@@ -4081,6 +4174,17 @@ bool InitializationSequence::Diagnose(Sema &S,
<< (Failure == FK_ArrayNeedsInitListOrStringLiteral);
break;
+ case FK_ArrayTypeMismatch:
+ case FK_NonConstantArrayInit:
+ S.Diag(Kind.getLocation(),
+ (Failure == FK_ArrayTypeMismatch
+ ? diag::err_array_init_different_type
+ : diag::err_array_init_non_constant_array))
+ << DestType.getNonReferenceType()
+ << Args[0]->getType()
+ << Args[0]->getSourceRange();
+ break;
+
case FK_AddressOfOverloadFailed: {
DeclAccessPair Found;
S.ResolveAddressOfOverloadedFunction(Args[0],
@@ -4338,6 +4442,14 @@ void InitializationSequence::dump(llvm::raw_ostream &OS) const {
OS << "array requires initializer list or string literal";
break;
+ case FK_ArrayTypeMismatch:
+ OS << "array type mismatch";
+ break;
+
+ case FK_NonConstantArrayInit:
+ OS << "non-constant array initializer";
+ break;
+
case FK_AddressOfOverloadFailed:
OS << "address of overloaded function failed";
break;
@@ -4441,6 +4553,10 @@ void InitializationSequence::dump(llvm::raw_ostream &OS) const {
case StringInit:
OS << "String initialization: ";
break;
+
+ case ArrayInit:
+ OS << "Array initialization: ";
+ break;
}
for (step_iterator S = step_begin(), SEnd = step_end(); S != SEnd; ++S) {
@@ -4520,6 +4636,10 @@ void InitializationSequence::dump(llvm::raw_ostream &OS) const {
case SK_ObjCObjectConversion:
OS << "Objective-C object conversion";
break;
+
+ case SK_ArrayInit:
+ OS << "array initialization";
+ break;
}
}
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp
index 0fd0e08..3deb403 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp
@@ -18,6 +18,7 @@
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/TemplateDeduction.h"
+#include "clang/Sema/ExternalSemaSource.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/Decl.h"
@@ -1132,7 +1133,11 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) {
if (AllowBuiltinCreation)
return LookupBuiltin(*this, R);
- return false;
+ // If we didn't find a use of this identifier, the ExternalSource
+ // may be able to handle the situation.
+ // Note: some lookup failures are expected!
+ // See e.g. R.isForRedeclaration().
+ return (ExternalSource && ExternalSource->LookupUnqualified(R, S));
}
/// @brief Perform qualified name lookup in the namespaces nominated by
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp
index 6fb789c..8d03285 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp
@@ -2261,6 +2261,8 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
// Record the standard conversion we used and the conversion function.
if (CXXConstructorDecl *Constructor
= dyn_cast<CXXConstructorDecl>(Best->Function)) {
+ S.MarkDeclarationReferenced(From->getLocStart(), Constructor);
+
// C++ [over.ics.user]p1:
// If the user-defined conversion is specified by a
// constructor (12.3.1), the initial standard conversion
@@ -2282,6 +2284,8 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
return OR_Success;
} else if (CXXConversionDecl *Conversion
= dyn_cast<CXXConversionDecl>(Best->Function)) {
+ S.MarkDeclarationReferenced(From->getLocStart(), Conversion);
+
// C++ [over.ics.user]p1:
//
// [...] If the user-defined conversion is specified by a
@@ -3068,6 +3072,8 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
if (!Best->FinalConversion.DirectBinding)
return false;
+ if (Best->Function)
+ S.MarkDeclarationReferenced(DeclLoc, Best->Function);
ICS.setUserDefined();
ICS.UserDefined.Before = Best->Conversions[0].Standard;
ICS.UserDefined.After = Best->FinalConversion;
@@ -6280,15 +6286,6 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
Best->Function->getAttr<UnavailableAttr>()))
return OR_Deleted;
- // 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)
- S.MarkDeclarationReferenced(Loc, Best->Function);
-
return OR_Success;
}
@@ -7078,16 +7075,6 @@ void OverloadCandidateSet::NoteCandidates(Sema &S,
S.Diag(OpLoc, diag::note_ovl_too_many_candidates) << int(E - I);
}
-static bool CheckUnresolvedAccess(Sema &S, OverloadExpr *E, DeclAccessPair D) {
- if (isa<UnresolvedLookupExpr>(E))
- return S.CheckUnresolvedLookupAccess(cast<UnresolvedLookupExpr>(E), D);
-
- return S.CheckUnresolvedMemberAccess(cast<UnresolvedMemberExpr>(E), D);
-}
-
-
-
-
// [PossiblyAFunctionType] --> [Return]
// NonFunctionType --> NonFunctionType
// R (A) --> R(A)
@@ -7603,10 +7590,9 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
SourceLocation RParenLoc) {
CXXScopeSpec SS;
- if (ULE->getQualifier()) {
- SS.setScopeRep(ULE->getQualifier());
- SS.setRange(ULE->getQualifierRange());
- }
+ if (ULE->getQualifier())
+ SS.MakeTrivial(SemaRef.Context,
+ ULE->getQualifier(), ULE->getQualifierRange());
TemplateArgumentListInfo TABuffer;
const TemplateArgumentListInfo *ExplicitTemplateArgs = 0;
@@ -7691,6 +7677,7 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,
switch (CandidateSet.BestViableFunction(*this, Fn->getLocStart(), Best)) {
case OR_Success: {
FunctionDecl *FDecl = Best->Function;
+ MarkDeclarationReferenced(Fn->getExprLoc(), FDecl);
CheckUnresolvedLookupAccess(ULE, Best->FoundDecl);
DiagnoseUseOfDecl(FDecl? FDecl : Best->FoundDecl.getDecl(),
ULE->getNameLoc());
@@ -7713,11 +7700,15 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,
break;
case OR_Deleted:
- Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_deleted_call)
- << Best->Function->isDeleted()
- << ULE->getName()
- << Fn->getSourceRange();
- CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
+ {
+ Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_deleted_call)
+ << Best->Function->isDeleted()
+ << ULE->getName()
+ << Best->Function->getMessageUnavailableAttr(
+ !Best->Function->isDeleted())
+ << Fn->getSourceRange();
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
+ }
break;
}
@@ -7824,6 +7815,8 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
// We matched an overloaded operator. Build a call to that
// operator.
+ MarkDeclarationReferenced(OpLoc, FnDecl);
+
// Convert the arguments.
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
CheckMemberOperatorAccess(OpLoc, Args[0], 0, Best->FoundDecl);
@@ -7895,6 +7888,8 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
Diag(OpLoc, diag::err_ovl_deleted_oper)
<< Best->Function->isDeleted()
<< UnaryOperator::getOpcodeStr(Opc)
+ << Best->Function->getMessageUnavailableAttr(
+ !Best->Function->isDeleted())
<< Input->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
return ExprError();
@@ -8047,6 +8042,8 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// We matched an overloaded operator. Build a call to that
// operator.
+ MarkDeclarationReferenced(OpLoc, FnDecl);
+
// Convert the arguments.
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
// Best->Access is only meaningful for class members.
@@ -8161,6 +8158,8 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
Diag(OpLoc, diag::err_ovl_deleted_oper)
<< Best->Function->isDeleted()
<< BinaryOperator::getOpcodeStr(Opc)
+ << Best->Function->getMessageUnavailableAttr(
+ !Best->Function->isDeleted())
<< Args[0]->getSourceRange() << Args[1]->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2);
return ExprError();
@@ -8228,6 +8227,8 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
// We matched an overloaded operator. Build a call to that
// operator.
+ MarkDeclarationReferenced(LLoc, FnDecl);
+
CheckMemberOperatorAccess(LLoc, Args[0], Args[1], Best->FoundDecl);
DiagnoseUseOfDecl(Best->FoundDecl, LLoc);
@@ -8307,6 +8308,8 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
case OR_Deleted:
Diag(LLoc, diag::err_ovl_deleted_oper)
<< Best->Function->isDeleted() << "[]"
+ << Best->Function->getMessageUnavailableAttr(
+ !Best->Function->isDeleted())
<< Args[0]->getSourceRange() << Args[1]->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2,
"[]", LLoc);
@@ -8399,6 +8402,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
Best)) {
case OR_Success:
Method = cast<CXXMethodDecl>(Best->Function);
+ MarkDeclarationReferenced(UnresExpr->getMemberLoc(), Method);
FoundDecl = Best->FoundDecl;
CheckUnresolvedMemberAccess(UnresExpr, Best->FoundDecl);
DiagnoseUseOfDecl(Best->FoundDecl, UnresExpr->getNameLoc());
@@ -8422,7 +8426,10 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
case OR_Deleted:
Diag(UnresExpr->getMemberLoc(), diag::err_ovl_deleted_member_call)
<< Best->Function->isDeleted()
- << DeclName << MemExprE->getSourceRange();
+ << DeclName
+ << Best->Function->getMessageUnavailableAttr(
+ !Best->Function->isDeleted())
+ << MemExprE->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
// FIXME: Leaking incoming expressions!
return ExprError();
@@ -8594,7 +8601,10 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
Diag(Object->getSourceRange().getBegin(),
diag::err_ovl_deleted_object_call)
<< Best->Function->isDeleted()
- << Object->getType() << Object->getSourceRange();
+ << Object->getType()
+ << Best->Function->getMessageUnavailableAttr(
+ !Best->Function->isDeleted())
+ << Object->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
break;
}
@@ -8626,6 +8636,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
RParenLoc);
}
+ MarkDeclarationReferenced(LParenLoc, Best->Function);
CheckMemberOperatorAccess(LParenLoc, Object, 0, Best->FoundDecl);
DiagnoseUseOfDecl(Best->FoundDecl, LParenLoc);
@@ -8799,11 +8810,15 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) {
case OR_Deleted:
Diag(OpLoc, diag::err_ovl_deleted_oper)
<< Best->Function->isDeleted()
- << "->" << Base->getSourceRange();
+ << "->"
+ << Best->Function->getMessageUnavailableAttr(
+ !Best->Function->isDeleted())
+ << Base->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, &Base, 1);
return ExprError();
}
+ MarkDeclarationReferenced(OpLoc, Best->Function);
CheckMemberOperatorAccess(OpLoc, Base, 0, Best->FoundDecl);
DiagnoseUseOfDecl(Best->FoundDecl, OpLoc);
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp
index e995e8f..89957e6 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp
@@ -25,6 +25,7 @@
#include "clang/AST/TypeLoc.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
using namespace clang;
@@ -92,6 +93,8 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
unsigned DiagID = diag::warn_unused_expr;
if (const ExprWithCleanups *Temps = dyn_cast<ExprWithCleanups>(E))
E = Temps->getSubExpr();
+ if (const CXXBindTemporaryExpr *TempExpr = dyn_cast<CXXBindTemporaryExpr>(E))
+ E = TempExpr->getSubExpr();
E = E->IgnoreParenImpCasts();
if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
@@ -143,7 +146,7 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
}
}
- DiagRuntimeBehavior(Loc, PDiag(DiagID) << R1 << R2);
+ DiagRuntimeBehavior(Loc, 0, PDiag(DiagID) << R1 << R2);
}
StmtResult
@@ -499,8 +502,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
bool HasDependentValue
= CondExpr->isTypeDependent() || CondExpr->isValueDependent();
unsigned CondWidth
- = HasDependentValue? 0
- : static_cast<unsigned>(Context.getTypeSize(CondTypeBeforePromotion));
+ = HasDependentValue ? 0 : Context.getIntWidth(CondTypeBeforePromotion);
bool CondIsSigned = CondTypeBeforePromotion->isSignedIntegerType();
// Accumulate all of the case values in a vector so that we can sort them
@@ -1392,19 +1394,29 @@ static bool CheckAsmLValue(const Expr *E, Sema &S) {
return true;
}
+/// isOperandMentioned - Return true if the specified operand # is mentioned
+/// anywhere in the decomposed asm string.
+static bool isOperandMentioned(unsigned OpNo,
+ llvm::ArrayRef<AsmStmt::AsmStringPiece> AsmStrPieces) {
+ for (unsigned p = 0, e = AsmStrPieces.size(); p != e; ++p) {
+ const AsmStmt::AsmStringPiece &Piece = AsmStrPieces[p];
+ if (!Piece.isOperand()) continue;
+
+ // If this is a reference to the input and if the input was the smaller
+ // one, then we have to reject this asm.
+ if (Piece.getOperandNo() == OpNo)
+ return true;
+ }
+
+ return false;
+}
-StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc,
- bool IsSimple,
- bool IsVolatile,
- unsigned NumOutputs,
- unsigned NumInputs,
- IdentifierInfo **Names,
- MultiExprArg constraints,
- MultiExprArg exprs,
- Expr *asmString,
- MultiExprArg clobbers,
- SourceLocation RParenLoc,
- bool MSAsm) {
+StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple,
+ bool IsVolatile, unsigned NumOutputs,
+ unsigned NumInputs, IdentifierInfo **Names,
+ MultiExprArg constraints, MultiExprArg exprs,
+ Expr *asmString, MultiExprArg clobbers,
+ SourceLocation RParenLoc, bool MSAsm) {
unsigned NumClobbers = clobbers.size();
StringLiteral **Constraints =
reinterpret_cast<StringLiteral**>(constraints.get());
@@ -1529,8 +1541,9 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc,
if (!Info.hasTiedOperand()) continue;
unsigned TiedTo = Info.getTiedOperand();
+ unsigned InputOpNo = i+NumOutputs;
Expr *OutputExpr = Exprs[TiedTo];
- Expr *InputExpr = Exprs[i+NumOutputs];
+ Expr *InputExpr = Exprs[InputOpNo];
QualType InTy = InputExpr->getType();
QualType OutTy = OutputExpr->getType();
if (Context.hasSameType(InTy, OutTy))
@@ -1569,30 +1582,22 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc,
continue;
// If the smaller input/output operand is not mentioned in the asm string,
- // then we can promote it and the asm string won't notice. Check this
- // case now.
+ // then we can promote the smaller one to a larger input and the asm string
+ // won't notice.
bool SmallerValueMentioned = false;
- for (unsigned p = 0, e = Pieces.size(); p != e; ++p) {
- AsmStmt::AsmStringPiece &Piece = Pieces[p];
- if (!Piece.isOperand()) continue;
-
- // If this is a reference to the input and if the input was the smaller
- // one, then we have to reject this asm.
- if (Piece.getOperandNo() == i+NumOutputs) {
- if (InSize < OutSize) {
- SmallerValueMentioned = true;
- break;
- }
- }
-
- // If this is a reference to the input and if the input was the smaller
- // one, then we have to reject this asm.
- if (Piece.getOperandNo() == TiedTo) {
- if (InSize > OutSize) {
- SmallerValueMentioned = true;
- break;
- }
- }
+
+ // If this is a reference to the input and if the input was the smaller
+ // one, then we have to reject this asm.
+ if (isOperandMentioned(InputOpNo, Pieces)) {
+ // This is a use in the asm string of the smaller operand. Since we
+ // codegen this by promoting to a wider value, the asm will get printed
+ // "wrong".
+ SmallerValueMentioned |= InSize < OutSize;
+ }
+ if (isOperandMentioned(TiedTo, Pieces)) {
+ // If this is a reference to the output, and if the output is the larger
+ // value, then it's ok because we'll promote the input to the larger type.
+ SmallerValueMentioned |= OutSize < InSize;
}
// If the smaller value wasn't mentioned in the asm string, and if the
@@ -1601,7 +1606,20 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc,
if (!SmallerValueMentioned && InputDomain != AD_Other &&
OutputConstraintInfos[TiedTo].allowsRegister())
continue;
-
+
+ // Either both of the operands were mentioned or the smaller one was
+ // mentioned. One more special case that we'll allow: if the tied input is
+ // integer, unmentioned, and is a constant, then we'll allow truncating it
+ // down to the size of the destination.
+ if (InputDomain == AD_Int && OutputDomain == AD_Int &&
+ !isOperandMentioned(InputOpNo, Pieces) &&
+ InputExpr->isEvaluatable(Context)) {
+ ImpCastExprToType(InputExpr, OutTy, CK_IntegralCast);
+ Exprs[InputOpNo] = InputExpr;
+ NS->setInputExpr(i, InputExpr);
+ continue;
+ }
+
Diag(InputExpr->getLocStart(),
diag::err_asm_tying_incompatible_types)
<< InTy << OutTy << OutputExpr->getSourceRange()
@@ -1747,8 +1765,10 @@ public:
StmtResult
Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
MultiStmtArg RawHandlers) {
- if (!getLangOptions().Exceptions)
- Diag(TryLoc, diag::err_exceptions_disabled) << "try";
+ // Don't report an error if 'try' is used in system headers.
+ if (!getLangOptions().Exceptions &&
+ !getSourceManager().isInSystemHeader(TryLoc))
+ Diag(TryLoc, diag::err_exceptions_disabled) << "try";
unsigned NumHandlers = RawHandlers.size();
assert(NumHandlers > 0 &&
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
index f0a0103..f02dd25 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
@@ -400,8 +400,7 @@ Sema::BuildDependentDeclRefExpr(const CXXScopeSpec &SS,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs) {
return Owned(DependentScopeDeclRefExpr::Create(Context,
- static_cast<NestedNameSpecifier*>(SS.getScopeRep()),
- SS.getRange(),
+ SS.getWithLocInContext(Context),
NameInfo,
TemplateArgs));
}
@@ -783,8 +782,7 @@ Sema::ActOnTemplateParameterList(unsigned Depth,
static void SetNestedNameSpecifier(TagDecl *T, const CXXScopeSpec &SS) {
if (SS.isSet())
- T->setQualifierInfo(static_cast<NestedNameSpecifier*>(SS.getScopeRep()),
- SS.getRange());
+ T->setQualifierInfo(SS.getWithLocInContext(T->getASTContext()));
}
DeclResult
@@ -2333,9 +2331,13 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
DeclarationNameInfo NameInfo(DTN->getIdentifier(),
Arg.getTemplateNameLoc());
+ // FIXME: TemplateArgumentLoc should store a NestedNameSpecifierLoc
+ // for the template name.
+ CXXScopeSpec SS;
+ SS.MakeTrivial(Context, DTN->getQualifier(),
+ Arg.getTemplateQualifierRange());
Expr *E = DependentScopeDeclRefExpr::Create(Context,
- DTN->getQualifier(),
- Arg.getTemplateQualifierRange(),
+ SS.getWithLocInContext(Context),
NameInfo);
// If we parsed the template argument as a pack expansion, create a
@@ -2868,6 +2870,7 @@ bool UnnamedLocalNoLinkageFinder::VisitNestedNameSpecifier(
switch (NNS->getKind()) {
case NestedNameSpecifier::Identifier:
case NestedNameSpecifier::Namespace:
+ case NestedNameSpecifier::NamespaceAlias:
case NestedNameSpecifier::Global:
return false;
@@ -3610,7 +3613,7 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
= NestedNameSpecifier::Create(Context, 0, false,
ClassType.getTypePtr());
CXXScopeSpec SS;
- SS.setScopeRep(Qualifier);
+ SS.MakeTrivial(Context, Qualifier, Loc);
// The actual value-ness of this is unimportant, but for
// internal consistency's sake, references to instance methods
@@ -5997,8 +6000,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
SourceLocation KeywordLoc, SourceRange NNSRange,
SourceLocation IILoc) {
CXXScopeSpec SS;
- SS.setScopeRep(NNS);
- SS.setRange(NNSRange);
+ SS.MakeTrivial(Context, NNS, NNSRange);
DeclContext *Ctx = computeDeclContext(SS);
if (!Ctx) {
@@ -6036,7 +6038,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
<< Name << Ctx << FullRange;
if (UnresolvedUsingValueDecl *Using
= dyn_cast<UnresolvedUsingValueDecl>(Result.getRepresentativeDecl())){
- SourceLocation Loc = Using->getTargetNestedNameRange().getBegin();
+ SourceLocation Loc = Using->getQualifierLoc().getBeginLoc();
Diag(Loc, diag::note_using_value_decl_missing_typename)
<< FixItHint::CreateInsertion(Loc, "typename ");
}
@@ -6168,16 +6170,18 @@ ExprResult Sema::RebuildExprInCurrentInstantiation(Expr *E) {
}
bool Sema::RebuildNestedNameSpecifierInCurrentInstantiation(CXXScopeSpec &SS) {
- if (SS.isInvalid()) return true;
+ if (SS.isInvalid())
+ return true;
- NestedNameSpecifier *NNS = static_cast<NestedNameSpecifier*>(SS.getScopeRep());
+ NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
CurrentInstantiationRebuilder Rebuilder(*this, SS.getRange().getBegin(),
DeclarationName());
- NestedNameSpecifier *Rebuilt =
- Rebuilder.TransformNestedNameSpecifier(NNS, SS.getRange());
- if (!Rebuilt) return true;
+ NestedNameSpecifierLoc Rebuilt
+ = Rebuilder.TransformNestedNameSpecifierLoc(QualifierLoc);
+ if (!Rebuilt)
+ return true;
- SS.setScopeRep(Rebuilt);
+ SS.Adopt(Rebuilt);
return false;
}
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
index bd0a618..139fafb 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3004,12 +3004,12 @@ Sema::DeduceAutoType(QualType Type, Expr *Init, QualType &Result) {
LocalInstantiationScope InstScope(*this);
// Build template<class TemplParam> void Func(FuncParam);
- NamedDecl *TemplParam
- = TemplateTypeParmDecl::Create(Context, 0, Loc, 0, 0, 0, false, false);
- TemplateParameterList *TemplateParams
- = TemplateParameterList::Create(Context, Loc, Loc, &TemplParam, 1, Loc);
-
QualType TemplArg = Context.getTemplateTypeParmType(0, 0, false);
+ TemplateTypeParmDecl TemplParam(0, Loc, 0, false, TemplArg, false);
+ NamedDecl *TemplParamPtr = &TemplParam;
+ FixedSizeTemplateParameterList<1> TemplateParams(Loc, Loc, &TemplParamPtr,
+ Loc);
+
QualType FuncParam =
SubstituteAutoTransform(*this, TemplArg).TransformType(Type);
@@ -3018,13 +3018,13 @@ Sema::DeduceAutoType(QualType Type, Expr *Init, QualType &Result) {
Deduced.resize(1);
QualType InitType = Init->getType();
unsigned TDF = 0;
- if (AdjustFunctionParmAndArgTypesForDeduction(*this, TemplateParams,
+ if (AdjustFunctionParmAndArgTypesForDeduction(*this, &TemplateParams,
FuncParam, InitType, Init,
TDF))
return false;
TemplateDeductionInfo Info(Context, Loc);
- if (::DeduceTemplateArguments(*this, TemplateParams,
+ if (::DeduceTemplateArguments(*this, &TemplateParams,
FuncParam, InitType, Info, Deduced,
TDF))
return false;
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 44f5913..ae0ac9c 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -2140,6 +2140,17 @@ Sema::SubstNestedNameSpecifier(NestedNameSpecifier *NNS,
return Instantiator.TransformNestedNameSpecifier(NNS, Range);
}
+NestedNameSpecifierLoc
+Sema::SubstNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
+ if (!NNS)
+ return NestedNameSpecifierLoc();
+
+ TemplateInstantiator Instantiator(*this, TemplateArgs, NNS.getBeginLoc(),
+ DeclarationName());
+ return Instantiator.TransformNestedNameSpecifierLoc(NNS);
+}
+
/// \brief Do template substitution on declaration name info.
DeclarationNameInfo
Sema::SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo,
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index c0150c0..3a40b6f 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -27,33 +27,33 @@ using namespace clang;
bool TemplateDeclInstantiator::SubstQualifier(const DeclaratorDecl *OldDecl,
DeclaratorDecl *NewDecl) {
- NestedNameSpecifier *OldQual = OldDecl->getQualifier();
- if (!OldQual) return false;
-
- SourceRange QualRange = OldDecl->getQualifierRange();
-
- NestedNameSpecifier *NewQual
- = SemaRef.SubstNestedNameSpecifier(OldQual, QualRange, TemplateArgs);
- if (!NewQual)
+ if (!OldDecl->getQualifierLoc())
+ return false;
+
+ NestedNameSpecifierLoc NewQualifierLoc
+ = SemaRef.SubstNestedNameSpecifierLoc(OldDecl->getQualifierLoc(),
+ TemplateArgs);
+
+ if (!NewQualifierLoc)
return true;
-
- NewDecl->setQualifierInfo(NewQual, QualRange);
+
+ NewDecl->setQualifierInfo(NewQualifierLoc);
return false;
}
bool TemplateDeclInstantiator::SubstQualifier(const TagDecl *OldDecl,
TagDecl *NewDecl) {
- NestedNameSpecifier *OldQual = OldDecl->getQualifier();
- if (!OldQual) return false;
-
- SourceRange QualRange = OldDecl->getQualifierRange();
-
- NestedNameSpecifier *NewQual
- = SemaRef.SubstNestedNameSpecifier(OldQual, QualRange, TemplateArgs);
- if (!NewQual)
+ if (!OldDecl->getQualifierLoc())
+ return false;
+
+ NestedNameSpecifierLoc NewQualifierLoc
+ = SemaRef.SubstNestedNameSpecifierLoc(OldDecl->getQualifierLoc(),
+ TemplateArgs);
+
+ if (!NewQualifierLoc)
return true;
-
- NewDecl->setQualifierInfo(NewQual, QualRange);
+
+ NewDecl->setQualifierInfo(NewQualifierLoc);
return false;
}
@@ -120,9 +120,8 @@ TemplateDeclInstantiator::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
= NamespaceAliasDecl::Create(SemaRef.Context, Owner,
D->getNamespaceLoc(),
D->getAliasLoc(),
- D->getNamespace()->getIdentifier(),
- D->getQualifierRange(),
- D->getQualifier(),
+ D->getIdentifier(),
+ D->getQualifierLoc(),
D->getTargetNameLoc(),
D->getNamespace());
Owner->addDecl(Inst);
@@ -642,12 +641,12 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
// Instantiate the qualifier. We have to do this first in case
// we're a friend declaration, because if we are then we need to put
// the new declaration in the appropriate context.
- NestedNameSpecifier *Qualifier = Pattern->getQualifier();
- if (Qualifier) {
- Qualifier = SemaRef.SubstNestedNameSpecifier(Qualifier,
- Pattern->getQualifierRange(),
- TemplateArgs);
- if (!Qualifier) return 0;
+ NestedNameSpecifierLoc QualifierLoc = Pattern->getQualifierLoc();
+ if (QualifierLoc) {
+ QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc,
+ TemplateArgs);
+ if (!QualifierLoc)
+ return 0;
}
CXXRecordDecl *PrevDecl = 0;
@@ -668,10 +667,9 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
// the appropriate context.
DeclContext *DC = Owner;
if (isFriend) {
- if (Qualifier) {
+ if (QualifierLoc) {
CXXScopeSpec SS;
- SS.setScopeRep(Qualifier);
- SS.setRange(Pattern->getQualifierRange());
+ SS.Adopt(QualifierLoc);
DC = SemaRef.computeDeclContext(SS);
if (!DC) return 0;
} else {
@@ -692,10 +690,10 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
PrevDecl = PrevClassTemplate->getTemplatedDecl();
}
- if (!PrevClassTemplate && Qualifier) {
+ if (!PrevClassTemplate && QualifierLoc) {
SemaRef.Diag(Pattern->getLocation(), diag::err_not_tag_in_scope)
<< D->getTemplatedDecl()->getTagKind() << Pattern->getDeclName() << DC
- << Pattern->getQualifierRange();
+ << QualifierLoc.getSourceRange();
return 0;
}
@@ -756,8 +754,8 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
Pattern->getTagKeywordLoc(), PrevDecl,
/*DelayTypeCreation=*/true);
- if (Qualifier)
- RecordInst->setQualifierInfo(Qualifier, Pattern->getQualifierRange());
+ if (QualifierLoc)
+ RecordInst->setQualifierInfo(QualifierLoc);
ClassTemplateDecl *Inst
= ClassTemplateDecl::Create(SemaRef.Context, DC, D->getLocation(),
@@ -969,12 +967,12 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
return 0;
QualType T = TInfo->getType();
- NestedNameSpecifier *Qualifier = D->getQualifier();
- if (Qualifier) {
- Qualifier = SemaRef.SubstNestedNameSpecifier(Qualifier,
- D->getQualifierRange(),
- TemplateArgs);
- if (!Qualifier) return 0;
+ NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc();
+ if (QualifierLoc) {
+ QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc,
+ TemplateArgs);
+ if (!QualifierLoc)
+ return 0;
}
// If we're instantiating a local function declaration, put the result
@@ -982,10 +980,9 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
DeclContext *DC;
if (D->getDeclContext()->isFunctionOrMethod())
DC = Owner;
- else if (isFriend && Qualifier) {
+ else if (isFriend && QualifierLoc) {
CXXScopeSpec SS;
- SS.setScopeRep(Qualifier);
- SS.setRange(D->getQualifierRange());
+ SS.Adopt(QualifierLoc);
DC = SemaRef.computeDeclContext(SS);
if (!DC) return 0;
} else {
@@ -999,8 +996,8 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
D->getStorageClass(), D->getStorageClassAsWritten(),
D->isInlineSpecified(), D->hasWrittenPrototype());
- if (Qualifier)
- Function->setQualifierInfo(Qualifier, D->getQualifierRange());
+ if (QualifierLoc)
+ Function->setQualifierInfo(QualifierLoc);
DeclContext *LexicalDC = Owner;
if (!isFriend && D->isOutOfLine()) {
@@ -1262,20 +1259,19 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
return 0;
}
- NestedNameSpecifier *Qualifier = D->getQualifier();
- if (Qualifier) {
- Qualifier = SemaRef.SubstNestedNameSpecifier(Qualifier,
- D->getQualifierRange(),
+ NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc();
+ if (QualifierLoc) {
+ QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc,
TemplateArgs);
- if (!Qualifier) return 0;
+ if (!QualifierLoc)
+ return 0;
}
DeclContext *DC = Owner;
if (isFriend) {
- if (Qualifier) {
+ if (QualifierLoc) {
CXXScopeSpec SS;
- SS.setScopeRep(Qualifier);
- SS.setRange(D->getQualifierRange());
+ SS.Adopt(QualifierLoc);
DC = SemaRef.computeDeclContext(SS);
if (DC && SemaRef.RequireCompleteDeclContext(SS, DC))
@@ -1318,8 +1314,8 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
D->isInlineSpecified());
}
- if (Qualifier)
- Method->setQualifierInfo(Qualifier, D->getQualifierRange());
+ if (QualifierLoc)
+ Method->setQualifierInfo(QualifierLoc);
if (TemplateParams) {
// Our resulting instantiation is actually a function template, since we
@@ -1641,12 +1637,13 @@ TemplateDeclInstantiator::VisitTemplateTemplateParmDecl(
}
Decl *TemplateDeclInstantiator::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
- // Using directives are never dependent, so they require no explicit
+ // Using directives are never dependent (and never contain any types or
+ // expressions), so they require no explicit instantiation work.
UsingDirectiveDecl *Inst
= UsingDirectiveDecl::Create(SemaRef.Context, Owner, D->getLocation(),
D->getNamespaceKeyLocation(),
- D->getQualifierRange(), D->getQualifier(),
+ D->getQualifierLoc(),
D->getIdentLocation(),
D->getNominatedNamespace(),
D->getCommonAncestor());
@@ -1664,12 +1661,11 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
// template struct t<int>;
// Here, in using s1::f1, s1 refers to t<T>::s1;
// we need to substitute for t<int>::s1.
- NestedNameSpecifier *NNS =
- SemaRef.SubstNestedNameSpecifier(D->getTargetNestedNameDecl(),
- D->getNestedNameRange(),
- TemplateArgs);
- if (!NNS)
- return 0;
+ NestedNameSpecifierLoc QualifierLoc
+ = SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(),
+ TemplateArgs);
+ if (!QualifierLoc)
+ return 0;
// The name info is non-dependent, so no transformation
// is required.
@@ -1684,16 +1680,13 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
Sema::ForRedeclaration);
UsingDecl *NewUD = UsingDecl::Create(SemaRef.Context, Owner,
- D->getNestedNameRange(),
D->getUsingLocation(),
- NNS,
+ QualifierLoc,
NameInfo,
D->isTypeName());
CXXScopeSpec SS;
- SS.setScopeRep(NNS);
- SS.setRange(D->getNestedNameRange());
-
+ SS.Adopt(QualifierLoc);
if (CheckRedeclaration) {
Prev.setHideTags(false);
SemaRef.LookupQualifiedName(Prev, Owner);
@@ -1752,16 +1745,14 @@ Decl *TemplateDeclInstantiator::VisitUsingShadowDecl(UsingShadowDecl *D) {
Decl * TemplateDeclInstantiator
::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
- NestedNameSpecifier *NNS =
- SemaRef.SubstNestedNameSpecifier(D->getTargetNestedNameSpecifier(),
- D->getTargetNestedNameRange(),
- TemplateArgs);
- if (!NNS)
+ NestedNameSpecifierLoc QualifierLoc
+ = SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(),
+ TemplateArgs);
+ if (!QualifierLoc)
return 0;
CXXScopeSpec SS;
- SS.setRange(D->getTargetNestedNameRange());
- SS.setScopeRep(NNS);
+ SS.Adopt(QualifierLoc);
// Since NameInfo refers to a typename, it cannot be a C++ special name.
// Hence, no tranformation is required for it.
@@ -1779,16 +1770,13 @@ Decl * TemplateDeclInstantiator
Decl * TemplateDeclInstantiator
::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
- NestedNameSpecifier *NNS =
- SemaRef.SubstNestedNameSpecifier(D->getTargetNestedNameSpecifier(),
- D->getTargetNestedNameRange(),
- TemplateArgs);
- if (!NNS)
+ NestedNameSpecifierLoc QualifierLoc
+ = SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(), TemplateArgs);
+ if (!QualifierLoc)
return 0;
-
+
CXXScopeSpec SS;
- SS.setRange(D->getTargetNestedNameRange());
- SS.setScopeRep(NNS);
+ SS.Adopt(QualifierLoc);
DeclarationNameInfo NameInfo
= SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs);
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp
index c88baa5..ba80076 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp
@@ -1395,6 +1395,56 @@ QualType Sema::GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo) {
return QT;
}
+static void DiagnoseIgnoredQualifiers(unsigned Quals,
+ SourceLocation ConstQualLoc,
+ SourceLocation VolatileQualLoc,
+ SourceLocation RestrictQualLoc,
+ Sema& S) {
+ std::string QualStr;
+ unsigned NumQuals = 0;
+ SourceLocation Loc;
+
+ FixItHint ConstFixIt;
+ FixItHint VolatileFixIt;
+ FixItHint RestrictFixIt;
+
+ // FIXME: The locations here are set kind of arbitrarily. It'd be nicer to
+ // find a range and grow it to encompass all the qualifiers, regardless of
+ // the order in which they textually appear.
+ if (Quals & Qualifiers::Const) {
+ ConstFixIt = FixItHint::CreateRemoval(ConstQualLoc);
+ Loc = ConstQualLoc;
+ ++NumQuals;
+ QualStr = "const";
+ }
+ if (Quals & Qualifiers::Volatile) {
+ VolatileFixIt = FixItHint::CreateRemoval(VolatileQualLoc);
+ if (NumQuals == 0) {
+ Loc = VolatileQualLoc;
+ QualStr = "volatile";
+ } else {
+ QualStr += " volatile";
+ }
+ ++NumQuals;
+ }
+ if (Quals & Qualifiers::Restrict) {
+ RestrictFixIt = FixItHint::CreateRemoval(RestrictQualLoc);
+ if (NumQuals == 0) {
+ Loc = RestrictQualLoc;
+ QualStr = "restrict";
+ } else {
+ QualStr += " restrict";
+ }
+ ++NumQuals;
+ }
+
+ assert(NumQuals > 0 && "No known qualifiers?");
+
+ S.Diag(Loc, diag::warn_qual_return_type)
+ << QualStr << NumQuals
+ << ConstFixIt << VolatileFixIt << RestrictFixIt;
+}
+
/// GetTypeForDeclarator - Convert the type for the specified
/// declarator to Type instances.
///
@@ -1450,8 +1500,12 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
if (D.getAttributes())
distributeTypeAttrsFromDeclarator(state, T);
+ // C++0x [dcl.spec.auto]p5: reject 'auto' if it is not in an allowed context.
+ // In C++0x, a function declarator using 'auto' must have a trailing return
+ // type (this is checked later) and we can skip this. In other languages
+ // using auto, we need to check regardless.
if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto &&
- !D.isFunctionDeclarator()) {
+ (!getLangOptions().CPlusPlus0x || !D.isFunctionDeclarator())) {
int Error = -1;
switch (D.getContext()) {
@@ -1483,7 +1537,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
break;
case Declarator::TypeNameContext:
if (!AutoAllowedInTypeName)
- Error = 8; // Generic
+ Error = 10; // Generic
break;
case Declarator::FileContext:
case Declarator::BlockContext:
@@ -1492,6 +1546,32 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
break;
}
+ if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
+ Error = 8;
+
+ // In Objective-C it is an error to use 'auto' on a function declarator.
+ if (D.isFunctionDeclarator())
+ Error = 9;
+
+ // C++0x [dcl.spec.auto]p2: 'auto' is always fine if the declarator
+ // contains a trailing return type. That is only legal at the outermost
+ // level. Check all declarator chunks (outermost first) anyway, to give
+ // better diagnostics.
+ if (getLangOptions().CPlusPlus0x && Error != -1) {
+ for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
+ unsigned chunkIndex = e - i - 1;
+ state.setCurrentChunkIndex(chunkIndex);
+ DeclaratorChunk &DeclType = D.getTypeObject(chunkIndex);
+ if (DeclType.Kind == DeclaratorChunk::Function) {
+ const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
+ if (FTI.TrailingReturnType) {
+ Error = -1;
+ break;
+ }
+ }
+ }
+ }
+
if (Error != -1) {
Diag(D.getDeclSpec().getTypeSpecTypeLoc(), diag::err_auto_not_allowed)
<< Error;
@@ -1499,7 +1579,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
D.setInvalidType(true);
}
}
-
+
if (T.isNull())
return Context.getNullTypeSourceInfo();
@@ -1600,21 +1680,6 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
// of the type, otherwise the argument list is ().
const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
- // C99 6.7.5.3p1: The return type may not be a function or array type.
- // For conversion functions, we'll diagnose this particular error later.
- if ((T->isArrayType() || T->isFunctionType()) &&
- (D.getName().getKind() != UnqualifiedId::IK_ConversionFunctionId)) {
- unsigned diagID = diag::err_func_returning_array_function;
- // Last processing chunk in block context means this function chunk
- // represents the block.
- if (chunkIndex == 0 &&
- D.getContext() == Declarator::BlockLiteralContext)
- diagID = diag::err_block_returning_array_function;
- Diag(DeclType.Loc, diagID) << T->isFunctionType() << T;
- T = Context.IntTy;
- D.setInvalidType(true);
- }
-
// Check for auto functions and trailing return type and adjust the
// return type accordingly.
if (!D.isInvalidType()) {
@@ -1627,8 +1692,13 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
T = Context.IntTy;
D.setInvalidType(true);
} else if (FTI.TrailingReturnType) {
- if (T.hasQualifiers() || !isa<AutoType>(T)) {
- // T must be exactly 'auto' at this point. See CWG issue 681.
+ // T must be exactly 'auto' at this point. See CWG issue 681.
+ if (isa<ParenType>(T)) {
+ Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
+ diag::err_trailing_return_in_parens)
+ << T << D.getDeclSpec().getSourceRange();
+ D.setInvalidType(true);
+ } else if (T.hasQualifiers() || !isa<AutoType>(T)) {
Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
diag::err_trailing_return_without_auto)
<< T << D.getDeclSpec().getSourceRange();
@@ -1641,48 +1711,48 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
}
}
+ // C99 6.7.5.3p1: The return type may not be a function or array type.
+ // For conversion functions, we'll diagnose this particular error later.
+ if ((T->isArrayType() || T->isFunctionType()) &&
+ (D.getName().getKind() != UnqualifiedId::IK_ConversionFunctionId)) {
+ unsigned diagID = diag::err_func_returning_array_function;
+ // Last processing chunk in block context means this function chunk
+ // represents the block.
+ if (chunkIndex == 0 &&
+ D.getContext() == Declarator::BlockLiteralContext)
+ diagID = diag::err_block_returning_array_function;
+ Diag(DeclType.Loc, diagID) << T->isFunctionType() << T;
+ T = Context.IntTy;
+ D.setInvalidType(true);
+ }
+
// cv-qualifiers on return types are pointless except when the type is a
// class type in C++.
- if (T.getCVRQualifiers() && D.getDeclSpec().getTypeQualifiers() &&
+ if (T->isPointerType() && T.getCVRQualifiers() &&
+ (!getLangOptions().CPlusPlus || !T->isDependentType())) {
+ assert(chunkIndex + 1 < e && "No DeclaratorChunk for the return type?");
+ DeclaratorChunk ReturnTypeChunk = D.getTypeObject(chunkIndex + 1);
+ assert(ReturnTypeChunk.Kind == DeclaratorChunk::Pointer);
+
+ DeclaratorChunk::PointerTypeInfo &PTI = ReturnTypeChunk.Ptr;
+
+ DiagnoseIgnoredQualifiers(PTI.TypeQuals,
+ SourceLocation::getFromRawEncoding(PTI.ConstQualLoc),
+ SourceLocation::getFromRawEncoding(PTI.VolatileQualLoc),
+ SourceLocation::getFromRawEncoding(PTI.RestrictQualLoc),
+ *this);
+
+ } else if (T.getCVRQualifiers() && D.getDeclSpec().getTypeQualifiers() &&
(!getLangOptions().CPlusPlus ||
(!T->isDependentType() && !T->isRecordType()))) {
- unsigned Quals = D.getDeclSpec().getTypeQualifiers();
- std::string QualStr;
- unsigned NumQuals = 0;
- SourceLocation Loc;
- if (Quals & Qualifiers::Const) {
- Loc = D.getDeclSpec().getConstSpecLoc();
- ++NumQuals;
- QualStr = "const";
- }
- if (Quals & Qualifiers::Volatile) {
- if (NumQuals == 0) {
- Loc = D.getDeclSpec().getVolatileSpecLoc();
- QualStr = "volatile";
- } else
- QualStr += " volatile";
- ++NumQuals;
- }
- if (Quals & Qualifiers::Restrict) {
- if (NumQuals == 0) {
- Loc = D.getDeclSpec().getRestrictSpecLoc();
- QualStr = "restrict";
- } else
- QualStr += " restrict";
- ++NumQuals;
- }
- assert(NumQuals > 0 && "No known qualifiers?");
-
- SemaDiagnosticBuilder DB = Diag(Loc, diag::warn_qual_return_type);
- DB << QualStr << NumQuals;
- if (Quals & Qualifiers::Const)
- DB << FixItHint::CreateRemoval(D.getDeclSpec().getConstSpecLoc());
- if (Quals & Qualifiers::Volatile)
- DB << FixItHint::CreateRemoval(D.getDeclSpec().getVolatileSpecLoc());
- if (Quals & Qualifiers::Restrict)
- DB << FixItHint::CreateRemoval(D.getDeclSpec().getRestrictSpecLoc());
+
+ DiagnoseIgnoredQualifiers(D.getDeclSpec().getTypeQualifiers(),
+ D.getDeclSpec().getConstSpecLoc(),
+ D.getDeclSpec().getVolatileSpecLoc(),
+ D.getDeclSpec().getRestrictSpecLoc(),
+ *this);
}
-
+
if (getLangOptions().CPlusPlus && D.getDeclSpec().isTypeSpecOwned()) {
// C++ [dcl.fct]p6:
// Types shall not be defined in return or parameter types.
@@ -1825,6 +1895,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
break;
case NestedNameSpecifier::Namespace:
+ case NestedNameSpecifier::NamespaceAlias:
case NestedNameSpecifier::Global:
llvm_unreachable("Nested-name-specifier must name a type");
break;
@@ -2047,7 +2118,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
break;
}
}
-
+
if (T.isNull())
return Context.getNullTypeSourceInfo();
else if (D.isInvalidType())
diff --git a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h
index 944e6a1..57a44ad 100644
--- a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h
+++ b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h
@@ -385,6 +385,17 @@ public:
QualType ObjectType = QualType(),
NamedDecl *FirstQualifierInScope = 0);
+ /// \brief Transform the given nested-name-specifier with source-location
+ /// information.
+ ///
+ /// By default, transforms all of the types and declarations within the
+ /// nested-name-specifier. Subclasses may override this function to provide
+ /// alternate behavior.
+ NestedNameSpecifierLoc TransformNestedNameSpecifierLoc(
+ NestedNameSpecifierLoc NNS,
+ QualType ObjectType = QualType(),
+ NamedDecl *FirstQualifierInScope = 0);
+
/// \brief Transform the given declaration name.
///
/// By default, transforms the types of conversion function, constructor,
@@ -759,8 +770,7 @@ public:
SourceRange NNSRange,
SourceLocation IdLoc) {
CXXScopeSpec SS;
- SS.setScopeRep(NNS);
- SS.setRange(NNSRange);
+ SS.MakeTrivial(SemaRef.Context, NNS, NNSRange);
if (NNS->isDependent()) {
// If the name is still dependent, just build a new dependent name type.
@@ -878,6 +888,16 @@ public:
NamespaceDecl *NS);
/// \brief Build a new nested-name-specifier given the prefix and the
+ /// namespace alias named in the next step in the nested-name-specifier.
+ ///
+ /// By default, performs semantic analysis when building the new
+ /// nested-name-specifier. Subclasses may override this routine to provide
+ /// different behavior.
+ NestedNameSpecifier *RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
+ SourceRange Range,
+ NamespaceAliasDecl *Alias);
+
+ /// \brief Build a new nested-name-specifier given the prefix and the
/// type named in the next step in the nested-name-specifier.
///
/// By default, performs semantic analysis when building the new
@@ -1083,11 +1103,8 @@ public:
StmtResult RebuildDeclStmt(Decl **Decls, unsigned NumDecls,
SourceLocation StartLoc,
SourceLocation EndLoc) {
- return getSema().Owned(
- new (getSema().Context) DeclStmt(
- DeclGroupRef::Create(getSema().Context,
- Decls, NumDecls),
- StartLoc, EndLoc));
+ Sema::DeclGroupPtrTy DG = getSema().BuildDeclaratorGroup(Decls, NumDecls);
+ return getSema().ActOnDeclStmt(DG, StartLoc, EndLoc);
}
/// \brief Build a new inline asm statement.
@@ -1246,8 +1263,7 @@ public:
const DeclarationNameInfo &NameInfo,
TemplateArgumentListInfo *TemplateArgs) {
CXXScopeSpec SS;
- SS.setScopeRep(Qualifier);
- SS.setRange(QualifierRange);
+ SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange);
// FIXME: loses template args.
@@ -1268,13 +1284,12 @@ public:
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
ExprResult RebuildCXXPseudoDestructorExpr(Expr *Base,
- SourceLocation OperatorLoc,
- bool isArrow,
- NestedNameSpecifier *Qualifier,
- SourceRange QualifierRange,
- TypeSourceInfo *ScopeType,
- SourceLocation CCLoc,
- SourceLocation TildeLoc,
+ SourceLocation OperatorLoc,
+ bool isArrow,
+ CXXScopeSpec &SS,
+ TypeSourceInfo *ScopeType,
+ SourceLocation CCLoc,
+ SourceLocation TildeLoc,
PseudoDestructorTypeStorage Destroyed);
/// \brief Build a new unary operator expression.
@@ -1386,8 +1401,7 @@ public:
CXXScopeSpec SS;
if (Qualifier) {
- SS.setRange(QualifierRange);
- SS.setScopeRep(Qualifier);
+ SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange);
}
getSema().DefaultFunctionArrayConversion(Base);
@@ -1873,13 +1887,12 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- ExprResult RebuildDependentScopeDeclRefExpr(NestedNameSpecifier *NNS,
- SourceRange QualifierRange,
+ ExprResult RebuildDependentScopeDeclRefExpr(
+ NestedNameSpecifierLoc QualifierLoc,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs) {
CXXScopeSpec SS;
- SS.setRange(QualifierRange);
- SS.setScopeRep(NNS);
+ SS.Adopt(QualifierLoc);
if (TemplateArgs)
return getSema().BuildQualifiedTemplateIdExpr(SS, NameInfo,
@@ -1964,8 +1977,7 @@ public:
const DeclarationNameInfo &MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs) {
CXXScopeSpec SS;
- SS.setRange(QualifierRange);
- SS.setScopeRep(Qualifier);
+ SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange);
return SemaRef.BuildMemberReferenceExpr(BaseE, BaseType,
OperatorLoc, IsArrow,
@@ -1988,8 +2000,7 @@ public:
LookupResult &R,
const TemplateArgumentListInfo *TemplateArgs) {
CXXScopeSpec SS;
- SS.setRange(QualifierRange);
- SS.setScopeRep(Qualifier);
+ SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange);
return SemaRef.BuildMemberReferenceExpr(BaseE, BaseType,
OperatorLoc, IsArrow,
@@ -2263,6 +2274,11 @@ private:
QualType ObjectType,
NamedDecl *FirstQualifierInScope,
NestedNameSpecifier *Prefix);
+
+ TypeLoc TransformTypeInObjectScope(TypeLoc TL,
+ QualType ObjectType,
+ NamedDecl *FirstQualifierInScope,
+ CXXScopeSpec &SS);
};
template<typename Derived>
@@ -2459,6 +2475,19 @@ TreeTransform<Derived>::TransformNestedNameSpecifier(NestedNameSpecifier *NNS,
return getDerived().RebuildNestedNameSpecifier(Prefix, Range, NS);
}
+ case NestedNameSpecifier::NamespaceAlias: {
+ NamespaceAliasDecl *Alias
+ = cast_or_null<NamespaceAliasDecl>(
+ getDerived().TransformDecl(Range.getBegin(),
+ NNS->getAsNamespaceAlias()));
+ if (!getDerived().AlwaysRebuild() &&
+ Prefix == NNS->getPrefix() &&
+ Alias == NNS->getAsNamespaceAlias())
+ return NNS;
+
+ return getDerived().RebuildNestedNameSpecifier(Prefix, Range, Alias);
+ }
+
case NestedNameSpecifier::Global:
// There is no meaningful transformation that one could perform on the
// global scope.
@@ -2490,6 +2519,103 @@ TreeTransform<Derived>::TransformNestedNameSpecifier(NestedNameSpecifier *NNS,
}
template<typename Derived>
+NestedNameSpecifierLoc
+TreeTransform<Derived>::TransformNestedNameSpecifierLoc(
+ NestedNameSpecifierLoc NNS,
+ QualType ObjectType,
+ NamedDecl *FirstQualifierInScope) {
+ llvm::SmallVector<NestedNameSpecifierLoc, 4> Qualifiers;
+ for (NestedNameSpecifierLoc Qualifier = NNS; Qualifier;
+ Qualifier = Qualifier.getPrefix())
+ Qualifiers.push_back(Qualifier);
+
+ CXXScopeSpec SS;
+ while (!Qualifiers.empty()) {
+ NestedNameSpecifierLoc Q = Qualifiers.pop_back_val();
+ NestedNameSpecifier *QNNS = Q.getNestedNameSpecifier();
+
+ switch (QNNS->getKind()) {
+ case NestedNameSpecifier::Identifier:
+ if (SemaRef.BuildCXXNestedNameSpecifier(/*Scope=*/0,
+ *QNNS->getAsIdentifier(),
+ Q.getLocalBeginLoc(),
+ Q.getLocalEndLoc(),
+ ObjectType, false, SS,
+ FirstQualifierInScope, false))
+ return NestedNameSpecifierLoc();
+
+ break;
+
+ case NestedNameSpecifier::Namespace: {
+ NamespaceDecl *NS
+ = cast_or_null<NamespaceDecl>(
+ getDerived().TransformDecl(
+ Q.getLocalBeginLoc(),
+ QNNS->getAsNamespace()));
+ SS.Extend(SemaRef.Context, NS, Q.getLocalBeginLoc(), Q.getLocalEndLoc());
+ break;
+ }
+
+ case NestedNameSpecifier::NamespaceAlias: {
+ NamespaceAliasDecl *Alias
+ = cast_or_null<NamespaceAliasDecl>(
+ getDerived().TransformDecl(Q.getLocalBeginLoc(),
+ QNNS->getAsNamespaceAlias()));
+ SS.Extend(SemaRef.Context, Alias, Q.getLocalBeginLoc(),
+ Q.getLocalEndLoc());
+ break;
+ }
+
+ case NestedNameSpecifier::Global:
+ // There is no meaningful transformation that one could perform on the
+ // global scope.
+ SS.MakeGlobal(SemaRef.Context, Q.getBeginLoc());
+ break;
+
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ case NestedNameSpecifier::TypeSpec: {
+ TypeLoc TL = TransformTypeInObjectScope(Q.getTypeLoc(), ObjectType,
+ FirstQualifierInScope, SS);
+
+ if (!TL)
+ return NestedNameSpecifierLoc();
+
+ if (TL.getType()->isDependentType() || TL.getType()->isRecordType() ||
+ (SemaRef.getLangOptions().CPlusPlus0x &&
+ TL.getType()->isEnumeralType())) {
+ assert(!TL.getType().hasLocalQualifiers() &&
+ "Can't get cv-qualifiers here");
+ SS.Extend(SemaRef.Context, /*FIXME:*/SourceLocation(), TL,
+ Q.getLocalEndLoc());
+ break;
+ }
+
+ SemaRef.Diag(TL.getBeginLoc(), diag::err_nested_name_spec_non_tag)
+ << TL.getType() << SS.getRange();
+ return NestedNameSpecifierLoc();
+ }
+ }
+
+ // The qualifier-in-scope only applies to the leftmost entity.
+ FirstQualifierInScope = 0;
+ }
+
+ // Don't rebuild the nested-name-specifier if we don't have to.
+ if (SS.getScopeRep() == NNS.getNestedNameSpecifier() &&
+ !getDerived().AlwaysRebuild())
+ return NNS;
+
+ // If we can re-use the source-location data from the original
+ // nested-name-specifier, do so.
+ if (SS.location_size() == NNS.getDataLength() &&
+ memcmp(SS.location_data(), NNS.getOpaqueData(), SS.location_size()) == 0)
+ return NestedNameSpecifierLoc(SS.getScopeRep(), NNS.getOpaqueData());
+
+ // Allocate new nested-name-specifier location information.
+ return SS.getWithLocInContext(SemaRef.Context);
+}
+
+template<typename Derived>
DeclarationNameInfo
TreeTransform<Derived>
::TransformDeclarationNameInfo(const DeclarationNameInfo &NameInfo) {
@@ -3085,7 +3211,7 @@ TreeTransform<Derived>::TransformTypeInObjectScope(TypeSourceInfo *TSI,
QualType ObjectType,
NamedDecl *UnqualLookup,
NestedNameSpecifier *Prefix) {
- // TODO: in some cases, we might be some verification to do here.
+ // TODO: in some cases, we might have some verification to do here.
if (ObjectType.isNull())
return getDerived().TransformType(TSI);
@@ -3122,6 +3248,62 @@ TreeTransform<Derived>::TransformTypeInObjectScope(TypeSourceInfo *TSI,
return TLB.getTypeSourceInfo(SemaRef.Context, Result);
}
+template<typename Derived>
+TypeLoc
+TreeTransform<Derived>::TransformTypeInObjectScope(TypeLoc TL,
+ QualType ObjectType,
+ NamedDecl *UnqualLookup,
+ CXXScopeSpec &SS) {
+ // FIXME: Painfully copy-paste from the above!
+
+ // TODO: in some cases, we might have some verification to do here.
+ if (ObjectType.isNull()) {
+ TypeLocBuilder TLB;
+ TLB.reserve(TL.getFullDataSize());
+ QualType Result = getDerived().TransformType(TLB, TL);
+ if (Result.isNull())
+ return TypeLoc();
+
+ return TLB.getTypeSourceInfo(SemaRef.Context, Result)->getTypeLoc();
+ }
+
+ QualType T = TL.getType();
+ if (getDerived().AlreadyTransformed(T))
+ return TL;
+
+ TypeLocBuilder TLB;
+ QualType Result;
+
+ if (isa<TemplateSpecializationType>(T)) {
+ TemplateSpecializationTypeLoc SpecTL
+ = cast<TemplateSpecializationTypeLoc>(TL);
+
+ TemplateName Template =
+ getDerived().TransformTemplateName(SpecTL.getTypePtr()->getTemplateName(),
+ ObjectType, UnqualLookup);
+ if (Template.isNull())
+ return TypeLoc();
+
+ Result = getDerived().TransformTemplateSpecializationType(TLB, SpecTL,
+ Template);
+ } else if (isa<DependentTemplateSpecializationType>(T)) {
+ DependentTemplateSpecializationTypeLoc SpecTL
+ = cast<DependentTemplateSpecializationTypeLoc>(TL);
+
+ Result = getDerived().TransformDependentTemplateSpecializationType(TLB,
+ SpecTL,
+ SS.getScopeRep());
+ } else {
+ // Nothing special needs to be done for these.
+ Result = getDerived().TransformType(TLB, TL);
+ }
+
+ if (Result.isNull())
+ return TypeLoc();
+
+ return TLB.getTypeSourceInfo(SemaRef.Context, Result)->getTypeLoc();
+}
+
template <class TyLoc> static inline
QualType TransformTypeSpecType(TypeLocBuilder &TLB, TyLoc T) {
TyLoc NewT = TLB.push<TyLoc>(T.getType());
@@ -4337,7 +4519,8 @@ QualType TreeTransform<Derived>::
TemplateArgumentListInfo NewTemplateArgs;
NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc());
NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc());
-
+
+ // FIXME: Nested-name-specifier source location info!
typedef TemplateArgumentLocContainerIterator<
DependentTemplateSpecializationTypeLoc> ArgIterator;
if (getDerived().TransformTemplateArguments(ArgIterator(TL, 0),
@@ -6426,21 +6609,22 @@ TreeTransform<Derived>::TransformCXXPseudoDestructorExpr(
return ExprError();
QualType ObjectType = ObjectTypePtr.get();
- NestedNameSpecifier *Qualifier = E->getQualifier();
- if (Qualifier) {
- Qualifier
- = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
- E->getQualifierRange(),
- ObjectType);
- if (!Qualifier)
+ NestedNameSpecifierLoc QualifierLoc = E->getQualifierLoc();
+ if (QualifierLoc) {
+ QualifierLoc
+ = getDerived().TransformNestedNameSpecifierLoc(QualifierLoc, ObjectType);
+ if (!QualifierLoc)
return ExprError();
}
+ CXXScopeSpec SS;
+ SS.Adopt(QualifierLoc);
PseudoDestructorTypeStorage Destroyed;
if (E->getDestroyedTypeInfo()) {
TypeSourceInfo *DestroyedTypeInfo
= getDerived().TransformTypeInObjectScope(E->getDestroyedTypeInfo(),
- ObjectType, 0, Qualifier);
+ ObjectType, 0,
+ QualifierLoc.getNestedNameSpecifier());
if (!DestroyedTypeInfo)
return ExprError();
Destroyed = DestroyedTypeInfo;
@@ -6451,12 +6635,6 @@ TreeTransform<Derived>::TransformCXXPseudoDestructorExpr(
E->getDestroyedTypeLoc());
} else {
// Look for a destructor known with the given name.
- CXXScopeSpec SS;
- if (Qualifier) {
- SS.setScopeRep(Qualifier);
- SS.setRange(E->getQualifierRange());
- }
-
ParsedType T = SemaRef.getDestructorName(E->getTildeLoc(),
*E->getDestroyedTypeIdentifier(),
E->getDestroyedTypeLoc(),
@@ -6481,8 +6659,7 @@ TreeTransform<Derived>::TransformCXXPseudoDestructorExpr(
return getDerived().RebuildCXXPseudoDestructorExpr(Base.get(),
E->getOperatorLoc(),
E->isArrow(),
- Qualifier,
- E->getQualifierRange(),
+ SS,
ScopeTypeInfo,
E->getColonColonLoc(),
E->getTildeLoc(),
@@ -6538,8 +6715,7 @@ TreeTransform<Derived>::TransformUnresolvedLookupExpr(
if (!Qualifier)
return ExprError();
- SS.setScopeRep(Qualifier);
- SS.setRange(Old->getQualifierRange());
+ SS.MakeTrivial(SemaRef.Context, Qualifier, Old->getQualifierRange());
}
if (Old->getNamingClass()) {
@@ -6611,10 +6787,9 @@ template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformDependentScopeDeclRefExpr(
DependentScopeDeclRefExpr *E) {
- NestedNameSpecifier *NNS
- = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
- E->getQualifierRange());
- if (!NNS)
+ NestedNameSpecifierLoc QualifierLoc
+ = getDerived().TransformNestedNameSpecifierLoc(E->getQualifierLoc());
+ if (!QualifierLoc)
return ExprError();
// TODO: If this is a conversion-function-id, verify that the
@@ -6628,14 +6803,13 @@ TreeTransform<Derived>::TransformDependentScopeDeclRefExpr(
if (!E->hasExplicitTemplateArgs()) {
if (!getDerived().AlwaysRebuild() &&
- NNS == E->getQualifier() &&
+ QualifierLoc == E->getQualifierLoc() &&
// Note: it is sufficient to compare the Name component of NameInfo:
// if name has not changed, DNLoc has not changed either.
NameInfo.getName() == E->getDeclName())
return SemaRef.Owned(E);
- return getDerived().RebuildDependentScopeDeclRefExpr(NNS,
- E->getQualifierRange(),
+ return getDerived().RebuildDependentScopeDeclRefExpr(QualifierLoc,
NameInfo,
/*TemplateArgs*/ 0);
}
@@ -6646,8 +6820,7 @@ TreeTransform<Derived>::TransformDependentScopeDeclRefExpr(
TransArgs))
return ExprError();
- return getDerived().RebuildDependentScopeDeclRefExpr(NNS,
- E->getQualifierRange(),
+ return getDerived().RebuildDependentScopeDeclRefExpr(QualifierLoc,
NameInfo,
&TransArgs);
}
@@ -7560,14 +7733,15 @@ TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
NamedDecl *FirstQualifierInScope) {
CXXScopeSpec SS;
// FIXME: The source location information is all wrong.
- SS.setRange(Range);
- SS.setScopeRep(Prefix);
- return static_cast<NestedNameSpecifier *>(
- SemaRef.BuildCXXNestedNameSpecifier(0, SS, Range.getEnd(),
- Range.getEnd(), II,
- ObjectType,
- FirstQualifierInScope,
- false, false));
+ SS.MakeTrivial(SemaRef.Context, Prefix, Range);
+ if (SemaRef.BuildCXXNestedNameSpecifier(0, II, /*FIXME:*/Range.getBegin(),
+ /*FIXME:*/Range.getEnd(),
+ ObjectType, false,
+ SS, FirstQualifierInScope,
+ false))
+ return 0;
+
+ return SS.getScopeRep();
}
template<typename Derived>
@@ -7582,6 +7756,14 @@ template<typename Derived>
NestedNameSpecifier *
TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
SourceRange Range,
+ NamespaceAliasDecl *Alias) {
+ return NestedNameSpecifier::Create(SemaRef.Context, Prefix, Alias);
+}
+
+template<typename Derived>
+NestedNameSpecifier *
+TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
+ SourceRange Range,
bool TemplateKW,
QualType T) {
if (T->isDependentType() || T->isRecordType() ||
@@ -7612,8 +7794,7 @@ TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
QualType ObjectType,
NamedDecl *FirstQualifierInScope) {
CXXScopeSpec SS;
- SS.setRange(QualifierRange);
- SS.setScopeRep(Qualifier);
+ SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange);
UnqualifiedId Name;
Name.setIdentifier(&II, /*FIXME:*/getDerived().getBaseLocation());
Sema::TemplateTy Template;
@@ -7633,8 +7814,7 @@ TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
OverloadedOperatorKind Operator,
QualType ObjectType) {
CXXScopeSpec SS;
- SS.setRange(SourceRange(getDerived().getBaseLocation()));
- SS.setScopeRep(Qualifier);
+ SS.MakeTrivial(SemaRef.Context, Qualifier, SourceRange(getDerived().getBaseLocation()));
UnqualifiedId Name;
SourceLocation SymbolLocations[3]; // FIXME: Bogus location information.
Name.setOperatorFunctionId(/*FIXME:*/getDerived().getBaseLocation(),
@@ -7740,18 +7920,11 @@ ExprResult
TreeTransform<Derived>::RebuildCXXPseudoDestructorExpr(Expr *Base,
SourceLocation OperatorLoc,
bool isArrow,
- NestedNameSpecifier *Qualifier,
- SourceRange QualifierRange,
+ CXXScopeSpec &SS,
TypeSourceInfo *ScopeType,
SourceLocation CCLoc,
SourceLocation TildeLoc,
PseudoDestructorTypeStorage Destroyed) {
- CXXScopeSpec SS;
- if (Qualifier) {
- SS.setRange(QualifierRange);
- SS.setScopeRep(Qualifier);
- }
-
QualType BaseType = Base->getType();
if (Base->isTypeDependent() || Destroyed.getIdentifier() ||
(!isArrow && !BaseType->getAs<RecordType>()) ||
diff --git a/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h b/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h
index 3d20a52..1e0a7c4 100644
--- a/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h
+++ b/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h
@@ -107,6 +107,19 @@ class TypeLocBuilder {
return DI;
}
+ /// \brief Copies the type-location information to the given AST context and
+ /// returns a \c TypeLoc referring into the AST context.
+ TypeLoc getTypeLocInContext(ASTContext &Context, QualType T) {
+#ifndef NDEBUG
+ assert(T == LastTy && "type doesn't match last type pushed!");
+#endif
+
+ size_t FullDataSize = Capacity - Index;
+ void *Mem = Context.Allocate(FullDataSize);
+ memcpy(Mem, &Buffer[Index], FullDataSize);
+ return TypeLoc(T, Mem);
+ }
+
private:
TypeLoc pushImpl(QualType T, size_t LocalSize) {
#ifndef NDEBUG
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp
index ce87b11..c3953ba 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp
@@ -97,8 +97,9 @@ PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) {
diag::warn_pch_lax_vector_conversions);
PARSE_LANGOPT_IMPORTANT(AltiVec, diag::warn_pch_altivec);
PARSE_LANGOPT_IMPORTANT(Exceptions, diag::warn_pch_exceptions);
- PARSE_LANGOPT_IMPORTANT(SjLjExceptions, diag::warn_pch_sjlj_exceptions);
PARSE_LANGOPT_IMPORTANT(ObjCExceptions, diag::warn_pch_objc_exceptions);
+ PARSE_LANGOPT_IMPORTANT(CXXExceptions, diag::warn_pch_cxx_exceptions);
+ PARSE_LANGOPT_IMPORTANT(SjLjExceptions, diag::warn_pch_sjlj_exceptions);
PARSE_LANGOPT_IMPORTANT(MSBitfields, diag::warn_pch_ms_bitfields);
PARSE_LANGOPT_IMPORTANT(NeXTRuntime, diag::warn_pch_objc_runtime);
PARSE_LANGOPT_IMPORTANT(Freestanding, diag::warn_pch_freestanding);
@@ -243,14 +244,15 @@ FindMacro(const PCHPredefinesBlocks &Buffers, llvm::StringRef MacroDef) {
bool PCHValidator::ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers,
llvm::StringRef OriginalFileName,
- std::string &SuggestedPredefines) {
+ std::string &SuggestedPredefines,
+ FileManager &FileMgr) {
// We are in the context of an implicit include, so the predefines buffer will
// have a #include entry for the PCH file itself (as normalized by the
// preprocessor initialization). Find it and skip over it in the checking
// below.
llvm::SmallString<256> PCHInclude;
PCHInclude += "#include \"";
- PCHInclude += NormalizeDashIncludePath(OriginalFileName);
+ PCHInclude += NormalizeDashIncludePath(OriginalFileName, FileMgr);
PCHInclude += "\"\n";
std::pair<llvm::StringRef,llvm::StringRef> Split =
llvm::StringRef(PP.getPredefines()).split(PCHInclude.str());
@@ -960,7 +962,8 @@ bool ASTReader::CheckPredefinesBuffers() {
if (Listener)
return Listener->ReadPredefinesBuffer(PCHPredefinesBuffers,
ActualOriginalFileName,
- SuggestedPredefines);
+ SuggestedPredefines,
+ FileMgr);
return false;
}
@@ -2799,8 +2802,9 @@ bool ASTReader::ParseLanguageOptions(
PARSE_LANGOPT(LaxVectorConversions);
PARSE_LANGOPT(AltiVec);
PARSE_LANGOPT(Exceptions);
- PARSE_LANGOPT(SjLjExceptions);
PARSE_LANGOPT(ObjCExceptions);
+ PARSE_LANGOPT(CXXExceptions);
+ PARSE_LANGOPT(SjLjExceptions);
PARSE_LANGOPT(MSBitfields);
PARSE_LANGOPT(NeXTRuntime);
PARSE_LANGOPT(Freestanding);
@@ -4476,8 +4480,7 @@ void ASTReader::ReadDeclarationNameInfo(PerFileData &F,
void ASTReader::ReadQualifierInfo(PerFileData &F, QualifierInfo &Info,
const RecordData &Record, unsigned &Idx) {
- Info.NNS = ReadNestedNameSpecifier(Record, Idx);
- Info.NNSRange = ReadSourceRange(F, Record, Idx);
+ Info.QualifierLoc = ReadNestedNameSpecifierLoc(F, Record, Idx);
unsigned NumTPLists = Record[Idx++];
Info.NumTemplParamLists = NumTPLists;
if (NumTPLists) {
@@ -4726,6 +4729,13 @@ ASTReader::ReadNestedNameSpecifier(const RecordData &Record, unsigned &Idx) {
break;
}
+ case NestedNameSpecifier::NamespaceAlias: {
+ NamespaceAliasDecl *Alias
+ = cast<NamespaceAliasDecl>(GetDecl(Record[Idx++]));
+ NNS = NestedNameSpecifier::Create(*Context, Prev, Alias);
+ break;
+ }
+
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate: {
const Type *T = GetType(Record[Idx++]).getTypePtrOrNull();
@@ -4748,6 +4758,109 @@ ASTReader::ReadNestedNameSpecifier(const RecordData &Record, unsigned &Idx) {
return NNS;
}
+NestedNameSpecifierLoc
+ASTReader::ReadNestedNameSpecifierLoc(PerFileData &F, const RecordData &Record,
+ unsigned &Idx) {
+ unsigned N = Record[Idx++];
+ NestedNameSpecifier *NNS = 0, *Prev = 0;
+ llvm::SmallVector<char, 32> LocationData;
+ for (unsigned I = 0; I != N; ++I) {
+ NestedNameSpecifier::SpecifierKind Kind
+ = (NestedNameSpecifier::SpecifierKind)Record[Idx++];
+ switch (Kind) {
+ case NestedNameSpecifier::Identifier: {
+ // Nested-name-specifier
+ IdentifierInfo *II = GetIdentifierInfo(Record, Idx);
+ NNS = NestedNameSpecifier::Create(*Context, Prev, II);
+
+ // Location information
+ SourceRange Range = ReadSourceRange(F, Record, Idx);
+ unsigned RawStart = Range.getBegin().getRawEncoding();
+ unsigned RawEnd = Range.getEnd().getRawEncoding();
+ LocationData.append(reinterpret_cast<char*>(&RawStart),
+ reinterpret_cast<char*>(&RawStart) +sizeof(unsigned));
+ LocationData.append(reinterpret_cast<char*>(&RawEnd),
+ reinterpret_cast<char*>(&RawEnd) + sizeof(unsigned));
+ break;
+ }
+
+ case NestedNameSpecifier::Namespace: {
+ // Nested-name-specifier
+ NamespaceDecl *NS = cast<NamespaceDecl>(GetDecl(Record[Idx++]));
+ NNS = NestedNameSpecifier::Create(*Context, Prev, NS);
+
+ // Location information
+ SourceRange Range = ReadSourceRange(F, Record, Idx);
+ unsigned RawStart = Range.getBegin().getRawEncoding();
+ unsigned RawEnd = Range.getEnd().getRawEncoding();
+ LocationData.append(reinterpret_cast<char*>(&RawStart),
+ reinterpret_cast<char*>(&RawStart) +sizeof(unsigned));
+ LocationData.append(reinterpret_cast<char*>(&RawEnd),
+ reinterpret_cast<char*>(&RawEnd) + sizeof(unsigned));
+ break;
+ }
+
+ case NestedNameSpecifier::NamespaceAlias: {
+ // Nested-name-specifier
+ NamespaceAliasDecl *Alias
+ = cast<NamespaceAliasDecl>(GetDecl(Record[Idx++]));
+ NNS = NestedNameSpecifier::Create(*Context, Prev, Alias);
+
+ // Location information
+ SourceRange Range = ReadSourceRange(F, Record, Idx);
+ unsigned RawStart = Range.getBegin().getRawEncoding();
+ unsigned RawEnd = Range.getEnd().getRawEncoding();
+ LocationData.append(reinterpret_cast<char*>(&RawStart),
+ reinterpret_cast<char*>(&RawStart) +sizeof(unsigned));
+ LocationData.append(reinterpret_cast<char*>(&RawEnd),
+ reinterpret_cast<char*>(&RawEnd) + sizeof(unsigned));
+
+ break;
+ }
+
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate: {
+ // Nested-name-specifier
+ bool Template = Record[Idx++];
+ TypeSourceInfo *T = GetTypeSourceInfo(F, Record, Idx);
+ if (!T)
+ return NestedNameSpecifierLoc();
+ NNS = NestedNameSpecifier::Create(*Context, Prev, Template,
+ T->getType().getTypePtr());
+
+ // Location information.
+ SourceLocation ColonColonLoc = ReadSourceLocation(F, Record, Idx);
+ unsigned RawLocation = ColonColonLoc.getRawEncoding();
+ void *OpaqueTypeData = T->getTypeLoc().getOpaqueData();
+ LocationData.append(reinterpret_cast<char*>(&OpaqueTypeData),
+ (reinterpret_cast<char*>(&OpaqueTypeData)
+ + sizeof(void *)));
+ LocationData.append(reinterpret_cast<char*>(&RawLocation),
+ (reinterpret_cast<char*>(&RawLocation) +
+ sizeof(unsigned)));
+ break;
+ }
+
+ case NestedNameSpecifier::Global: {
+ // Nested-name-specifier
+ NNS = NestedNameSpecifier::GlobalSpecifier(*Context);
+
+ SourceLocation ColonColonLoc = ReadSourceLocation(F, Record, Idx);
+ unsigned RawLocation = ColonColonLoc.getRawEncoding();
+ LocationData.append(reinterpret_cast<char*>(&RawLocation),
+ (reinterpret_cast<char*>(&RawLocation) +
+ sizeof(unsigned)));
+ break;
+ }
+ }
+ Prev = NNS;
+ }
+
+ void *Mem = Context->Allocate(LocationData.size(), llvm::alignOf<void*>());
+ memcpy(Mem, LocationData.data(), LocationData.size());
+ return NestedNameSpecifierLoc(NNS, Mem);
+}
+
SourceRange
ASTReader::ReadSourceRange(PerFileData &F, const RecordData &Record,
unsigned &Idx) {
@@ -4932,4 +5045,3 @@ ASTReader::PerFileData::~PerFileData() {
delete static_cast<HeaderFileInfoLookupTable *>(HeaderFileInfoTable);
delete static_cast<ASTSelectorLookupTable *>(SelectorLookupTable);
}
-
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp
index dec15dd..493ccba 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -744,17 +744,15 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) {
void ASTDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
VisitNamedDecl(D);
D->NamespaceLoc = ReadSourceLocation(Record, Idx);
- D->setQualifierRange(ReadSourceRange(Record, Idx));
- D->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx));
D->IdentLoc = ReadSourceLocation(Record, Idx);
+ D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
D->Namespace = cast<NamedDecl>(Reader.GetDecl(Record[Idx++]));
}
void ASTDeclReader::VisitUsingDecl(UsingDecl *D) {
VisitNamedDecl(D);
D->setUsingLocation(ReadSourceLocation(Record, Idx));
- D->setNestedNameRange(ReadSourceRange(Record, Idx));
- D->setTargetNestedNameDecl(Reader.ReadNestedNameSpecifier(Record, Idx));
+ D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
ReadDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record, Idx);
D->FirstUsingShadow = cast_or_null<UsingShadowDecl>(Reader.GetDecl(Record[Idx++]));
D->setTypeName(Record[Idx++]);
@@ -777,27 +775,24 @@ void ASTDeclReader::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
VisitNamedDecl(D);
D->UsingLoc = ReadSourceLocation(Record, Idx);
D->NamespaceLoc = ReadSourceLocation(Record, Idx);
- D->QualifierRange = ReadSourceRange(Record, Idx);
- D->Qualifier = Reader.ReadNestedNameSpecifier(Record, Idx);
+ D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
D->NominatedNamespace = cast<NamedDecl>(Reader.GetDecl(Record[Idx++]));
D->CommonAncestor = cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++]));
}
void ASTDeclReader::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
VisitValueDecl(D);
- D->setTargetNestedNameRange(ReadSourceRange(Record, Idx));
D->setUsingLoc(ReadSourceLocation(Record, Idx));
- D->setTargetNestedNameSpecifier(Reader.ReadNestedNameSpecifier(Record, Idx));
+ D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
ReadDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record, Idx);
}
void ASTDeclReader::VisitUnresolvedUsingTypenameDecl(
UnresolvedUsingTypenameDecl *D) {
VisitTypeDecl(D);
- D->TargetNestedNameRange = ReadSourceRange(Record, Idx);
D->UsingLocation = ReadSourceLocation(Record, Idx);
D->TypenameLocation = ReadSourceLocation(Record, Idx);
- D->TargetNestedNameSpecifier = Reader.ReadNestedNameSpecifier(Record, Idx);
+ D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
}
void ASTDeclReader::ReadCXXDefinitionData(
@@ -1432,30 +1427,33 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) {
break;
case DECL_NAMESPACE_ALIAS:
D = NamespaceAliasDecl::Create(*Context, 0, SourceLocation(),
- SourceLocation(), 0, SourceRange(), 0,
+ SourceLocation(), 0,
+ NestedNameSpecifierLoc(),
SourceLocation(), 0);
break;
case DECL_USING:
- D = UsingDecl::Create(*Context, 0, SourceRange(), SourceLocation(),
- 0, DeclarationNameInfo(), false);
+ D = UsingDecl::Create(*Context, 0, SourceLocation(),
+ NestedNameSpecifierLoc(), DeclarationNameInfo(),
+ false);
break;
case DECL_USING_SHADOW:
D = UsingShadowDecl::Create(*Context, 0, SourceLocation(), 0, 0);
break;
case DECL_USING_DIRECTIVE:
D = UsingDirectiveDecl::Create(*Context, 0, SourceLocation(),
- SourceLocation(), SourceRange(), 0,
+ SourceLocation(), NestedNameSpecifierLoc(),
SourceLocation(), 0, 0);
break;
case DECL_UNRESOLVED_USING_VALUE:
D = UnresolvedUsingValueDecl::Create(*Context, 0, SourceLocation(),
- SourceRange(), 0,
+ NestedNameSpecifierLoc(),
DeclarationNameInfo());
break;
case DECL_UNRESOLVED_USING_TYPENAME:
D = UnresolvedUsingTypenameDecl::Create(*Context, 0, SourceLocation(),
- SourceLocation(), SourceRange(),
- 0, SourceLocation(),
+ SourceLocation(),
+ NestedNameSpecifierLoc(),
+ SourceLocation(),
DeclarationName());
break;
case DECL_CXX_RECORD:
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp
index 4e91c98..42f0b1a 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -1167,14 +1167,13 @@ void ASTStmtReader::VisitCXXDeleteExpr(CXXDeleteExpr *E) {
void ASTStmtReader::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
VisitExpr(E);
- E->setBase(Reader.ReadSubExpr());
- E->setArrow(Record[Idx++]);
- E->setOperatorLoc(ReadSourceLocation(Record, Idx));
- E->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx));
- E->setQualifierRange(ReadSourceRange(Record, Idx));
- E->setScopeTypeInfo(GetTypeSourceInfo(Record, Idx));
- E->setColonColonLoc(ReadSourceLocation(Record, Idx));
- E->setTildeLoc(ReadSourceLocation(Record, Idx));
+ E->Base = Reader.ReadSubExpr();
+ E->IsArrow = Record[Idx++];
+ E->OperatorLoc = ReadSourceLocation(Record, Idx);
+ E->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
+ E->ScopeType = GetTypeSourceInfo(Record, Idx);
+ E->ColonColonLoc = ReadSourceLocation(Record, Idx);
+ E->TildeLoc = ReadSourceLocation(Record, Idx);
IdentifierInfo *II = Reader.GetIdentifierInfo(Record, Idx);
if (II)
@@ -1220,10 +1219,9 @@ ASTStmtReader::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
if (Record[Idx++])
ReadExplicitTemplateArgumentList(E->getExplicitTemplateArgs(),
Record[Idx++]);
-
+
+ E->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
ReadDeclarationNameInfo(E->NameInfo, Record, Idx);
- E->setQualifierRange(ReadSourceRange(Record, Idx));
- E->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx));
}
void
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp
index 8fcb535..383ca3d 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp
@@ -1023,8 +1023,9 @@ void ASTWriter::WriteLanguageOptions(const LangOptions &LangOpts) {
Record.push_back(LangOpts.LaxVectorConversions);
Record.push_back(LangOpts.AltiVec);
Record.push_back(LangOpts.Exceptions); // Support exception handling.
- Record.push_back(LangOpts.SjLjExceptions);
Record.push_back(LangOpts.ObjCExceptions);
+ Record.push_back(LangOpts.CXXExceptions);
+ Record.push_back(LangOpts.SjLjExceptions);
Record.push_back(LangOpts.MSBitfields); // MS-compatible structure layout
Record.push_back(LangOpts.NeXTRuntime); // Use NeXT runtime.
@@ -3275,15 +3276,21 @@ void ASTWriter::AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg,
Record);
}
-void ASTWriter::AddTypeSourceInfo(TypeSourceInfo *TInfo, RecordDataImpl &Record) {
+void ASTWriter::AddTypeSourceInfo(TypeSourceInfo *TInfo,
+ RecordDataImpl &Record) {
if (TInfo == 0) {
AddTypeRef(QualType(), Record);
return;
}
- AddTypeRef(TInfo->getType(), Record);
+ AddTypeLoc(TInfo->getTypeLoc(), Record);
+}
+
+void ASTWriter::AddTypeLoc(TypeLoc TL, RecordDataImpl &Record) {
+ AddTypeRef(TL.getType(), Record);
+
TypeLocWriter TLW(*this, Record);
- for (TypeLoc TL = TInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc())
+ for (; !TL.isNull(); TL = TL.getNextTypeLoc())
TLW.Visit(TL);
}
@@ -3436,8 +3443,7 @@ void ASTWriter::AddDeclarationNameInfo(const DeclarationNameInfo &NameInfo,
void ASTWriter::AddQualifierInfo(const QualifierInfo &Info,
RecordDataImpl &Record) {
- AddNestedNameSpecifier(Info.NNS, Record);
- AddSourceRange(Info.NNSRange, Record);
+ AddNestedNameSpecifierLoc(Info.QualifierLoc, Record);
Record.push_back(Info.NumTemplParamLists);
for (unsigned i=0, e=Info.NumTemplParamLists; i != e; ++i)
AddTemplateParameterList(Info.TemplParamLists[i], Record);
@@ -3469,6 +3475,10 @@ void ASTWriter::AddNestedNameSpecifier(NestedNameSpecifier *NNS,
AddDeclRef(NNS->getAsNamespace(), Record);
break;
+ case NestedNameSpecifier::NamespaceAlias:
+ AddDeclRef(NNS->getAsNamespaceAlias(), Record);
+ break;
+
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate:
AddTypeRef(QualType(NNS->getAsType(), 0), Record);
@@ -3482,6 +3492,55 @@ void ASTWriter::AddNestedNameSpecifier(NestedNameSpecifier *NNS,
}
}
+void ASTWriter::AddNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
+ RecordDataImpl &Record) {
+ // Nested name specifiers usually aren't too long. I think that 8 would
+ // typically accomodate the vast majority.
+ llvm::SmallVector<NestedNameSpecifierLoc , 8> NestedNames;
+
+ // Push each of the nested-name-specifiers's onto a stack for
+ // serialization in reverse order.
+ while (NNS) {
+ NestedNames.push_back(NNS);
+ NNS = NNS.getPrefix();
+ }
+
+ Record.push_back(NestedNames.size());
+ while(!NestedNames.empty()) {
+ NNS = NestedNames.pop_back_val();
+ NestedNameSpecifier::SpecifierKind Kind
+ = NNS.getNestedNameSpecifier()->getKind();
+ Record.push_back(Kind);
+ switch (Kind) {
+ case NestedNameSpecifier::Identifier:
+ AddIdentifierRef(NNS.getNestedNameSpecifier()->getAsIdentifier(), Record);
+ AddSourceRange(NNS.getLocalSourceRange(), Record);
+ break;
+
+ case NestedNameSpecifier::Namespace:
+ AddDeclRef(NNS.getNestedNameSpecifier()->getAsNamespace(), Record);
+ AddSourceRange(NNS.getLocalSourceRange(), Record);
+ break;
+
+ case NestedNameSpecifier::NamespaceAlias:
+ AddDeclRef(NNS.getNestedNameSpecifier()->getAsNamespaceAlias(), Record);
+ AddSourceRange(NNS.getLocalSourceRange(), Record);
+ break;
+
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ Record.push_back(Kind == NestedNameSpecifier::TypeSpecWithTemplate);
+ AddTypeLoc(NNS.getTypeLoc(), Record);
+ AddSourceLocation(NNS.getLocalSourceRange().getEnd(), Record);
+ break;
+
+ case NestedNameSpecifier::Global:
+ AddSourceLocation(NNS.getLocalSourceRange().getEnd(), Record);
+ break;
+ }
+ }
+}
+
void ASTWriter::AddTemplateName(TemplateName Name, RecordDataImpl &Record) {
TemplateName::NameKind Kind = Name.getKind();
Record.push_back(Kind);
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp
index ce07e138..12d1226 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -697,18 +697,16 @@ void ASTDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) {
void ASTDeclWriter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
VisitNamedDecl(D);
Writer.AddSourceLocation(D->getNamespaceLoc(), Record);
- Writer.AddSourceRange(D->getQualifierRange(), Record);
- Writer.AddNestedNameSpecifier(D->getQualifier(), Record);
Writer.AddSourceLocation(D->getTargetNameLoc(), Record);
+ Writer.AddNestedNameSpecifierLoc(D->getQualifierLoc(), Record);
Writer.AddDeclRef(D->getNamespace(), Record);
Code = serialization::DECL_NAMESPACE_ALIAS;
}
void ASTDeclWriter::VisitUsingDecl(UsingDecl *D) {
VisitNamedDecl(D);
- Writer.AddSourceRange(D->getNestedNameRange(), Record);
Writer.AddSourceLocation(D->getUsingLocation(), Record);
- Writer.AddNestedNameSpecifier(D->getTargetNestedNameDecl(), Record);
+ Writer.AddNestedNameSpecifierLoc(D->getQualifierLoc(), Record);
Writer.AddDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record);
Writer.AddDeclRef(D->FirstUsingShadow, Record);
Record.push_back(D->isTypeName());
@@ -728,8 +726,7 @@ void ASTDeclWriter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
VisitNamedDecl(D);
Writer.AddSourceLocation(D->getUsingLoc(), Record);
Writer.AddSourceLocation(D->getNamespaceKeyLocation(), Record);
- Writer.AddSourceRange(D->getQualifierRange(), Record);
- Writer.AddNestedNameSpecifier(D->getQualifier(), Record);
+ Writer.AddNestedNameSpecifierLoc(D->getQualifierLoc(), Record);
Writer.AddDeclRef(D->getNominatedNamespace(), Record);
Writer.AddDeclRef(dyn_cast<Decl>(D->getCommonAncestor()), Record);
Code = serialization::DECL_USING_DIRECTIVE;
@@ -737,9 +734,8 @@ void ASTDeclWriter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
void ASTDeclWriter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
VisitValueDecl(D);
- Writer.AddSourceRange(D->getTargetNestedNameRange(), Record);
Writer.AddSourceLocation(D->getUsingLoc(), Record);
- Writer.AddNestedNameSpecifier(D->getTargetNestedNameSpecifier(), Record);
+ Writer.AddNestedNameSpecifierLoc(D->getQualifierLoc(), Record);
Writer.AddDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record);
Code = serialization::DECL_UNRESOLVED_USING_VALUE;
}
@@ -747,10 +743,9 @@ void ASTDeclWriter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
void ASTDeclWriter::VisitUnresolvedUsingTypenameDecl(
UnresolvedUsingTypenameDecl *D) {
VisitTypeDecl(D);
- Writer.AddSourceRange(D->getTargetNestedNameRange(), Record);
Writer.AddSourceLocation(D->getUsingLoc(), Record);
Writer.AddSourceLocation(D->getTypenameLoc(), Record);
- Writer.AddNestedNameSpecifier(D->getTargetNestedNameSpecifier(), Record);
+ Writer.AddNestedNameSpecifierLoc(D->getQualifierLoc(), Record);
Code = serialization::DECL_UNRESOLVED_USING_TYPENAME;
}
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp
index 8a5ffe9..af846a9 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -1150,8 +1150,7 @@ void ASTStmtWriter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
Writer.AddStmt(E->getBase());
Record.push_back(E->isArrow());
Writer.AddSourceLocation(E->getOperatorLoc(), Record);
- Writer.AddNestedNameSpecifier(E->getQualifier(), Record);
- Writer.AddSourceRange(E->getQualifierRange(), Record);
+ Writer.AddNestedNameSpecifierLoc(E->getQualifierLoc(), Record);
Writer.AddTypeSourceInfo(E->getScopeTypeInfo(), Record);
Writer.AddSourceLocation(E->getColonColonLoc(), Record);
Writer.AddSourceLocation(E->getTildeLoc(), Record);
@@ -1217,9 +1216,8 @@ ASTStmtWriter::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
AddExplicitTemplateArgumentList(Args);
}
+ Writer.AddNestedNameSpecifierLoc(E->getQualifierLoc(), Record);
Writer.AddDeclarationNameInfo(E->NameInfo, Record);
- Writer.AddSourceRange(E->getQualifierRange(), Record);
- Writer.AddNestedNameSpecifier(E->getQualifier(), Record);
Code = serialization::EXPR_CXX_DEPENDENT_SCOPE_DECL_REF;
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp
index 9194791..25e224e 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp
@@ -12,9 +12,11 @@
//
//===----------------------------------------------------------------------===//
-#include "InternalChecks.h"
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
using namespace clang;
@@ -22,21 +24,15 @@ using namespace ento;
namespace {
class ArrayBoundChecker :
- public CheckerVisitor<ArrayBoundChecker> {
- BuiltinBug *BT;
+ public CheckerV2<check::Location> {
+ mutable llvm::OwningPtr<BuiltinBug> BT;
public:
- ArrayBoundChecker() : BT(0) {}
- static void *getTag() { static int x = 0; return &x; }
- void visitLocation(CheckerContext &C, const Stmt *S, SVal l, bool isLoad);
+ void checkLocation(SVal l, bool isLoad, CheckerContext &C) const;
};
}
-void ento::RegisterArrayBoundChecker(ExprEngine &Eng) {
- Eng.registerCheck(new ArrayBoundChecker());
-}
-
-void ArrayBoundChecker::visitLocation(CheckerContext &C, const Stmt *S, SVal l,
- bool isLoad) {
+void ArrayBoundChecker::checkLocation(SVal l, bool isLoad,
+ CheckerContext &C) const {
// Check for out of bound array element access.
const MemRegion *R = l.getAsRegion();
if (!R)
@@ -69,8 +65,8 @@ void ArrayBoundChecker::visitLocation(CheckerContext &C, const Stmt *S, SVal l,
return;
if (!BT)
- BT = new BuiltinBug("Out-of-bound array access",
- "Access out-of-bound array element (buffer overflow)");
+ BT.reset(new BuiltinBug("Out-of-bound array access",
+ "Access out-of-bound array element (buffer overflow)"));
// FIXME: It would be nice to eventually make this diagnostic more clear,
// e.g., by referencing the original declaration or by saying *why* this
@@ -80,7 +76,7 @@ void ArrayBoundChecker::visitLocation(CheckerContext &C, const Stmt *S, SVal l,
RangedBugReport *report =
new RangedBugReport(*BT, BT->getDescription(), N);
- report->addRange(S->getSourceRange());
+ report->addRange(C.getStmt()->getSourceRange());
C.EmitReport(report);
return;
}
@@ -90,3 +86,7 @@ void ArrayBoundChecker::visitLocation(CheckerContext &C, const Stmt *S, SVal l,
assert(StInBound);
C.addTransition(StInBound);
}
+
+void ento::registerArrayBoundChecker(CheckerManager &mgr) {
+ mgr.registerChecker<ArrayBoundChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
index 1b6c528..7aff201 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
@@ -16,14 +16,14 @@
#include "BasicObjCFoundationChecks.h"
#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
#include "clang/StaticAnalyzer/Checkers/LocalCheckers.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
@@ -69,22 +69,23 @@ static inline bool isNil(SVal X) {
//===----------------------------------------------------------------------===//
namespace {
- class NilArgChecker : public CheckerVisitor<NilArgChecker> {
- APIMisuse *BT;
- void WarnNilArg(CheckerContext &C, const ObjCMessage &msg, unsigned Arg);
+ class NilArgChecker : public CheckerV2<check::PreObjCMessage> {
+ mutable llvm::OwningPtr<APIMisuse> BT;
+
+ void WarnNilArg(CheckerContext &C,
+ const ObjCMessage &msg, unsigned Arg) const;
+
public:
- NilArgChecker() : BT(0) {}
- static void *getTag() { static int x = 0; return &x; }
- void preVisitObjCMessage(CheckerContext &C, ObjCMessage msg);
+ void checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const;
};
}
void NilArgChecker::WarnNilArg(CheckerContext &C,
const ObjCMessage &msg,
- unsigned int Arg)
+ unsigned int Arg) const
{
if (!BT)
- BT = new APIMisuse("nil argument");
+ BT.reset(new APIMisuse("nil argument"));
if (ExplodedNode *N = C.generateSink()) {
llvm::SmallString<128> sbuf;
@@ -98,9 +99,8 @@ void NilArgChecker::WarnNilArg(CheckerContext &C,
}
}
-void NilArgChecker::preVisitObjCMessage(CheckerContext &C,
- ObjCMessage msg)
-{
+void NilArgChecker::checkPreObjCMessage(ObjCMessage msg,
+ CheckerContext &C) const {
const ObjCInterfaceType *ReceiverType = GetReceiverType(msg);
if (!ReceiverType)
return;
@@ -140,14 +140,14 @@ void NilArgChecker::preVisitObjCMessage(CheckerContext &C,
//===----------------------------------------------------------------------===//
namespace {
-class CFNumberCreateChecker : public CheckerVisitor<CFNumberCreateChecker> {
- APIMisuse* BT;
- IdentifierInfo* II;
+class CFNumberCreateChecker : public CheckerV2< check::PreStmt<CallExpr> > {
+ mutable llvm::OwningPtr<APIMisuse> BT;
+ mutable IdentifierInfo* II;
public:
- CFNumberCreateChecker() : BT(0), II(0) {}
- ~CFNumberCreateChecker() {}
- static void *getTag() { static int x = 0; return &x; }
- void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
+ CFNumberCreateChecker() : II(0) {}
+
+ void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
+
private:
void EmitError(const TypedRegion* R, const Expr* Ex,
uint64_t SourceSize, uint64_t TargetSize, uint64_t NumberKind);
@@ -247,9 +247,8 @@ static const char* GetCFNumberTypeStr(uint64_t i) {
}
#endif
-void CFNumberCreateChecker::PreVisitCallExpr(CheckerContext &C,
- const CallExpr *CE)
-{
+void CFNumberCreateChecker::checkPreStmt(const CallExpr *CE,
+ CheckerContext &C) const {
const Expr* Callee = CE->getCallee();
const GRState *state = C.getState();
SVal CallV = state->getSVal(Callee);
@@ -335,7 +334,7 @@ void CFNumberCreateChecker::PreVisitCallExpr(CheckerContext &C,
<< " bits of the input integer will be lost.";
if (!BT)
- BT = new APIMisuse("Bad use of CFNumberCreate");
+ BT.reset(new APIMisuse("Bad use of CFNumberCreate"));
RangedBugReport *report = new RangedBugReport(*BT, os.str(), N);
report->addRange(CE->getArg(2)->getSourceRange());
@@ -348,19 +347,18 @@ void CFNumberCreateChecker::PreVisitCallExpr(CheckerContext &C,
//===----------------------------------------------------------------------===//
namespace {
-class CFRetainReleaseChecker : public CheckerVisitor<CFRetainReleaseChecker> {
- APIMisuse *BT;
- IdentifierInfo *Retain, *Release;
+class CFRetainReleaseChecker : public CheckerV2< check::PreStmt<CallExpr> > {
+ mutable llvm::OwningPtr<APIMisuse> BT;
+ mutable IdentifierInfo *Retain, *Release;
public:
- CFRetainReleaseChecker(): BT(0), Retain(0), Release(0) {}
- static void *getTag() { static int x = 0; return &x; }
- void PreVisitCallExpr(CheckerContext& C, const CallExpr* CE);
+ CFRetainReleaseChecker(): Retain(0), Release(0) {}
+ void checkPreStmt(const CallExpr* CE, CheckerContext& C) const;
};
} // end anonymous namespace
-void CFRetainReleaseChecker::PreVisitCallExpr(CheckerContext& C,
- const CallExpr* CE) {
+void CFRetainReleaseChecker::checkPreStmt(const CallExpr* CE,
+ CheckerContext& C) const {
// If the CallExpr doesn't have exactly 1 argument just give up checking.
if (CE->getNumArgs() != 1)
return;
@@ -377,7 +375,7 @@ void CFRetainReleaseChecker::PreVisitCallExpr(CheckerContext& C,
ASTContext &Ctx = C.getASTContext();
Retain = &Ctx.Idents.get("CFRetain");
Release = &Ctx.Idents.get("CFRelease");
- BT = new APIMisuse("null passed to CFRetain/CFRelease");
+ BT.reset(new APIMisuse("null passed to CFRetain/CFRelease"));
}
// Check if we called CFRetain/CFRelease.
@@ -431,28 +429,24 @@ void CFRetainReleaseChecker::PreVisitCallExpr(CheckerContext& C,
//===----------------------------------------------------------------------===//
namespace {
-class ClassReleaseChecker : public CheckerVisitor<ClassReleaseChecker> {
- Selector releaseS;
- Selector retainS;
- Selector autoreleaseS;
- Selector drainS;
- BugType *BT;
-public:
- ClassReleaseChecker()
- : BT(0) {}
+class ClassReleaseChecker : public CheckerV2<check::PreObjCMessage> {
+ mutable Selector releaseS;
+ mutable Selector retainS;
+ mutable Selector autoreleaseS;
+ mutable Selector drainS;
+ mutable llvm::OwningPtr<BugType> BT;
- static void *getTag() { static int x = 0; return &x; }
-
- void preVisitObjCMessage(CheckerContext &C, ObjCMessage msg);
+public:
+ void checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const;
};
}
-void ClassReleaseChecker::preVisitObjCMessage(CheckerContext &C,
- ObjCMessage msg) {
+void ClassReleaseChecker::checkPreObjCMessage(ObjCMessage msg,
+ CheckerContext &C) const {
if (!BT) {
- BT = new APIMisuse("message incorrectly sent to class instead of class "
- "instance");
+ BT.reset(new APIMisuse("message incorrectly sent to class instead of class "
+ "instance"));
ASTContext &Ctx = C.getASTContext();
releaseS = GetNullarySelector("release", Ctx);
@@ -488,34 +482,18 @@ void ClassReleaseChecker::preVisitObjCMessage(CheckerContext &C,
// Check registration.
//===----------------------------------------------------------------------===//
-static void RegisterNilArgChecker(ExprEngine& Eng) {
- Eng.registerCheck(new NilArgChecker());
-}
-
void ento::registerNilArgChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterNilArgChecker);
-}
-
-static void RegisterCFNumberCreateChecker(ExprEngine& Eng) {
- Eng.registerCheck(new CFNumberCreateChecker());
+ mgr.registerChecker<NilArgChecker>();
}
void ento::registerCFNumberCreateChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterCFNumberCreateChecker);
-}
-
-static void RegisterCFRetainReleaseChecker(ExprEngine& Eng) {
- Eng.registerCheck(new CFRetainReleaseChecker());
+ mgr.registerChecker<CFNumberCreateChecker>();
}
void ento::registerCFRetainReleaseChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterCFRetainReleaseChecker);
-}
-
-static void RegisterClassReleaseChecker(ExprEngine& Eng) {
- Eng.registerCheck(new ClassReleaseChecker());
+ mgr.registerChecker<CFRetainReleaseChecker>();
}
void ento::registerClassReleaseChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterClassReleaseChecker);
+ mgr.registerChecker<ClassReleaseChecker>();
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
index 03f9047..2566e3c 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -13,9 +13,10 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
#include "llvm/ADT/StringSwitch.h"
@@ -23,75 +24,86 @@ using namespace clang;
using namespace ento;
namespace {
-class CStringChecker : public CheckerVisitor<CStringChecker> {
- BugType *BT_Null, *BT_Bounds, *BT_BoundsWrite, *BT_Overlap, *BT_NotCString;
+class CStringChecker : public CheckerV2< eval::Call,
+ check::PreStmt<DeclStmt>,
+ check::LiveSymbols,
+ check::DeadSymbols,
+ check::RegionChanges
+ > {
+ mutable llvm::OwningPtr<BugType> BT_Null, BT_Bounds, BT_BoundsWrite,
+ BT_Overlap, BT_NotCString;
public:
- CStringChecker()
- : BT_Null(0), BT_Bounds(0), BT_BoundsWrite(0), BT_Overlap(0), BT_NotCString(0)
- {}
static void *getTag() { static int tag; return &tag; }
- bool evalCallExpr(CheckerContext &C, const CallExpr *CE);
- void PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS);
- void MarkLiveSymbols(const GRState *state, SymbolReaper &SR);
- void evalDeadSymbols(CheckerContext &C, SymbolReaper &SR);
- bool wantsRegionChangeUpdate(const GRState *state);
+ bool evalCall(const CallExpr *CE, CheckerContext &C) const;
+ void checkPreStmt(const DeclStmt *DS, CheckerContext &C) const;
+ void checkLiveSymbols(const GRState *state, SymbolReaper &SR) const;
+ void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
+ bool wantsRegionChangeUpdate(const GRState *state) const;
- const GRState *EvalRegionChanges(const GRState *state,
- const MemRegion * const *Begin,
- const MemRegion * const *End,
- bool*);
+ const GRState *checkRegionChanges(const GRState *state,
+ const MemRegion * const *Begin,
+ const MemRegion * const *End) const;
- typedef void (CStringChecker::*FnCheck)(CheckerContext &, const CallExpr *);
+ typedef void (CStringChecker::*FnCheck)(CheckerContext &,
+ const CallExpr *) const;
- void evalMemcpy(CheckerContext &C, const CallExpr *CE);
- void evalMemmove(CheckerContext &C, const CallExpr *CE);
- void evalBcopy(CheckerContext &C, const CallExpr *CE);
+ void evalMemcpy(CheckerContext &C, const CallExpr *CE) const;
+ void evalMemmove(CheckerContext &C, const CallExpr *CE) const;
+ void evalBcopy(CheckerContext &C, const CallExpr *CE) const;
void evalCopyCommon(CheckerContext &C, const GRState *state,
const Expr *Size, const Expr *Source, const Expr *Dest,
- bool Restricted = false);
+ bool Restricted = false) const;
- void evalMemcmp(CheckerContext &C, const CallExpr *CE);
+ void evalMemcmp(CheckerContext &C, const CallExpr *CE) const;
- void evalstrLength(CheckerContext &C, const CallExpr *CE);
+ void evalstrLength(CheckerContext &C, const CallExpr *CE) const;
+ void evalstrnLength(CheckerContext &C, const CallExpr *CE) const;
+ void evalstrLengthCommon(CheckerContext &C, const CallExpr *CE,
+ bool IsStrnlen = false) const;
- void evalStrcpy(CheckerContext &C, const CallExpr *CE);
- void evalStpcpy(CheckerContext &C, const CallExpr *CE);
- void evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, bool returnEnd);
+ void evalStrcpy(CheckerContext &C, const CallExpr *CE) const;
+ void evalStrncpy(CheckerContext &C, const CallExpr *CE) const;
+ void evalStpcpy(CheckerContext &C, const CallExpr *CE) const;
+ void evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, bool returnEnd,
+ bool isStrncpy) const;
// Utility methods
std::pair<const GRState*, const GRState*>
- assumeZero(CheckerContext &C, const GRState *state, SVal V, QualType Ty);
-
- const GRState *setCStringLength(const GRState *state, const MemRegion *MR,
- SVal strLength);
- SVal getCStringLengthForRegion(CheckerContext &C, const GRState *&state,
- const Expr *Ex, const MemRegion *MR);
+ static assumeZero(CheckerContext &C,
+ const GRState *state, SVal V, QualType Ty);
+
+ static const GRState *setCStringLength(const GRState *state,
+ const MemRegion *MR, SVal strLength);
+ static SVal getCStringLengthForRegion(CheckerContext &C,
+ const GRState *&state,
+ const Expr *Ex, const MemRegion *MR);
SVal getCStringLength(CheckerContext &C, const GRState *&state,
- const Expr *Ex, SVal Buf);
+ const Expr *Ex, SVal Buf) const;
- const GRState *InvalidateBuffer(CheckerContext &C, const GRState *state,
- const Expr *Ex, SVal V);
+ static const GRState *InvalidateBuffer(CheckerContext &C,
+ const GRState *state,
+ const Expr *Ex, SVal V);
- bool SummarizeRegion(llvm::raw_ostream& os, ASTContext& Ctx,
- const MemRegion *MR);
+ static bool SummarizeRegion(llvm::raw_ostream& os, ASTContext& Ctx,
+ const MemRegion *MR);
// Re-usable checks
const GRState *checkNonNull(CheckerContext &C, const GRState *state,
- const Expr *S, SVal l);
+ const Expr *S, SVal l) const;
const GRState *CheckLocation(CheckerContext &C, const GRState *state,
const Expr *S, SVal l,
- bool IsDestination = false);
+ bool IsDestination = false) const;
const GRState *CheckBufferAccess(CheckerContext &C, const GRState *state,
const Expr *Size,
const Expr *FirstBuf,
const Expr *SecondBuf = NULL,
- bool FirstIsDestination = false);
+ bool FirstIsDestination = false) const;
const GRState *CheckOverlap(CheckerContext &C, const GRState *state,
const Expr *Size, const Expr *First,
- const Expr *Second);
+ const Expr *Second) const;
void emitOverlapBug(CheckerContext &C, const GRState *state,
- const Stmt *First, const Stmt *Second);
+ const Stmt *First, const Stmt *Second) const;
};
class CStringLength {
@@ -110,14 +122,6 @@ namespace ento {
}
}
-static void RegisterCStringChecker(ExprEngine &Eng) {
- Eng.registerCheck(new CStringChecker());
-}
-
-void ento::registerCStringChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterCStringChecker);
-}
-
//===----------------------------------------------------------------------===//
// Individual checks and utility methods.
//===----------------------------------------------------------------------===//
@@ -136,7 +140,7 @@ CStringChecker::assumeZero(CheckerContext &C, const GRState *state, SVal V,
const GRState *CStringChecker::checkNonNull(CheckerContext &C,
const GRState *state,
- const Expr *S, SVal l) {
+ const Expr *S, SVal l) const {
// If a previous check has failed, propagate the failure.
if (!state)
return NULL;
@@ -150,11 +154,11 @@ const GRState *CStringChecker::checkNonNull(CheckerContext &C,
return NULL;
if (!BT_Null)
- BT_Null = new BuiltinBug("API",
- "Null pointer argument in call to byte string function");
+ BT_Null.reset(new BuiltinBug("API",
+ "Null pointer argument in call to byte string function"));
// Generate a report for this bug.
- BuiltinBug *BT = static_cast<BuiltinBug*>(BT_Null);
+ BuiltinBug *BT = static_cast<BuiltinBug*>(BT_Null.get());
EnhancedBugReport *report = new EnhancedBugReport(*BT,
BT->getDescription(), N);
@@ -173,7 +177,7 @@ const GRState *CStringChecker::checkNonNull(CheckerContext &C,
const GRState *CStringChecker::CheckLocation(CheckerContext &C,
const GRState *state,
const Expr *S, SVal l,
- bool IsDestination) {
+ bool IsDestination) const {
// If a previous check has failed, propagate the failure.
if (!state)
return NULL;
@@ -209,16 +213,16 @@ const GRState *CStringChecker::CheckLocation(CheckerContext &C,
BuiltinBug *BT;
if (IsDestination) {
if (!BT_BoundsWrite) {
- BT_BoundsWrite = new BuiltinBug("Out-of-bound array access",
- "Byte string function overflows destination buffer");
+ BT_BoundsWrite.reset(new BuiltinBug("Out-of-bound array access",
+ "Byte string function overflows destination buffer"));
}
- BT = static_cast<BuiltinBug*>(BT_BoundsWrite);
+ BT = static_cast<BuiltinBug*>(BT_BoundsWrite.get());
} else {
if (!BT_Bounds) {
- BT_Bounds = new BuiltinBug("Out-of-bound array access",
- "Byte string function accesses out-of-bound array element");
+ BT_Bounds.reset(new BuiltinBug("Out-of-bound array access",
+ "Byte string function accesses out-of-bound array element"));
}
- BT = static_cast<BuiltinBug*>(BT_Bounds);
+ BT = static_cast<BuiltinBug*>(BT_Bounds.get());
}
// FIXME: It would be nice to eventually make this diagnostic more clear,
@@ -243,7 +247,7 @@ const GRState *CStringChecker::CheckBufferAccess(CheckerContext &C,
const Expr *Size,
const Expr *FirstBuf,
const Expr *SecondBuf,
- bool FirstIsDestination) {
+ bool FirstIsDestination) const {
// If a previous check has failed, propagate the failure.
if (!state)
return NULL;
@@ -306,7 +310,7 @@ const GRState *CStringChecker::CheckOverlap(CheckerContext &C,
const GRState *state,
const Expr *Size,
const Expr *First,
- const Expr *Second) {
+ const Expr *Second) const {
// Do a simple check for overlap: if the two arguments are from the same
// buffer, see if the end of the first is greater than the start of the second
// or vice versa.
@@ -413,13 +417,13 @@ const GRState *CStringChecker::CheckOverlap(CheckerContext &C,
}
void CStringChecker::emitOverlapBug(CheckerContext &C, const GRState *state,
- const Stmt *First, const Stmt *Second) {
+ const Stmt *First, const Stmt *Second) const {
ExplodedNode *N = C.generateSink(state);
if (!N)
return;
if (!BT_Overlap)
- BT_Overlap = new BugType("Unix API", "Improper arguments");
+ BT_Overlap.reset(new BugType("Unix API", "Improper arguments"));
// Generate a report for this bug.
RangedBugReport *report =
@@ -480,13 +484,14 @@ SVal CStringChecker::getCStringLengthForRegion(CheckerContext &C,
unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
SValBuilder &svalBuilder = C.getSValBuilder();
QualType sizeTy = svalBuilder.getContext().getSizeType();
- SVal strLength = svalBuilder.getMetadataSymbolVal(getTag(), MR, Ex, sizeTy, Count);
+ SVal strLength = svalBuilder.getMetadataSymbolVal(CStringChecker::getTag(),
+ MR, Ex, sizeTy, Count);
state = state->set<CStringLength>(MR, strLength);
return strLength;
}
SVal CStringChecker::getCStringLength(CheckerContext &C, const GRState *&state,
- const Expr *Ex, SVal Buf) {
+ const Expr *Ex, SVal Buf) const {
const MemRegion *MR = Buf.getAsRegion();
if (!MR) {
// If we can't get a region, see if it's something we /know/ isn't a
@@ -495,8 +500,8 @@ SVal CStringChecker::getCStringLength(CheckerContext &C, const GRState *&state,
if (loc::GotoLabel *Label = dyn_cast<loc::GotoLabel>(&Buf)) {
if (ExplodedNode *N = C.generateNode(state)) {
if (!BT_NotCString)
- BT_NotCString = new BuiltinBug("API",
- "Argument is not a null-terminated string.");
+ BT_NotCString.reset(new BuiltinBug("API",
+ "Argument is not a null-terminated string."));
llvm::SmallString<120> buf;
llvm::raw_svector_ostream os(buf);
@@ -551,8 +556,8 @@ SVal CStringChecker::getCStringLength(CheckerContext &C, const GRState *&state,
// The caller should always be prepared to handle this case.
if (ExplodedNode *N = C.generateNode(state)) {
if (!BT_NotCString)
- BT_NotCString = new BuiltinBug("API",
- "Argument is not a null-terminated string.");
+ BT_NotCString.reset(new BuiltinBug("API",
+ "Argument is not a null-terminated string."));
llvm::SmallString<120> buf;
llvm::raw_svector_ostream os(buf);
@@ -652,7 +657,7 @@ bool CStringChecker::SummarizeRegion(llvm::raw_ostream& os, ASTContext& Ctx,
void CStringChecker::evalCopyCommon(CheckerContext &C, const GRState *state,
const Expr *Size, const Expr *Dest,
- const Expr *Source, bool Restricted) {
+ const Expr *Source, bool Restricted) const {
// See if the size argument is zero.
SVal sizeVal = state->getSVal(Size);
QualType sizeTy = Size->getType();
@@ -685,7 +690,7 @@ void CStringChecker::evalCopyCommon(CheckerContext &C, const GRState *state,
}
-void CStringChecker::evalMemcpy(CheckerContext &C, const CallExpr *CE) {
+void CStringChecker::evalMemcpy(CheckerContext &C, const CallExpr *CE) const {
// void *memcpy(void *restrict dst, const void *restrict src, size_t n);
// The return value is the address of the destination buffer.
const Expr *Dest = CE->getArg(0);
@@ -694,7 +699,7 @@ void CStringChecker::evalMemcpy(CheckerContext &C, const CallExpr *CE) {
evalCopyCommon(C, state, CE->getArg(2), Dest, CE->getArg(1), true);
}
-void CStringChecker::evalMemmove(CheckerContext &C, const CallExpr *CE) {
+void CStringChecker::evalMemmove(CheckerContext &C, const CallExpr *CE) const {
// void *memmove(void *dst, const void *src, size_t n);
// The return value is the address of the destination buffer.
const Expr *Dest = CE->getArg(0);
@@ -703,12 +708,12 @@ void CStringChecker::evalMemmove(CheckerContext &C, const CallExpr *CE) {
evalCopyCommon(C, state, CE->getArg(2), Dest, CE->getArg(1));
}
-void CStringChecker::evalBcopy(CheckerContext &C, const CallExpr *CE) {
+void CStringChecker::evalBcopy(CheckerContext &C, const CallExpr *CE) const {
// void bcopy(const void *src, void *dst, size_t n);
evalCopyCommon(C, C.getState(), CE->getArg(2), CE->getArg(1), CE->getArg(0));
}
-void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) {
+void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) const {
// int memcmp(const void *s1, const void *s2, size_t n);
const Expr *Left = CE->getArg(0);
const Expr *Right = CE->getArg(1);
@@ -774,8 +779,20 @@ void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) {
}
}
-void CStringChecker::evalstrLength(CheckerContext &C, const CallExpr *CE) {
+void CStringChecker::evalstrLength(CheckerContext &C,
+ const CallExpr *CE) const {
// size_t strlen(const char *s);
+ evalstrLengthCommon(C, CE, /* IsStrnlen = */ false);
+}
+
+void CStringChecker::evalstrnLength(CheckerContext &C,
+ const CallExpr *CE) const {
+ // size_t strnlen(const char *s, size_t maxlen);
+ evalstrLengthCommon(C, CE, /* IsStrnlen = */ true);
+}
+
+void CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE,
+ bool IsStrnlen) const {
const GRState *state = C.getState();
const Expr *Arg = CE->getArg(0);
SVal ArgVal = state->getSVal(Arg);
@@ -791,6 +808,32 @@ void CStringChecker::evalstrLength(CheckerContext &C, const CallExpr *CE) {
if (strLength.isUndef())
return;
+ // If the check is for strnlen() then bind the return value to no more than
+ // the maxlen value.
+ if (IsStrnlen) {
+ const Expr *maxlenExpr = CE->getArg(1);
+ SVal maxlenVal = state->getSVal(maxlenExpr);
+
+ NonLoc *strLengthNL = dyn_cast<NonLoc>(&strLength);
+ NonLoc *maxlenValNL = dyn_cast<NonLoc>(&maxlenVal);
+
+ QualType cmpTy = C.getSValBuilder().getContext().IntTy;
+ const GRState *stateTrue, *stateFalse;
+
+ // Check if the strLength is greater than or equal to the maxlen
+ llvm::tie(stateTrue, stateFalse) =
+ state->assume(cast<DefinedOrUnknownSVal>
+ (C.getSValBuilder().evalBinOpNN(state, BO_GE,
+ *strLengthNL, *maxlenValNL,
+ cmpTy)));
+
+ // If the strLength is greater than or equal to the maxlen, set strLength
+ // to maxlen
+ if (stateTrue && !stateFalse) {
+ strLength = maxlenVal;
+ }
+ }
+
// If getCStringLength couldn't figure out the length, conjure a return
// value, so it can be used in constraints, at least.
if (strLength.isUnknown()) {
@@ -804,18 +847,23 @@ void CStringChecker::evalstrLength(CheckerContext &C, const CallExpr *CE) {
}
}
-void CStringChecker::evalStrcpy(CheckerContext &C, const CallExpr *CE) {
+void CStringChecker::evalStrcpy(CheckerContext &C, const CallExpr *CE) const {
+ // char *strcpy(char *restrict dst, const char *restrict src);
+ evalStrcpyCommon(C, CE, /* returnEnd = */ false, /* isStrncpy = */ false);
+}
+
+void CStringChecker::evalStrncpy(CheckerContext &C, const CallExpr *CE) const {
// char *strcpy(char *restrict dst, const char *restrict src);
- evalStrcpyCommon(C, CE, /* returnEnd = */ false);
+ evalStrcpyCommon(C, CE, /* returnEnd = */ false, /* isStrncpy = */ true);
}
-void CStringChecker::evalStpcpy(CheckerContext &C, const CallExpr *CE) {
+void CStringChecker::evalStpcpy(CheckerContext &C, const CallExpr *CE) const {
// char *stpcpy(char *restrict dst, const char *restrict src);
- evalStrcpyCommon(C, CE, /* returnEnd = */ true);
+ evalStrcpyCommon(C, CE, /* returnEnd = */ true, /* isStrncpy = */ false);
}
void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
- bool returnEnd) {
+ bool returnEnd, bool isStrncpy) const {
const GRState *state = C.getState();
// Check that the destination is non-null
@@ -840,6 +888,31 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
if (strLength.isUndef())
return;
+ if (isStrncpy) {
+ // Get the max number of characters to copy
+ const Expr *lenExpr = CE->getArg(2);
+ SVal lenVal = state->getSVal(lenExpr);
+
+ NonLoc *strLengthNL = dyn_cast<NonLoc>(&strLength);
+ NonLoc *lenValNL = dyn_cast<NonLoc>(&lenVal);
+
+ QualType cmpTy = C.getSValBuilder().getContext().IntTy;
+ const GRState *stateTrue, *stateFalse;
+
+ // Check if the max number to copy is less than the length of the src
+ llvm::tie(stateTrue, stateFalse) =
+ state->assume(cast<DefinedOrUnknownSVal>
+ (C.getSValBuilder().evalBinOpNN(state, BO_GT,
+ *strLengthNL, *lenValNL,
+ cmpTy)));
+
+ if (stateTrue) {
+ // Max number to copy is less than the length of the src, so the actual
+ // strLength copied is the max number arg.
+ strLength = lenVal;
+ }
+ }
+
SVal Result = (returnEnd ? UnknownVal() : DstVal);
// If the destination is a MemRegion, try to check for a buffer overflow and
@@ -889,7 +962,7 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
// The driver method, and other Checker callbacks.
//===----------------------------------------------------------------------===//
-bool CStringChecker::evalCallExpr(CheckerContext &C, const CallExpr *CE) {
+bool CStringChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
// Get the callee. All the functions we care about are C functions
// with simple identifiers.
const GRState *state = C.getState();
@@ -912,8 +985,10 @@ bool CStringChecker::evalCallExpr(CheckerContext &C, const CallExpr *CE) {
.Cases("memcmp", "bcmp", &CStringChecker::evalMemcmp)
.Cases("memmove", "__memmove_chk", &CStringChecker::evalMemmove)
.Cases("strcpy", "__strcpy_chk", &CStringChecker::evalStrcpy)
+ .Cases("strncpy", "__strncpy_chk", &CStringChecker::evalStrncpy)
.Cases("stpcpy", "__stpcpy_chk", &CStringChecker::evalStpcpy)
.Case("strlen", &CStringChecker::evalstrLength)
+ .Case("strnlen", &CStringChecker::evalstrnLength)
.Case("bcopy", &CStringChecker::evalBcopy)
.Default(NULL);
@@ -926,7 +1001,7 @@ bool CStringChecker::evalCallExpr(CheckerContext &C, const CallExpr *CE) {
return true;
}
-void CStringChecker::PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS) {
+void CStringChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
// Record string length for char a[] = "abc";
const GRState *state = C.getState();
@@ -962,15 +1037,15 @@ void CStringChecker::PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS) {
C.addTransition(state);
}
-bool CStringChecker::wantsRegionChangeUpdate(const GRState *state) {
+bool CStringChecker::wantsRegionChangeUpdate(const GRState *state) const {
CStringLength::EntryMap Entries = state->get<CStringLength>();
return !Entries.isEmpty();
}
-const GRState *CStringChecker::EvalRegionChanges(const GRState *state,
- const MemRegion * const *Begin,
- const MemRegion * const *End,
- bool *) {
+const GRState *
+CStringChecker::checkRegionChanges(const GRState *state,
+ const MemRegion * const *Begin,
+ const MemRegion * const *End) const {
CStringLength::EntryMap Entries = state->get<CStringLength>();
if (Entries.isEmpty())
return state;
@@ -1017,7 +1092,8 @@ const GRState *CStringChecker::EvalRegionChanges(const GRState *state,
return state->set<CStringLength>(Entries);
}
-void CStringChecker::MarkLiveSymbols(const GRState *state, SymbolReaper &SR) {
+void CStringChecker::checkLiveSymbols(const GRState *state,
+ SymbolReaper &SR) const {
// Mark all symbols in our string length map as valid.
CStringLength::EntryMap Entries = state->get<CStringLength>();
@@ -1029,7 +1105,8 @@ void CStringChecker::MarkLiveSymbols(const GRState *state, SymbolReaper &SR) {
}
}
-void CStringChecker::evalDeadSymbols(CheckerContext &C, SymbolReaper &SR) {
+void CStringChecker::checkDeadSymbols(SymbolReaper &SR,
+ CheckerContext &C) const {
if (!SR.hasDeadSymbols())
return;
@@ -1051,3 +1128,7 @@ void CStringChecker::evalDeadSymbols(CheckerContext &C, SymbolReaper &SR) {
state = state->set<CStringLength>(Entries);
C.generateNode(state);
}
+
+void ento::registerCStringChecker(CheckerManager &mgr) {
+ mgr.registerChecker<CStringChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
index 518cf96..6a4506b 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
@@ -11,30 +11,25 @@
// whether the size of the symbolic region is a multiple of the size of T.
//
//===----------------------------------------------------------------------===//
-#include "clang/AST/CharUnits.h"
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
-#include "InternalChecks.h"
+#include "clang/AST/CharUnits.h"
using namespace clang;
using namespace ento;
namespace {
-class CastSizeChecker : public CheckerVisitor<CastSizeChecker> {
- BuiltinBug *BT;
+class CastSizeChecker : public CheckerV2< check::PreStmt<CastExpr> > {
+ mutable llvm::OwningPtr<BuiltinBug> BT;
public:
- CastSizeChecker() : BT(0) {}
- static void *getTag();
- void PreVisitCastExpr(CheckerContext &C, const CastExpr *B);
+ void checkPreStmt(const CastExpr *CE, CheckerContext &C) const;
};
}
-void *CastSizeChecker::getTag() {
- static int x;
- return &x;
-}
-
-void CastSizeChecker::PreVisitCastExpr(CheckerContext &C, const CastExpr *CE) {
+void CastSizeChecker::checkPreStmt(const CastExpr *CE,CheckerContext &C) const {
const Expr *E = CE->getSubExpr();
ASTContext &Ctx = C.getASTContext();
QualType ToTy = Ctx.getCanonicalType(CE->getType());
@@ -74,9 +69,9 @@ void CastSizeChecker::PreVisitCastExpr(CheckerContext &C, const CastExpr *CE) {
if (regionSize % typeSize != 0) {
if (ExplodedNode *errorNode = C.generateSink()) {
if (!BT)
- BT = new BuiltinBug("Cast region with wrong size.",
+ BT.reset(new BuiltinBug("Cast region with wrong size.",
"Cast a region whose size is not a multiple of the"
- " destination type size.");
+ " destination type size."));
RangedBugReport *R = new RangedBugReport(*BT, BT->getDescription(),
errorNode);
R->addRange(CE->getSourceRange());
@@ -86,6 +81,6 @@ void CastSizeChecker::PreVisitCastExpr(CheckerContext &C, const CastExpr *CE) {
}
-void ento::RegisterCastSizeChecker(ExprEngine &Eng) {
- Eng.registerCheck(new CastSizeChecker());
+void ento::registerCastSizeChecker(CheckerManager &mgr) {
+ mgr.registerChecker<CastSizeChecker>();
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp
index 8ec226a..04cc253 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp
@@ -14,31 +14,25 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
using namespace clang;
using namespace ento;
namespace {
-class CastToStructChecker
- : public CheckerVisitor<CastToStructChecker> {
- BuiltinBug *BT;
+class CastToStructChecker : public CheckerV2< check::PreStmt<CastExpr> > {
+ mutable llvm::OwningPtr<BuiltinBug> BT;
+
public:
- CastToStructChecker() : BT(0) {}
- static void *getTag();
- void PreVisitCastExpr(CheckerContext &C, const CastExpr *B);
+ void checkPreStmt(const CastExpr *CE, CheckerContext &C) const;
};
}
-void *CastToStructChecker::getTag() {
- static int x;
- return &x;
-}
-
-void CastToStructChecker::PreVisitCastExpr(CheckerContext &C,
- const CastExpr *CE) {
+void CastToStructChecker::checkPreStmt(const CastExpr *CE,
+ CheckerContext &C) const {
const Expr *E = CE->getSubExpr();
ASTContext &Ctx = C.getASTContext();
QualType OrigTy = Ctx.getCanonicalType(E->getType());
@@ -64,10 +58,10 @@ void CastToStructChecker::PreVisitCastExpr(CheckerContext &C,
if (!OrigPointeeTy->isRecordType()) {
if (ExplodedNode *N = C.generateNode()) {
if (!BT)
- BT = new BuiltinBug("Cast from non-struct type to struct type",
+ BT.reset(new BuiltinBug("Cast from non-struct type to struct type",
"Casting a non-structure type to a structure type "
"and accessing a field can lead to memory access "
- "errors or data corruption.");
+ "errors or data corruption."));
RangedBugReport *R = new RangedBugReport(*BT,BT->getDescription(), N);
R->addRange(CE->getSourceRange());
C.EmitReport(R);
@@ -75,10 +69,6 @@ void CastToStructChecker::PreVisitCastExpr(CheckerContext &C,
}
}
-static void RegisterCastToStructChecker(ExprEngine &Eng) {
- Eng.registerCheck(new CastToStructChecker());
-}
-
void ento::registerCastToStructChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterCastToStructChecker);
+ mgr.registerChecker<CastToStructChecker>();
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Checkers.td b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Checkers.td
index 1dc7486..894b961 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Checkers.td
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Checkers.td
@@ -71,16 +71,16 @@ def ObjCUnusedIvarsChecker : Checker<"UnusedIvars">,
HelpText<"Warn about private ivars that are never used">,
DescFile<"ObjCUnusedIVarsChecker.cpp">;
-}
+} // end "cocoa"
-def StackAddrLeakChecker : Checker<"StackAddrLeak">,
+def StackAddrEscapeChecker : Checker<"StackAddrEscape">,
InPackage<Core>,
- HelpText<"Check that addresses to stack memory are not leaked outside the function">,
- DescFile<"StackAddrLeakChecker.cpp">;
+ HelpText<"Check that addresses to stack memory do not escape the function">,
+ DescFile<"StackAddrEscapeChecker.cpp">;
def DeadStoresChecker : Checker<"DeadStores">,
InPackage<Core>,
- HelpText<"Check for stores to dead variables">,
+ HelpText<"Check for values stored to a variables that are never read afterwards">,
DescFile<"DeadStoresChecker.cpp">;
def UnixAPIChecker : Checker<"API">,
@@ -90,12 +90,12 @@ def UnixAPIChecker : Checker<"API">,
def MacOSXAPIChecker : Checker<"API">,
InPackage<MacOSX>,
- HelpText<"Check calls to various MacOSXAPIChecker">,
+ HelpText<"Check for proper uses of various Mac OS X APIs">,
DescFile<"MacOSXAPIChecker.cpp">;
def CFNumberCreateChecker : Checker<"CFNumber">,
InPackage<MacOSX>,
- HelpText<"Check for CFNumberCreate">,
+ HelpText<"Check for proper uses of CFNumberCreate">,
DescFile<"BasicObjCFoundationChecks.cpp">;
def CFRetainReleaseChecker : Checker<"CFRetainRelease">,
@@ -137,7 +137,8 @@ def CStringChecker : Checker<"CString">,
def UnreachableCodeChecker : Checker<"UnreachableCode">,
InPackage<CoreExperimental>,
HelpText<"Check unreachable code">,
- DescFile<"UnreachableCodeChecker.cpp">;
+ DescFile<"UnreachableCodeChecker.cpp">,
+ Hidden; // Must be specified explicitly in order to run.
def IdempotentOperationChecker : Checker<"IdempotentOps">,
InPackage<CoreExperimental>,
@@ -174,6 +175,21 @@ def SecuritySyntaxChecker : Checker<"SecuritySyntactic">,
HelpText<"Perform quick security checks that require no data flow">,
DescFile<"CheckSecuritySyntaxOnly.cpp">;
+def ReturnPointerRangeChecker : Checker<"ReturnPtrRange">,
+ InPackage<CoreExperimental>,
+ HelpText<"Check for an out-of-bound pointer being returned to callers">,
+ DescFile<"ReturnPointerRangeChecker.cpp">;
+
+def ArrayBoundChecker : Checker<"ArrayBound">,
+ InPackage<CoreExperimental>,
+ HelpText<"Check for an out-of-bound pointer being returned to callers">,
+ DescFile<"ArrayBoundChecker.cpp">;
+
+def CastSizeChecker : Checker<"CastSize">,
+ InPackage<CoreExperimental>,
+ HelpText<"Check when casting a malloc'ed type T, whether the size is a multiple of the size of T">,
+ DescFile<"CastSizeChecker.cpp">;
+
def ObjCDeallocChecker : Checker<"Dealloc">,
InPackage<CocoaExperimental>,
HelpText<"Warn about Objective-C classes that lack a correct implementation of -dealloc">,
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
index 36e76d0..b6eef6d 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
@@ -12,9 +12,10 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
@@ -37,38 +38,30 @@ bool isRootChanged(intptr_t k) { return k == ROOT_CHANGED; }
// ROOT_CHANGED<--chdir(..)-- JAIL_ENTERED<--chdir(..)--
// | |
// bug<--foo()-- JAIL_ENTERED<--foo()--
-class ChrootChecker : public CheckerVisitor<ChrootChecker> {
- IdentifierInfo *II_chroot, *II_chdir;
+class ChrootChecker : public CheckerV2<eval::Call, check::PreStmt<CallExpr> > {
+ mutable IdentifierInfo *II_chroot, *II_chdir;
// This bug refers to possibly break out of a chroot() jail.
- BuiltinBug *BT_BreakJail;
+ mutable llvm::OwningPtr<BuiltinBug> BT_BreakJail;
public:
- ChrootChecker() : II_chroot(0), II_chdir(0), BT_BreakJail(0) {}
+ ChrootChecker() : II_chroot(0), II_chdir(0) {}
static void *getTag() {
static int x;
return &x;
}
- virtual bool evalCallExpr(CheckerContext &C, const CallExpr *CE);
- virtual void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
+ bool evalCall(const CallExpr *CE, CheckerContext &C) const;
+ void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
private:
- void Chroot(CheckerContext &C, const CallExpr *CE);
- void Chdir(CheckerContext &C, const CallExpr *CE);
+ void Chroot(CheckerContext &C, const CallExpr *CE) const;
+ void Chdir(CheckerContext &C, const CallExpr *CE) const;
};
} // end anonymous namespace
-static void RegisterChrootChecker(ExprEngine &Eng) {
- Eng.registerCheck(new ChrootChecker());
-}
-
-void ento::registerChrootChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterChrootChecker);
-}
-
-bool ChrootChecker::evalCallExpr(CheckerContext &C, const CallExpr *CE) {
+bool ChrootChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
const GRState *state = C.getState();
const Expr *Callee = CE->getCallee();
SVal L = state->getSVal(Callee);
@@ -94,7 +87,7 @@ bool ChrootChecker::evalCallExpr(CheckerContext &C, const CallExpr *CE) {
return false;
}
-void ChrootChecker::Chroot(CheckerContext &C, const CallExpr *CE) {
+void ChrootChecker::Chroot(CheckerContext &C, const CallExpr *CE) const {
const GRState *state = C.getState();
GRStateManager &Mgr = state->getStateManager();
@@ -104,7 +97,7 @@ void ChrootChecker::Chroot(CheckerContext &C, const CallExpr *CE) {
C.addTransition(state);
}
-void ChrootChecker::Chdir(CheckerContext &C, const CallExpr *CE) {
+void ChrootChecker::Chdir(CheckerContext &C, const CallExpr *CE) const {
const GRState *state = C.getState();
GRStateManager &Mgr = state->getStateManager();
@@ -131,7 +124,7 @@ void ChrootChecker::Chdir(CheckerContext &C, const CallExpr *CE) {
}
// Check the jail state before any function call except chroot and chdir().
-void ChrootChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
+void ChrootChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const {
const GRState *state = C.getState();
const Expr *Callee = CE->getCallee();
SVal L = state->getSVal(Callee);
@@ -155,9 +148,9 @@ void ChrootChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
if (isRootChanged((intptr_t) *k))
if (ExplodedNode *N = C.generateNode()) {
if (!BT_BreakJail)
- BT_BreakJail = new BuiltinBug("Break out of jail",
+ BT_BreakJail.reset(new BuiltinBug("Break out of jail",
"No call of chdir(\"/\") immediately "
- "after chroot");
+ "after chroot"));
BugReport *R = new BugReport(*BT_BreakJail,
BT_BreakJail->getDescription(), N);
C.EmitReport(R);
@@ -165,3 +158,7 @@ void ChrootChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
return;
}
+
+void ento::registerChrootChecker(CheckerManager &mgr) {
+ mgr.registerChecker<ChrootChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp
index 94f200f..5c0c950 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp
@@ -16,7 +16,9 @@
#include "ClangSACheckers.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/CheckerProvider.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/DenseSet.h"
+#include "map"
using namespace clang;
using namespace ento;
@@ -28,6 +30,7 @@ class ClangSACheckerProvider : public CheckerProvider {
public:
virtual void registerCheckers(CheckerManager &checkerMgr,
CheckerOptInfo *checkOpts, unsigned numCheckOpts);
+ virtual void printHelp(llvm::raw_ostream &OS);
};
}
@@ -41,6 +44,7 @@ namespace {
struct StaticCheckerInfoRec {
const char *FullName;
void (*RegFunc)(CheckerManager &mgr);
+ const char *HelpText;
bool Hidden;
};
@@ -49,13 +53,16 @@ struct StaticCheckerInfoRec {
static const StaticCheckerInfoRec StaticCheckerInfo[] = {
#define GET_CHECKERS
#define CHECKER(FULLNAME,CLASS,DESCFILE,HELPTEXT,HIDDEN) \
- { FULLNAME, register##CLASS, HIDDEN },
+ { FULLNAME, register##CLASS, HELPTEXT, HIDDEN },
#include "Checkers.inc"
- { 0, 0, 0}
+ { 0, 0, 0, 0}
#undef CHECKER
#undef GET_CHECKERS
};
+static const unsigned NumCheckers = sizeof(StaticCheckerInfo)
+ / sizeof(StaticCheckerInfoRec) - 1;
+
namespace {
struct CheckNameOption {
@@ -104,9 +111,10 @@ static void collectCheckers(const CheckNameOption *checkName,
// Enable/disable all subgroups along with this one.
if (const short *subGroups = checkName->SubGroups) {
- for (; *subGroups != -1; ++subGroups)
- collectCheckers(&CheckNameTable[*subGroups], enable, checkers,
- collectHidden && checkName->Hidden);
+ for (; *subGroups != -1; ++subGroups) {
+ const CheckNameOption *sub = &CheckNameTable[*subGroups];
+ collectCheckers(sub, enable, checkers, collectHidden && !sub->Hidden);
+ }
}
}
@@ -135,3 +143,41 @@ void ClangSACheckerProvider::registerCheckers(CheckerManager &checkerMgr,
(*I)->RegFunc(checkerMgr);
}
}
+
+typedef std::map<std::string, const StaticCheckerInfoRec *> SortedCheckers;
+
+static void printCheckerOption(llvm::raw_ostream &OS,SortedCheckers &checkers) {
+ // Find the maximum option length.
+ unsigned OptionFieldWidth = 0;
+ for (SortedCheckers::iterator
+ I = checkers.begin(), E = checkers.end(); I != E; ++I) {
+ // Limit the amount of padding we are willing to give up for alignment.
+ unsigned Length = strlen(I->second->FullName);
+ if (Length <= 30)
+ OptionFieldWidth = std::max(OptionFieldWidth, Length);
+ }
+
+ const unsigned InitialPad = 2;
+ for (SortedCheckers::iterator
+ I = checkers.begin(), E = checkers.end(); I != E; ++I) {
+ const std::string &Option = I->first;
+ int Pad = OptionFieldWidth - int(Option.size());
+ OS.indent(InitialPad) << Option;
+
+ // Break on long option names.
+ if (Pad < 0) {
+ OS << "\n";
+ Pad = OptionFieldWidth + InitialPad;
+ }
+ OS.indent(Pad + 1) << I->second->HelpText << '\n';
+ }
+}
+
+void ClangSACheckerProvider::printHelp(llvm::raw_ostream &OS) {
+ // Sort checkers according to their full name.
+ SortedCheckers checkers;
+ for (unsigned i = 0; i != NumCheckers; ++i)
+ checkers[StaticCheckerInfo[i].FullName] = &StaticCheckerInfo[i];
+
+ printCheckerOption(OS, checkers);
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExperimentalChecks.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExperimentalChecks.cpp
index d9bb480..990ba1c0 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExperimentalChecks.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExperimentalChecks.cpp
@@ -24,14 +24,3 @@ void ento::RegisterExperimentalChecks(ExprEngine &Eng) {
// within ExprEngine.
RegisterMallocChecker(Eng); // ArrayBoundChecker depends on this.
}
-
-void ento::RegisterExperimentalInternalChecks(ExprEngine &Eng) {
- // These are internal checks that should eventually migrate to
- // RegisterInternalChecks() once they have been further tested.
-
- // Note that this must be registered after ReturnStackAddresEngsChecker.
- RegisterReturnPointerRangeChecker(Eng);
-
- RegisterArrayBoundChecker(Eng);
- RegisterCastSizeChecker(Eng);
-}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
index ab8d564..c1b1e65 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
@@ -92,12 +92,13 @@ void ExprEngine::CheckerVisit(const Stmt *S, ExplodedNodeSet &Dst,
}
if (CO->empty()) {
- // If there are no checkers, return early without doing any
- // more work.
- Dst.insert(Src);
+ // If there are no checkers, just delegate to the checker manager.
+ getCheckerManager().runCheckersForStmt(Kind == PreVisitStmtCallback,
+ Dst, Src, S, *this);
return;
}
+ ExplodedNodeSet CheckersV1Dst;
ExplodedNodeSet Tmp;
ExplodedNodeSet *PrevSet = &Src;
unsigned checkersEvaluated = 0;
@@ -108,7 +109,7 @@ void ExprEngine::CheckerVisit(const Stmt *S, ExplodedNodeSet &Dst,
break;
ExplodedNodeSet *CurrSet = 0;
if (I+1 == E)
- CurrSet = &Dst;
+ CurrSet = &CheckersV1Dst;
else {
CurrSet = (PrevSet == &Tmp) ? &Src : &Tmp;
CurrSet->clear();
@@ -144,6 +145,9 @@ void ExprEngine::CheckerVisit(const Stmt *S, ExplodedNodeSet &Dst,
// Don't autotransition. The CheckerContext objects should do this
// automatically.
+
+ getCheckerManager().runCheckersForStmt(Kind == PreVisitStmtCallback,
+ Dst, CheckersV1Dst, S, *this);
}
void ExprEngine::CheckerVisitObjCMessage(const ObjCMessage &msg,
@@ -152,10 +156,12 @@ void ExprEngine::CheckerVisitObjCMessage(const ObjCMessage &msg,
bool isPrevisit) {
if (Checkers.empty()) {
- Dst.insert(Src);
+ getCheckerManager().runCheckersForObjCMessage(isPrevisit, Dst, Src, msg,
+ *this);
return;
}
+ ExplodedNodeSet CheckersV1Dst;
ExplodedNodeSet Tmp;
ExplodedNodeSet *PrevSet = &Src;
@@ -163,7 +169,7 @@ void ExprEngine::CheckerVisitObjCMessage(const ObjCMessage &msg,
{
ExplodedNodeSet *CurrSet = 0;
if (I+1 == E)
- CurrSet = &Dst;
+ CurrSet = &CheckersV1Dst;
else {
CurrSet = (PrevSet == &Tmp) ? &Src : &Tmp;
CurrSet->clear();
@@ -181,8 +187,8 @@ void ExprEngine::CheckerVisitObjCMessage(const ObjCMessage &msg,
PrevSet = CurrSet;
}
- // Don't autotransition. The CheckerContext objects should do this
- // automatically.
+ getCheckerManager().runCheckersForObjCMessage(isPrevisit, Dst, CheckersV1Dst,
+ msg, *this);
}
void ExprEngine::CheckerEvalNilReceiver(const ObjCMessage &msg,
@@ -232,11 +238,25 @@ bool ExprEngine::CheckerEvalCall(const CallExpr *CE,
DstTmp.clear();
}
- if (evaluated)
+ if (evaluated) {
Dst.insert(DstTmp);
- else
- Dst.insert(Pred);
+ return evaluated;
+ }
+
+ class DefaultEval : public GraphExpander {
+ bool &Evaluated;
+ public:
+ DefaultEval(bool &evaluated) : Evaluated(evaluated) { }
+ virtual void expandGraph(ExplodedNodeSet &Dst, ExplodedNode *Pred) {
+ Evaluated = false;
+ Dst.insert(Pred);
+ }
+ };
+ evaluated = true;
+ DefaultEval defaultEval(evaluated);
+ getCheckerManager().runCheckersForEvalCall(Dst, Pred, CE, *this,
+ &defaultEval);
return evaluated;
}
@@ -335,8 +355,6 @@ ExprEngine::ExprEngine(AnalysisManager &mgr, TransferFuncs *tf)
// FIXME: Eventually remove the TF object entirely.
TF->RegisterChecks(*this);
TF->RegisterPrinters(getStateManager().Printers);
-
- mgr.getCheckerManager()->registerCheckersToEngine(*this);
if (mgr.shouldEagerlyTrimExplodedGraph()) {
// Enable eager node reclaimation when constructing the ExplodedGraph.
@@ -495,7 +513,7 @@ bool ExprEngine::wantsRegionChangeUpdate(const GRState* state) {
return true;
}
- return false;
+ return getCheckerManager().wantsRegionChangeUpdate(state);
}
const GRState *
@@ -523,9 +541,9 @@ ExprEngine::processRegionChanges(const GRState *state,
CO = CO_Ref;
}
- // If there are no checkers, just return the state as is.
+ // If there are no checkers, just delegate to the checker manager.
if (CO->empty())
- return state;
+ return getCheckerManager().runCheckersForRegionChanges(state, Begin, End);
for (CheckersOrdered::iterator I = CO->begin(), E = CO->end(); I != E; ++I) {
// If any checker declares the state infeasible (or if it starts that way),
@@ -548,7 +566,7 @@ ExprEngine::processRegionChanges(const GRState *state,
if (NewCO.get())
CO_Ref = NewCO.take();
- return state;
+ return getCheckerManager().runCheckersForRegionChanges(state, Begin, End);
}
void ExprEngine::processEndWorklist(bool hasWorkRemaining) {
@@ -556,6 +574,7 @@ void ExprEngine::processEndWorklist(bool hasWorkRemaining) {
I != E; ++I) {
I->second->VisitEndAnalysis(G, BR, *this);
}
+ getCheckerManager().runCheckersForEndAnalysis(G, BR, *this);
}
void ExprEngine::processCFGElement(const CFGElement E,
@@ -603,6 +622,8 @@ void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder) {
checker->MarkLiveSymbols(St, SymReaper);
}
+ getCheckerManager().runCheckersForLiveSymbols(St, SymReaper);
+
const StackFrameContext *SFC = LC->getCurrentStackFrame();
CleanedState = StateMgr.removeDeadBindings(St, SFC, SymReaper);
} else {
@@ -626,8 +647,9 @@ void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder) {
getTF().evalDeadSymbols(Tmp2, *this, *Builder, EntryNode,
CleanedState, SymReaper);
+ ExplodedNodeSet checkersV1Tmp;
if (Checkers.empty())
- Tmp.insert(Tmp2);
+ checkersV1Tmp.insert(Tmp2);
else {
ExplodedNodeSet Tmp3;
ExplodedNodeSet *SrcSet = &Tmp2;
@@ -635,7 +657,7 @@ void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder) {
I != E; ++I) {
ExplodedNodeSet *DstSet = 0;
if (I+1 == E)
- DstSet = &Tmp;
+ DstSet = &checkersV1Tmp;
else {
DstSet = (SrcSet == &Tmp2) ? &Tmp3 : &Tmp2;
DstSet->clear();
@@ -651,6 +673,9 @@ void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder) {
}
}
+ getCheckerManager().runCheckersForDeadSymbols(Tmp, checkersV1Tmp,
+ SymReaper, currentStmt, *this);
+
if (!Builder->BuildSinks && !Builder->hasGeneratedNode)
Tmp.Add(EntryNode);
}
@@ -1419,8 +1444,10 @@ void ExprEngine::processEndOfFunction(EndOfFunctionNodeBuilder& builder) {
for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E;++I){
void *tag = I->first;
Checker *checker = I->second;
- checker->evalEndPath(builder, tag, *this);
+ EndOfFunctionNodeBuilder B = builder.withCheckerTag(tag);
+ checker->evalEndPath(B, tag, *this);
}
+ getCheckerManager().runCheckersForEndPath(builder, *this);
}
/// ProcessSwitch - Called by CoreEngine. Used to generate successor
@@ -1923,20 +1950,35 @@ void ExprEngine::evalLocation(ExplodedNodeSet &Dst, const Stmt *S,
const GRState* state, SVal location,
const void *tag, bool isLoad) {
// Early checks for performance reason.
- if (location.isUnknown() || Checkers.empty()) {
+ if (location.isUnknown()) {
Dst.Add(Pred);
return;
}
- ExplodedNodeSet Src, Tmp;
+ if (Checkers.empty()) {
+ ExplodedNodeSet Src;
+ if (Builder->GetState(Pred) == state) {
+ Src.Add(Pred);
+ } else {
+ // Associate this new state with an ExplodedNode.
+ Src.Add(Builder->generateNode(S, state, Pred));
+ }
+ getCheckerManager().runCheckersForLocation(Dst, Src, location, isLoad, S,
+ *this);
+ return;
+ }
+
+ ExplodedNodeSet Src;
Src.Add(Pred);
+ ExplodedNodeSet CheckersV1Dst;
+ ExplodedNodeSet Tmp;
ExplodedNodeSet *PrevSet = &Src;
for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E; ++I)
{
ExplodedNodeSet *CurrSet = 0;
if (I+1 == E)
- CurrSet = &Dst;
+ CurrSet = &CheckersV1Dst;
else {
CurrSet = (PrevSet == &Tmp) ? &Src : &Tmp;
CurrSet->clear();
@@ -1957,6 +1999,9 @@ void ExprEngine::evalLocation(ExplodedNodeSet &Dst, const Stmt *S,
// Update which NodeSet is the current one.
PrevSet = CurrSet;
}
+
+ getCheckerManager().runCheckersForLocation(Dst, CheckersV1Dst, location,
+ isLoad, S, *this);
}
bool ExprEngine::InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE,
@@ -3613,14 +3658,12 @@ void ExprEngine::ViewGraph(bool trim) {
const_cast<BugType*>(*I)->FlushReports(BR);
// Iterate through the reports and get their nodes.
- for (BugReporter::iterator I=BR.begin(), E=BR.end(); I!=E; ++I) {
- for (BugType::const_iterator I2=(*I)->begin(), E2=(*I)->end();
- I2!=E2; ++I2) {
- const BugReportEquivClass& EQ = *I2;
- const BugReport &R = **EQ.begin();
- ExplodedNode *N = const_cast<ExplodedNode*>(R.getErrorNode());
- if (N) Src.push_back(N);
- }
+ for (BugReporter::EQClasses_iterator
+ EI = BR.EQClasses_begin(), EE = BR.EQClasses_end(); EI != EE; ++EI) {
+ BugReportEquivClass& EQ = *EI;
+ const BugReport &R = **EQ.begin();
+ ExplodedNode *N = const_cast<ExplodedNode*>(R.getErrorNode());
+ if (N) Src.push_back(N);
}
ViewGraph(&Src[0], &Src[0]+Src.size());
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
index fe628a2..d7b27b5 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
@@ -14,31 +14,26 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
using namespace clang;
using namespace ento;
namespace {
class FixedAddressChecker
- : public CheckerVisitor<FixedAddressChecker> {
- BuiltinBug *BT;
+ : public CheckerV2< check::PreStmt<BinaryOperator> > {
+ mutable llvm::OwningPtr<BuiltinBug> BT;
+
public:
- FixedAddressChecker() : BT(0) {}
- static void *getTag();
- void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
+ void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const;
};
}
-void *FixedAddressChecker::getTag() {
- static int x;
- return &x;
-}
-
-void FixedAddressChecker::PreVisitBinaryOperator(CheckerContext &C,
- const BinaryOperator *B) {
+void FixedAddressChecker::checkPreStmt(const BinaryOperator *B,
+ CheckerContext &C) const {
// Using a fixed address is not portable because that address will probably
// not be valid in all environments or platforms.
@@ -58,20 +53,16 @@ void FixedAddressChecker::PreVisitBinaryOperator(CheckerContext &C,
if (ExplodedNode *N = C.generateNode()) {
if (!BT)
- BT = new BuiltinBug("Use fixed address",
+ BT.reset(new BuiltinBug("Use fixed address",
"Using a fixed address is not portable because that "
"address will probably not be valid in all "
- "environments or platforms.");
+ "environments or platforms."));
RangedBugReport *R = new RangedBugReport(*BT, BT->getDescription(), N);
R->addRange(B->getRHS()->getSourceRange());
C.EmitReport(R);
}
}
-static void RegisterFixedAddressChecker(ExprEngine &Eng) {
- Eng.registerCheck(new FixedAddressChecker());
-}
-
void ento::registerFixedAddressChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterFixedAddressChecker);
+ mgr.registerChecker<FixedAddressChecker>();
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp
index f49b125..83d9668 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp
@@ -45,11 +45,13 @@
#include "ClangSACheckers.h"
#include "clang/Analysis/CFGStmtMap.h"
#include "clang/Analysis/Analyses/PseudoConstantAnalysis.h"
+#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "clang/AST/Stmt.h"
@@ -64,29 +66,29 @@ using namespace ento;
namespace {
class IdempotentOperationChecker
- : public CheckerVisitor<IdempotentOperationChecker> {
+ : public CheckerV2<check::PreStmt<BinaryOperator>,
+ check::PostStmt<BinaryOperator>,
+ check::EndAnalysis> {
public:
- static void *getTag();
- void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
- void PostVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
- void VisitEndAnalysis(ExplodedGraph &G, BugReporter &B, ExprEngine &Eng);
+ void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const;
+ void checkPostStmt(const BinaryOperator *B, CheckerContext &C) const;
+ void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const;
private:
// Our assumption about a particular operation.
enum Assumption { Possible = 0, Impossible, Equal, LHSis1, RHSis1, LHSis0,
RHSis0 };
- void UpdateAssumption(Assumption &A, const Assumption &New);
+ static void UpdateAssumption(Assumption &A, const Assumption &New);
// False positive reduction methods
static bool isSelfAssign(const Expr *LHS, const Expr *RHS);
static bool isUnused(const Expr *E, AnalysisContext *AC);
static bool isTruncationExtensionAssignment(const Expr *LHS,
const Expr *RHS);
- bool pathWasCompletelyAnalyzed(const CFG *cfg,
- const CFGBlock *CB,
- const CFGStmtMap *CBM,
- const CoreEngine &CE);
+ static bool pathWasCompletelyAnalyzed(AnalysisContext *AC,
+ const CFGBlock *CB,
+ const CoreEngine &CE);
static bool CanVary(const Expr *Ex,
AnalysisContext *AC);
static bool isConstantOrPseudoConstant(const DeclRefExpr *DR,
@@ -104,46 +106,12 @@ private:
};
typedef llvm::DenseMap<const BinaryOperator *, BinaryOperatorData>
AssumptionMap;
- AssumptionMap hash;
-
- // A class that performs reachability queries for CFGBlocks. Several internal
- // checks in this checker require reachability information. The requests all
- // tend to have a common destination, so we lazily do a predecessor search
- // from the destination node and cache the results to prevent work
- // duplication.
- class CFGReachabilityAnalysis {
- typedef llvm::BitVector ReachableSet;
- typedef llvm::DenseMap<unsigned, ReachableSet> ReachableMap;
- ReachableSet analyzed;
- ReachableMap reachable;
- public:
- CFGReachabilityAnalysis(const CFG &cfg)
- : analyzed(cfg.getNumBlockIDs(), false) {}
-
- inline bool isReachable(const CFGBlock *Src, const CFGBlock *Dst);
- private:
- void MapReachability(const CFGBlock *Dst);
- };
- llvm::OwningPtr<CFGReachabilityAnalysis> CRA;
+ mutable AssumptionMap hash;
};
}
-void *IdempotentOperationChecker::getTag() {
- static int x = 0;
- return &x;
-}
-
-static void RegisterIdempotentOperationChecker(ExprEngine &Eng) {
- Eng.registerCheck(new IdempotentOperationChecker());
-}
-
-void ento::registerIdempotentOperationChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterIdempotentOperationChecker);
-}
-
-void IdempotentOperationChecker::PreVisitBinaryOperator(
- CheckerContext &C,
- const BinaryOperator *B) {
+void IdempotentOperationChecker::checkPreStmt(const BinaryOperator *B,
+ CheckerContext &C) const {
// Find or create an entry in the hash for this BinaryOperator instance.
// If we haven't done a lookup before, it will get default initialized to
// 'Possible'. At this stage we do not store the ExplodedNode, as it has not
@@ -359,9 +327,8 @@ void IdempotentOperationChecker::PreVisitBinaryOperator(
// At the post visit stage, the predecessor ExplodedNode will be the
// BinaryOperator that was just created. We use this hook to collect the
// ExplodedNode.
-void IdempotentOperationChecker::PostVisitBinaryOperator(
- CheckerContext &C,
- const BinaryOperator *B) {
+void IdempotentOperationChecker::checkPostStmt(const BinaryOperator *B,
+ CheckerContext &C) const {
// Add the ExplodedNode we just visited
BinaryOperatorData &Data = hash[B];
@@ -376,9 +343,9 @@ void IdempotentOperationChecker::PostVisitBinaryOperator(
Data.explodedNodes.Add(C.getPredecessor());
}
-void IdempotentOperationChecker::VisitEndAnalysis(ExplodedGraph &G,
+void IdempotentOperationChecker::checkEndAnalysis(ExplodedGraph &G,
BugReporter &BR,
- ExprEngine &Eng) {
+ ExprEngine &Eng) const {
BugType *BT = new BugType("Idempotent operation", "Dead code");
// Iterate over the hash to see if we have any paths with definite
// idempotent operations.
@@ -397,16 +364,11 @@ void IdempotentOperationChecker::VisitEndAnalysis(ExplodedGraph &G,
// If the analyzer did not finish, check to see if we can still emit this
// warning
if (Eng.hasWorkRemaining()) {
- const CFGStmtMap *CBM = CFGStmtMap::Build(AC->getCFG(),
- &AC->getParentMap());
-
// If we can trace back
- if (!pathWasCompletelyAnalyzed(AC->getCFG(),
- CBM->getBlock(B), CBM,
+ if (!pathWasCompletelyAnalyzed(AC,
+ AC->getCFGStmtMap()->getBlock(B),
Eng.getCoreEngine()))
continue;
-
- delete CBM;
}
// Select the error message and SourceRanges to report.
@@ -464,6 +426,8 @@ void IdempotentOperationChecker::VisitEndAnalysis(ExplodedGraph &G,
BR.EmitReport(report);
}
}
+
+ hash.clear();
}
// Updates the current assumption given the new assumption
@@ -564,13 +528,11 @@ bool IdempotentOperationChecker::isTruncationExtensionAssignment(
// Returns false if a path to this block was not completely analyzed, or true
// otherwise.
bool
-IdempotentOperationChecker::pathWasCompletelyAnalyzed(const CFG *cfg,
+IdempotentOperationChecker::pathWasCompletelyAnalyzed(AnalysisContext *AC,
const CFGBlock *CB,
- const CFGStmtMap *CBM,
const CoreEngine &CE) {
- if (!CRA.get())
- CRA.reset(new CFGReachabilityAnalysis(*cfg));
+ CFGReachabilityAnalysis *CRA = AC->getCFGReachablityAnalysis();
// Test for reachability from any aborted blocks to this block
typedef CoreEngine::BlocksAborted::const_iterator AbortedIterator;
@@ -621,14 +583,14 @@ IdempotentOperationChecker::pathWasCompletelyAnalyzed(const CFG *cfg,
return CRA.isReachable(B, TargetBlock);
}
};
- VisitWL visitWL(CBM, CB, *CRA.get());
+ VisitWL visitWL(AC->getCFGStmtMap(), CB, *CRA);
// Were there any items in the worklist that could potentially reach
// this block?
if (CE.getWorkList()->visitItemsInWorkList(visitWL))
return false;
// Verify that this block is reachable from the entry block
- if (!CRA->isReachable(&cfg->getEntry(), CB))
+ if (!CRA->isReachable(&AC->getCFG()->getEntry(), CB))
return false;
// If we get to this point, there is no connection to the entry block or an
@@ -766,57 +728,7 @@ bool IdempotentOperationChecker::containsNonLocalVarDecl(const Stmt *S) {
return false;
}
-bool IdempotentOperationChecker::CFGReachabilityAnalysis::isReachable(
- const CFGBlock *Src,
- const CFGBlock *Dst) {
- const unsigned DstBlockID = Dst->getBlockID();
- // If we haven't analyzed the destination node, run the analysis now
- if (!analyzed[DstBlockID]) {
- MapReachability(Dst);
- analyzed[DstBlockID] = true;
- }
-
- // Return the cached result
- return reachable[DstBlockID][Src->getBlockID()];
-}
-
-// Maps reachability to a common node by walking the predecessors of the
-// destination node.
-void IdempotentOperationChecker::CFGReachabilityAnalysis::MapReachability(
- const CFGBlock *Dst) {
-
- llvm::SmallVector<const CFGBlock *, 11> worklist;
- llvm::BitVector visited(analyzed.size());
-
- ReachableSet &DstReachability = reachable[Dst->getBlockID()];
- DstReachability.resize(analyzed.size(), false);
-
- // Start searching from the destination node, since we commonly will perform
- // multiple queries relating to a destination node.
- worklist.push_back(Dst);
- bool firstRun = true;
-
- while (!worklist.empty()) {
- const CFGBlock *block = worklist.back();
- worklist.pop_back();
-
- if (visited[block->getBlockID()])
- continue;
- visited[block->getBlockID()] = true;
-
- // Update reachability information for this node -> Dst
- if (!firstRun) {
- // Don't insert Dst -> Dst unless it was a predecessor of itself
- DstReachability[block->getBlockID()] = true;
- }
- else
- firstRun = false;
-
- // Add the predecessors to the worklist.
- for (CFGBlock::const_pred_iterator i = block->pred_begin(),
- e = block->pred_end(); i != e; ++i) {
- worklist.push_back(*i);
- }
- }
+void ento::registerIdempotentOperationChecker(CheckerManager &mgr) {
+ mgr.registerChecker<IdempotentOperationChecker>();
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/InternalChecks.h b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/InternalChecks.h
index e855386..e7c38ee 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/InternalChecks.h
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/InternalChecks.h
@@ -23,16 +23,13 @@ class ExprEngine;
// Foundational checks that handle basic semantics.
void RegisterAdjustedReturnValueChecker(ExprEngine &Eng);
-void RegisterArrayBoundChecker(ExprEngine &Eng);
void RegisterArrayBoundCheckerV2(ExprEngine &Eng);
void RegisterAttrNonNullChecker(ExprEngine &Eng);
void RegisterBuiltinFunctionChecker(ExprEngine &Eng);
void RegisterCallAndMessageChecker(ExprEngine &Eng);
-void RegisterCastSizeChecker(ExprEngine &Eng);
void RegisterDereferenceChecker(ExprEngine &Eng);
void RegisterDivZeroChecker(ExprEngine &Eng);
void RegisterNoReturnFunctionChecker(ExprEngine &Eng);
-void RegisterReturnPointerRangeChecker(ExprEngine &Eng);
void RegisterReturnUndefChecker(ExprEngine &Eng);
void RegisterUndefBranchChecker(ExprEngine &Eng);
void RegisterUndefCapturedBlockVarChecker(ExprEngine &Eng);
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
index 358be12..d70c65a 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
@@ -16,11 +16,12 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
-#include "clang/Basic/TargetInfo.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
+#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/raw_ostream.h"
@@ -29,31 +30,26 @@ using namespace clang;
using namespace ento;
namespace {
-class MacOSXAPIChecker : public CheckerVisitor<MacOSXAPIChecker> {
+class MacOSXAPIChecker : public CheckerV2< check::PreStmt<CallExpr> > {
enum SubChecks {
DispatchOnce = 0,
DispatchOnceF,
NumChecks
};
- BugType *BTypes[NumChecks];
+ mutable BugType *BTypes[NumChecks];
public:
MacOSXAPIChecker() { memset(BTypes, 0, sizeof(*BTypes) * NumChecks); }
- static void *getTag() { static unsigned tag = 0; return &tag; }
+ ~MacOSXAPIChecker() {
+ for (unsigned i=0; i != NumChecks; ++i)
+ delete BTypes[i];
+ }
- void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
+ void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
};
} //end anonymous namespace
-static void RegisterMacOSXAPIChecker(ExprEngine &Eng) {
- Eng.registerCheck(new MacOSXAPIChecker());
-}
-
-void ento::registerMacOSXAPIChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterMacOSXAPIChecker);
-}
-
//===----------------------------------------------------------------------===//
// dispatch_once and dispatch_once_f
//===----------------------------------------------------------------------===//
@@ -121,7 +117,8 @@ namespace {
};
} // end anonymous namespace
-void MacOSXAPIChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
+void MacOSXAPIChecker::checkPreStmt(const CallExpr *CE,
+ CheckerContext &C) const {
// FIXME: Mostly copy and paste from UnixAPIChecker. Should refactor.
const GRState *state = C.getState();
const Expr *Callee = CE->getCallee();
@@ -144,3 +141,11 @@ void MacOSXAPIChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
SC.run(C, CE, FI);
}
+
+//===----------------------------------------------------------------------===//
+// Registration.
+//===----------------------------------------------------------------------===//
+
+void ento::registerMacOSXAPIChecker(CheckerManager &mgr) {
+ mgr.registerChecker<MacOSXAPIChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index 9d3a887..794740a 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -599,7 +599,7 @@ void MallocChecker::evalEndPath(EndOfFunctionNodeBuilder &B, void *tag,
for (RegionStateTy::iterator I = M.begin(), E = M.end(); I != E; ++I) {
RefState RS = I->second;
if (RS.isAllocated()) {
- ExplodedNode *N = B.generateNode(state, tag, B.getPredecessor());
+ ExplodedNode *N = B.generateNode(state);
if (N) {
if (!BT_Leak)
BT_Leak = new BuiltinBug("Memory leak",
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp
index 9fb89d7..fed6a99 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp
@@ -16,10 +16,11 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Decl.h"
@@ -28,39 +29,18 @@ using namespace ento;
namespace {
class NSAutoreleasePoolChecker
- : public CheckerVisitor<NSAutoreleasePoolChecker> {
+ : public CheckerV2<check::PreObjCMessage> {
- Selector releaseS;
+ mutable Selector releaseS;
public:
- NSAutoreleasePoolChecker(Selector release_s) : releaseS(release_s) {}
-
- static void *getTag() {
- static int x = 0;
- return &x;
- }
-
- void preVisitObjCMessage(CheckerContext &C, ObjCMessage msg);
+ void checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const;
};
} // end anonymous namespace
-
-static void RegisterNSAutoreleasePoolChecker(ExprEngine &Eng) {
- ASTContext &Ctx = Eng.getContext();
- if (Ctx.getLangOptions().getGCMode() != LangOptions::NonGC) {
- Eng.registerCheck(new NSAutoreleasePoolChecker(GetNullarySelector("release",
- Ctx)));
- }
-}
-
-void ento::registerNSAutoreleasePoolChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterNSAutoreleasePoolChecker);
-}
-
-void
-NSAutoreleasePoolChecker::preVisitObjCMessage(CheckerContext &C,
- ObjCMessage msg) {
+void NSAutoreleasePoolChecker::checkPreObjCMessage(ObjCMessage msg,
+ CheckerContext &C) const {
const Expr *receiver = msg.getInstanceReceiver();
if (!receiver)
@@ -78,7 +58,9 @@ NSAutoreleasePoolChecker::preVisitObjCMessage(CheckerContext &C,
return;
if (!OD->getIdentifier()->getName().equals("NSAutoreleasePool"))
return;
-
+
+ if (releaseS.isNull())
+ releaseS = GetNullarySelector("release", C.getASTContext());
// Sending 'release' message?
if (msg.getSelector() != releaseS)
return;
@@ -90,3 +72,8 @@ NSAutoreleasePoolChecker::preVisitObjCMessage(CheckerContext &C,
"Use -drain instead of -release when using NSAutoreleasePool "
"and garbage collection", R.getBegin(), &R, 1);
}
+
+void ento::registerNSAutoreleasePoolChecker(CheckerManager &mgr) {
+ if (mgr.getLangOptions().getGCMode() != LangOptions::NonGC)
+ mgr.registerChecker<NSAutoreleasePoolChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
index 7d440ab..7746719 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
@@ -13,39 +13,29 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Checkers/DereferenceChecker.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
using namespace clang;
using namespace ento;
namespace {
-class ObjCAtSyncChecker : public CheckerVisitor<ObjCAtSyncChecker> {
- BuiltinBug *BT_null;
- BuiltinBug *BT_undef;
+class ObjCAtSyncChecker
+ : public CheckerV2< check::PreStmt<ObjCAtSynchronizedStmt> > {
+ mutable llvm::OwningPtr<BuiltinBug> BT_null;
+ mutable llvm::OwningPtr<BuiltinBug> BT_undef;
+
public:
- ObjCAtSyncChecker() : BT_null(0), BT_undef(0) {}
- static void *getTag() { static int tag = 0; return &tag; }
- void PreVisitObjCAtSynchronizedStmt(CheckerContext &C,
- const ObjCAtSynchronizedStmt *S);
+ void checkPreStmt(const ObjCAtSynchronizedStmt *S, CheckerContext &C) const;
};
} // end anonymous namespace
-static void RegisterObjCAtSyncChecker(ExprEngine &Eng) {
- // @synchronized is an Objective-C 2 feature.
- if (Eng.getContext().getLangOptions().ObjC2)
- Eng.registerCheck(new ObjCAtSyncChecker());
-}
-
-void ento::registerObjCAtSyncChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterObjCAtSyncChecker);
-}
-
-void ObjCAtSyncChecker::PreVisitObjCAtSynchronizedStmt(CheckerContext &C,
- const ObjCAtSynchronizedStmt *S) {
+void ObjCAtSyncChecker::checkPreStmt(const ObjCAtSynchronizedStmt *S,
+ CheckerContext &C) const {
const Expr *Ex = S->getSynchExpr();
const GRState *state = C.getState();
@@ -55,8 +45,8 @@ void ObjCAtSyncChecker::PreVisitObjCAtSynchronizedStmt(CheckerContext &C,
if (isa<UndefinedVal>(V)) {
if (ExplodedNode *N = C.generateSink()) {
if (!BT_undef)
- BT_undef = new BuiltinBug("Uninitialized value used as mutex "
- "for @synchronized");
+ BT_undef.reset(new BuiltinBug("Uninitialized value used as mutex "
+ "for @synchronized"));
EnhancedBugReport *report =
new EnhancedBugReport(*BT_undef, BT_undef->getDescription(), N);
report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, Ex);
@@ -78,8 +68,8 @@ void ObjCAtSyncChecker::PreVisitObjCAtSynchronizedStmt(CheckerContext &C,
// a null mutex just means no synchronization occurs.
if (ExplodedNode *N = C.generateNode(nullState)) {
if (!BT_null)
- BT_null = new BuiltinBug("Nil value used as mutex for @synchronized() "
- "(no synchronization will occur)");
+ BT_null.reset(new BuiltinBug("Nil value used as mutex for @synchronized() "
+ "(no synchronization will occur)"));
EnhancedBugReport *report =
new EnhancedBugReport(*BT_null, BT_null->getDescription(), N);
report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
@@ -98,3 +88,7 @@ void ObjCAtSyncChecker::PreVisitObjCAtSynchronizedStmt(CheckerContext &C,
C.addTransition(notNullState);
}
+void ento::registerObjCAtSyncChecker(CheckerManager &mgr) {
+ if (mgr.getLangOptions().ObjC2)
+ mgr.registerChecker<ObjCAtSyncChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
index 4f247ea..5f32bb8 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
@@ -47,8 +47,9 @@
// http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocAllocInit.html
#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
@@ -63,45 +64,23 @@ static bool isInitMessage(const ObjCMessage &msg);
static bool isSelfVar(SVal location, CheckerContext &C);
namespace {
-enum SelfFlagEnum {
- /// \brief No flag set.
- SelfFlag_None = 0x0,
- /// \brief Value came from 'self'.
- SelfFlag_Self = 0x1,
- /// \brief Value came from the result of an initializer (e.g. [super init]).
- SelfFlag_InitRes = 0x2
-};
-}
-
-namespace {
-class ObjCSelfInitChecker : public CheckerVisitor<ObjCSelfInitChecker> {
- /// \brief A call receiving a reference to 'self' invalidates the object that
- /// 'self' contains. This field keeps the "self flags" assigned to the 'self'
- /// object before the call and assign them to the new object that 'self'
- /// points to after the call.
- SelfFlagEnum preCallSelfFlags;
-
+class ObjCSelfInitChecker : public CheckerV2<
+ check::PostObjCMessage,
+ check::PostStmt<ObjCIvarRefExpr>,
+ check::PreStmt<ReturnStmt>,
+ check::PreStmt<CallExpr>,
+ check::PostStmt<CallExpr>,
+ check::Location > {
public:
- static void *getTag() { static int tag = 0; return &tag; }
- void postVisitObjCMessage(CheckerContext &C, ObjCMessage msg);
- void PostVisitObjCIvarRefExpr(CheckerContext &C, const ObjCIvarRefExpr *E);
- void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S);
- void PreVisitGenericCall(CheckerContext &C, const CallExpr *CE);
- void PostVisitGenericCall(CheckerContext &C, const CallExpr *CE);
- virtual void visitLocation(CheckerContext &C, const Stmt *S, SVal location,
- bool isLoad);
+ void checkPostObjCMessage(ObjCMessage msg, CheckerContext &C) const;
+ void checkPostStmt(const ObjCIvarRefExpr *E, CheckerContext &C) const;
+ void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
+ void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
+ void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
+ void checkLocation(SVal location, bool isLoad, CheckerContext &C) const;
};
} // end anonymous namespace
-static void RegisterObjCSelfInitChecker(ExprEngine &Eng) {
- if (Eng.getContext().getLangOptions().ObjC1)
- Eng.registerCheck(new ObjCSelfInitChecker());
-}
-
-void ento::registerObjCSelfInitChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterObjCSelfInitChecker);
-}
-
namespace {
class InitSelfBug : public BugType {
@@ -113,22 +92,40 @@ public:
} // end anonymous namespace
+namespace {
+enum SelfFlagEnum {
+ /// \brief No flag set.
+ SelfFlag_None = 0x0,
+ /// \brief Value came from 'self'.
+ SelfFlag_Self = 0x1,
+ /// \brief Value came from the result of an initializer (e.g. [super init]).
+ SelfFlag_InitRes = 0x2
+};
+}
+
typedef llvm::ImmutableMap<SymbolRef, unsigned> SelfFlag;
namespace { struct CalledInit {}; }
+namespace { struct PreCallSelfFlags {}; }
namespace clang {
namespace ento {
template<>
struct GRStateTrait<SelfFlag> : public GRStatePartialTrait<SelfFlag> {
- static void* GDMIndex() {
- static int index = 0;
- return &index;
- }
+ static void* GDMIndex() { static int index = 0; return &index; }
};
template <>
struct GRStateTrait<CalledInit> : public GRStatePartialTrait<bool> {
static void *GDMIndex() { static int index = 0; return &index; }
};
+
+ /// \brief A call receiving a reference to 'self' invalidates the object that
+ /// 'self' contains. This keeps the "self flags" assigned to the 'self'
+ /// object before the call so we can assign them to the new object that 'self'
+ /// points to after the call.
+ template <>
+ struct GRStateTrait<PreCallSelfFlags> : public GRStatePartialTrait<unsigned> {
+ static void *GDMIndex() { static int index = 0; return &index; }
+ };
}
}
@@ -188,8 +185,8 @@ static void checkForInvalidSelf(const Expr *E, CheckerContext &C,
C.EmitReport(report);
}
-void ObjCSelfInitChecker::postVisitObjCMessage(CheckerContext &C,
- ObjCMessage msg) {
+void ObjCSelfInitChecker::checkPostObjCMessage(ObjCMessage msg,
+ CheckerContext &C) const {
// When encountering a message that does initialization (init rule),
// tag the return value so that we know later on that if self has this value
// then it is properly initialized.
@@ -219,8 +216,8 @@ void ObjCSelfInitChecker::postVisitObjCMessage(CheckerContext &C,
// fails.
}
-void ObjCSelfInitChecker::PostVisitObjCIvarRefExpr(CheckerContext &C,
- const ObjCIvarRefExpr *E) {
+void ObjCSelfInitChecker::checkPostStmt(const ObjCIvarRefExpr *E,
+ CheckerContext &C) const {
// FIXME: A callback should disable checkers at the start of functions.
if (!shouldRunOnFunctionOrMethod(dyn_cast<NamedDecl>(
C.getCurrentAnalysisContext()->getDecl())))
@@ -231,8 +228,8 @@ void ObjCSelfInitChecker::PostVisitObjCIvarRefExpr(CheckerContext &C,
"'[(super or self) init...]'");
}
-void ObjCSelfInitChecker::PreVisitReturnStmt(CheckerContext &C,
- const ReturnStmt *S) {
+void ObjCSelfInitChecker::checkPreStmt(const ReturnStmt *S,
+ CheckerContext &C) const {
// FIXME: A callback should disable checkers at the start of functions.
if (!shouldRunOnFunctionOrMethod(dyn_cast<NamedDecl>(
C.getCurrentAnalysisContext()->getDecl())))
@@ -259,40 +256,46 @@ void ObjCSelfInitChecker::PreVisitReturnStmt(CheckerContext &C,
// Until we can use inter-procedural analysis, in such a call, transfer the
// SelfFlags to the result of the call.
-void ObjCSelfInitChecker::PreVisitGenericCall(CheckerContext &C,
- const CallExpr *CE) {
+void ObjCSelfInitChecker::checkPreStmt(const CallExpr *CE,
+ CheckerContext &C) const {
const GRState *state = C.getState();
for (CallExpr::const_arg_iterator
I = CE->arg_begin(), E = CE->arg_end(); I != E; ++I) {
SVal argV = state->getSVal(*I);
if (isSelfVar(argV, C)) {
- preCallSelfFlags = getSelfFlags(state->getSVal(cast<Loc>(argV)), C);
+ unsigned selfFlags = getSelfFlags(state->getSVal(cast<Loc>(argV)), C);
+ C.addTransition(state->set<PreCallSelfFlags>(selfFlags));
return;
} else if (hasSelfFlag(argV, SelfFlag_Self, C)) {
- preCallSelfFlags = getSelfFlags(argV, C);
+ unsigned selfFlags = getSelfFlags(argV, C);
+ C.addTransition(state->set<PreCallSelfFlags>(selfFlags));
return;
}
}
}
-void ObjCSelfInitChecker::PostVisitGenericCall(CheckerContext &C,
- const CallExpr *CE) {
+void ObjCSelfInitChecker::checkPostStmt(const CallExpr *CE,
+ CheckerContext &C) const {
const GRState *state = C.getState();
for (CallExpr::const_arg_iterator
I = CE->arg_begin(), E = CE->arg_end(); I != E; ++I) {
SVal argV = state->getSVal(*I);
if (isSelfVar(argV, C)) {
- addSelfFlag(state, state->getSVal(cast<Loc>(argV)), preCallSelfFlags, C);
+ SelfFlagEnum prevFlags = (SelfFlagEnum)state->get<PreCallSelfFlags>();
+ state = state->remove<PreCallSelfFlags>();
+ addSelfFlag(state, state->getSVal(cast<Loc>(argV)), prevFlags, C);
return;
} else if (hasSelfFlag(argV, SelfFlag_Self, C)) {
- addSelfFlag(state, state->getSVal(CE), preCallSelfFlags, C);
+ SelfFlagEnum prevFlags = (SelfFlagEnum)state->get<PreCallSelfFlags>();
+ state = state->remove<PreCallSelfFlags>();
+ addSelfFlag(state, state->getSVal(CE), prevFlags, C);
return;
}
}
}
-void ObjCSelfInitChecker::visitLocation(CheckerContext &C, const Stmt *S,
- SVal location, bool isLoad) {
+void ObjCSelfInitChecker::checkLocation(SVal location, bool isLoad,
+ CheckerContext &C) const {
// Tag the result of a load from 'self' so that we can easily know that the
// value is the object that 'self' points to.
const GRState *state = C.getState();
@@ -354,3 +357,11 @@ static bool isInitializationMethod(const ObjCMethodDecl *MD) {
static bool isInitMessage(const ObjCMessage &msg) {
return cocoa::deriveNamingConvention(msg.getSelector()) == cocoa::InitRule;
}
+
+//===----------------------------------------------------------------------===//
+// Registration.
+//===----------------------------------------------------------------------===//
+
+void ento::registerObjCSelfInitChecker(CheckerManager &mgr) {
+ mgr.registerChecker<ObjCSelfInitChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
index 741e48b..034a2aa 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
@@ -13,31 +13,26 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
using namespace clang;
using namespace ento;
namespace {
class PointerArithChecker
- : public CheckerVisitor<PointerArithChecker> {
- BuiltinBug *BT;
+ : public CheckerV2< check::PreStmt<BinaryOperator> > {
+ mutable llvm::OwningPtr<BuiltinBug> BT;
+
public:
- PointerArithChecker() : BT(0) {}
- static void *getTag();
- void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
+ void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const;
};
}
-void *PointerArithChecker::getTag() {
- static int x;
- return &x;
-}
-
-void PointerArithChecker::PreVisitBinaryOperator(CheckerContext &C,
- const BinaryOperator *B) {
+void PointerArithChecker::checkPreStmt(const BinaryOperator *B,
+ CheckerContext &C) const {
if (B->getOpcode() != BO_Sub && B->getOpcode() != BO_Add)
return;
@@ -57,10 +52,10 @@ void PointerArithChecker::PreVisitBinaryOperator(CheckerContext &C,
if (ExplodedNode *N = C.generateNode()) {
if (!BT)
- BT = new BuiltinBug("Dangerous pointer arithmetic",
+ BT.reset(new BuiltinBug("Dangerous pointer arithmetic",
"Pointer arithmetic done on non-array variables "
"means reliance on memory layout, which is "
- "dangerous.");
+ "dangerous."));
RangedBugReport *R = new RangedBugReport(*BT, BT->getDescription(), N);
R->addRange(B->getSourceRange());
C.EmitReport(R);
@@ -68,10 +63,6 @@ void PointerArithChecker::PreVisitBinaryOperator(CheckerContext &C,
}
}
-static void RegisterPointerArithChecker(ExprEngine &Eng) {
- Eng.registerCheck(new PointerArithChecker());
-}
-
void ento::registerPointerArithChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterPointerArithChecker);
+ mgr.registerChecker<PointerArithChecker>();
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
index f28fe9a..bf85b95 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
@@ -14,31 +14,26 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
using namespace clang;
using namespace ento;
namespace {
class PointerSubChecker
- : public CheckerVisitor<PointerSubChecker> {
- BuiltinBug *BT;
+ : public CheckerV2< check::PreStmt<BinaryOperator> > {
+ mutable llvm::OwningPtr<BuiltinBug> BT;
+
public:
- PointerSubChecker() : BT(0) {}
- static void *getTag();
- void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
+ void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const;
};
}
-void *PointerSubChecker::getTag() {
- static int x;
- return &x;
-}
-
-void PointerSubChecker::PreVisitBinaryOperator(CheckerContext &C,
- const BinaryOperator *B) {
+void PointerSubChecker::checkPreStmt(const BinaryOperator *B,
+ CheckerContext &C) const {
// When doing pointer subtraction, if the two pointers do not point to the
// same memory chunk, emit a warning.
if (B->getOpcode() != BO_Sub)
@@ -66,19 +61,15 @@ void PointerSubChecker::PreVisitBinaryOperator(CheckerContext &C,
if (ExplodedNode *N = C.generateNode()) {
if (!BT)
- BT = new BuiltinBug("Pointer subtraction",
+ BT.reset(new BuiltinBug("Pointer subtraction",
"Subtraction of two pointers that do not point to "
- "the same memory chunk may cause incorrect result.");
+ "the same memory chunk may cause incorrect result."));
RangedBugReport *R = new RangedBugReport(*BT, BT->getDescription(), N);
R->addRange(B->getSourceRange());
C.EmitReport(R);
}
}
-static void RegisterPointerSubChecker(ExprEngine &Eng) {
- Eng.registerCheck(new PointerSubChecker());
-}
-
void ento::registerPointerSubChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterPointerSubChecker);
+ mgr.registerChecker<PointerSubChecker>();
}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
index 34c095f..6c6901f 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
@@ -13,8 +13,9 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
#include "llvm/ADT/ImmutableSet.h"
@@ -24,21 +25,15 @@ using namespace ento;
namespace {
class PthreadLockChecker
- : public CheckerVisitor<PthreadLockChecker> {
- BugType *BT;
+ : public CheckerV2< check::PostStmt<CallExpr> > {
public:
- PthreadLockChecker() : BT(0) {}
- static void *getTag() {
- static int x = 0;
- return &x;
- }
- void PostVisitCallExpr(CheckerContext &C, const CallExpr *CE);
+ void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
void AcquireLock(CheckerContext &C, const CallExpr *CE,
- SVal lock, bool isTryLock);
+ SVal lock, bool isTryLock) const;
void ReleaseLock(CheckerContext &C, const CallExpr *CE,
- SVal lock);
+ SVal lock) const;
};
} // end anonymous namespace
@@ -49,22 +44,14 @@ namespace clang {
namespace ento {
template <> struct GRStateTrait<LockSet> :
public GRStatePartialTrait<llvm::ImmutableSet<const MemRegion*> > {
- static void* GDMIndex() { return PthreadLockChecker::getTag(); }
+ static void* GDMIndex() { static int x = 0; return &x; }
};
} // end GR namespace
} // end clang namespace
-static void RegisterPthreadLockChecker(ExprEngine &Eng) {
- Eng.registerCheck(new PthreadLockChecker());
-}
-
-void ento::registerPthreadLockChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterPthreadLockChecker);
-}
-
-void PthreadLockChecker::PostVisitCallExpr(CheckerContext &C,
- const CallExpr *CE) {
+void PthreadLockChecker::checkPostStmt(const CallExpr *CE,
+ CheckerContext &C) const {
const GRState *state = C.getState();
const Expr *Callee = CE->getCallee();
const FunctionTextRegion *R =
@@ -96,7 +83,7 @@ void PthreadLockChecker::PostVisitCallExpr(CheckerContext &C,
}
void PthreadLockChecker::AcquireLock(CheckerContext &C, const CallExpr *CE,
- SVal lock, bool isTryLock) {
+ SVal lock, bool isTryLock) const {
const MemRegion *lockR = lock.getAsRegion();
if (!lockR)
@@ -132,7 +119,7 @@ void PthreadLockChecker::AcquireLock(CheckerContext &C, const CallExpr *CE,
}
void PthreadLockChecker::ReleaseLock(CheckerContext &C, const CallExpr *CE,
- SVal lock) {
+ SVal lock) const {
const MemRegion *lockR = lock.getAsRegion();
if (!lockR)
@@ -150,3 +137,7 @@ void PthreadLockChecker::ReleaseLock(CheckerContext &C, const CallExpr *CE,
C.addTransition(C.generateNode(CE, unlockState));
}
+
+void ento::registerPthreadLockChecker(CheckerManager &mgr) {
+ mgr.registerChecker<PthreadLockChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
index 838a00f..2985156 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
@@ -12,9 +12,11 @@
//
//===----------------------------------------------------------------------===//
-#include "InternalChecks.h"
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
using namespace clang;
@@ -22,25 +24,15 @@ using namespace ento;
namespace {
class ReturnPointerRangeChecker :
- public CheckerVisitor<ReturnPointerRangeChecker> {
- BuiltinBug *BT;
+ public CheckerV2< check::PreStmt<ReturnStmt> > {
+ mutable llvm::OwningPtr<BuiltinBug> BT;
public:
- ReturnPointerRangeChecker() : BT(0) {}
- static void *getTag();
- void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *RS);
+ void checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const;
};
}
-void ento::RegisterReturnPointerRangeChecker(ExprEngine &Eng) {
- Eng.registerCheck(new ReturnPointerRangeChecker());
-}
-
-void *ReturnPointerRangeChecker::getTag() {
- static int x = 0; return &x;
-}
-
-void ReturnPointerRangeChecker::PreVisitReturnStmt(CheckerContext &C,
- const ReturnStmt *RS) {
+void ReturnPointerRangeChecker::checkPreStmt(const ReturnStmt *RS,
+ CheckerContext &C) const {
const GRState *state = C.getState();
const Expr *RetE = RS->getRetValue();
@@ -77,9 +69,9 @@ void ReturnPointerRangeChecker::PreVisitReturnStmt(CheckerContext &C,
// FIXME: This bug correspond to CWE-466. Eventually we should have bug
// types explicitly reference such exploit categories (when applicable).
if (!BT)
- BT = new BuiltinBug("Return of pointer value outside of expected range",
+ BT.reset(new BuiltinBug("Return of pointer value outside of expected range",
"Returned pointer value points outside the original object "
- "(potential buffer overflow)");
+ "(potential buffer overflow)"));
// FIXME: It would be nice to eventually make this diagnostic more clear,
// e.g., by referencing the original declaration or by saying *why* this
@@ -93,3 +85,7 @@ void ReturnPointerRangeChecker::PreVisitReturnStmt(CheckerContext &C,
C.EmitReport(report);
}
}
+
+void ento::registerReturnPointerRangeChecker(CheckerManager &mgr) {
+ mgr.registerChecker<ReturnPointerRangeChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrLeakChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
index 363f404..6a9a37d 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrLeakChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
@@ -1,4 +1,4 @@
-//=== StackAddrLeakChecker.cpp ------------------------------------*- C++ -*--//
+//=== StackAddrEscapeChecker.cpp ----------------------------------*- C++ -*--//
//
// The LLVM Compiler Infrastructure
//
@@ -13,9 +13,10 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/SmallString.h"
@@ -23,34 +24,23 @@ using namespace clang;
using namespace ento;
namespace {
-class StackAddrLeakChecker : public CheckerVisitor<StackAddrLeakChecker> {
- BuiltinBug *BT_stackleak;
- BuiltinBug *BT_returnstack;
+class StackAddrEscapeChecker : public CheckerV2< check::PreStmt<ReturnStmt>,
+ check::EndPath > {
+ mutable llvm::OwningPtr<BuiltinBug> BT_stackleak;
+ mutable llvm::OwningPtr<BuiltinBug> BT_returnstack;
public:
- StackAddrLeakChecker() : BT_stackleak(0), BT_returnstack(0) {}
- static void *getTag() {
- static int x;
- return &x;
- }
- void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *RS);
- void evalEndPath(EndOfFunctionNodeBuilder &B, void *tag, ExprEngine &Eng);
+ void checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const;
+ void checkEndPath(EndOfFunctionNodeBuilder &B, ExprEngine &Eng) const;
private:
- void EmitStackError(CheckerContext &C, const MemRegion *R, const Expr *RetE);
- SourceRange GenName(llvm::raw_ostream &os, const MemRegion *R,
- SourceManager &SM);
+ void EmitStackError(CheckerContext &C, const MemRegion *R,
+ const Expr *RetE) const;
+ static SourceRange GenName(llvm::raw_ostream &os, const MemRegion *R,
+ SourceManager &SM);
};
}
-static void RegisterStackAddrLeakChecker(ExprEngine &Eng) {
- Eng.registerCheck(new StackAddrLeakChecker());
-}
-
-void ento::registerStackAddrLeakChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterStackAddrLeakChecker);
-}
-
-SourceRange StackAddrLeakChecker::GenName(llvm::raw_ostream &os,
+SourceRange StackAddrEscapeChecker::GenName(llvm::raw_ostream &os,
const MemRegion *R,
SourceManager &SM) {
// Get the base region, stripping away fields and elements.
@@ -93,15 +83,16 @@ SourceRange StackAddrLeakChecker::GenName(llvm::raw_ostream &os,
return range;
}
-void StackAddrLeakChecker::EmitStackError(CheckerContext &C, const MemRegion *R,
- const Expr *RetE) {
+void StackAddrEscapeChecker::EmitStackError(CheckerContext &C, const MemRegion *R,
+ const Expr *RetE) const {
ExplodedNode *N = C.generateSink();
if (!N)
return;
if (!BT_returnstack)
- BT_returnstack=new BuiltinBug("Return of address to stack-allocated memory");
+ BT_returnstack.reset(
+ new BuiltinBug("Return of address to stack-allocated memory"));
// Generate a report for this bug.
llvm::SmallString<512> buf;
@@ -116,8 +107,8 @@ void StackAddrLeakChecker::EmitStackError(CheckerContext &C, const MemRegion *R,
C.EmitReport(report);
}
-void StackAddrLeakChecker::PreVisitReturnStmt(CheckerContext &C,
- const ReturnStmt *RS) {
+void StackAddrEscapeChecker::checkPreStmt(const ReturnStmt *RS,
+ CheckerContext &C) const {
const Expr *RetE = RS->getRetValue();
if (!RetE)
@@ -135,8 +126,8 @@ void StackAddrLeakChecker::PreVisitReturnStmt(CheckerContext &C,
}
}
-void StackAddrLeakChecker::evalEndPath(EndOfFunctionNodeBuilder &B, void *tag,
- ExprEngine &Eng) {
+void StackAddrEscapeChecker::checkEndPath(EndOfFunctionNodeBuilder &B,
+ ExprEngine &Eng) const {
const GRState *state = B.getState();
@@ -180,16 +171,16 @@ void StackAddrLeakChecker::evalEndPath(EndOfFunctionNodeBuilder &B, void *tag,
return;
// Generate an error node.
- ExplodedNode *N = B.generateNode(state, tag, B.getPredecessor());
+ ExplodedNode *N = B.generateNode(state);
if (!N)
return;
if (!BT_stackleak)
- BT_stackleak =
+ BT_stackleak.reset(
new BuiltinBug("Stack address stored into global variable",
"Stack address was saved into a global variable. "
"This is dangerous because the address will become "
- "invalid after returning from the function");
+ "invalid after returning from the function"));
for (unsigned i = 0, e = cb.V.size(); i != e; ++i) {
// Generate a report for this bug.
@@ -208,3 +199,7 @@ void StackAddrLeakChecker::evalEndPath(EndOfFunctionNodeBuilder &B, void *tag,
Eng.getBugReporter().EmitReport(report);
}
}
+
+void ento::registerStackAddrEscapeChecker(CheckerManager &mgr) {
+ mgr.registerChecker<StackAddrEscapeChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
index 2655be2..d0626b8 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
@@ -12,9 +12,10 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
@@ -55,52 +56,50 @@ struct StreamState {
}
};
-class StreamChecker : public CheckerVisitor<StreamChecker> {
- IdentifierInfo *II_fopen, *II_tmpfile, *II_fclose, *II_fread, *II_fwrite,
+class StreamChecker : public CheckerV2<eval::Call,
+ check::DeadSymbols,
+ check::EndPath,
+ check::PreStmt<ReturnStmt> > {
+ mutable IdentifierInfo *II_fopen, *II_tmpfile, *II_fclose, *II_fread,
+ *II_fwrite,
*II_fseek, *II_ftell, *II_rewind, *II_fgetpos, *II_fsetpos,
*II_clearerr, *II_feof, *II_ferror, *II_fileno;
- BuiltinBug *BT_nullfp, *BT_illegalwhence, *BT_doubleclose, *BT_ResourceLeak;
+ mutable llvm::OwningPtr<BuiltinBug> BT_nullfp, BT_illegalwhence,
+ BT_doubleclose, BT_ResourceLeak;
public:
StreamChecker()
: II_fopen(0), II_tmpfile(0) ,II_fclose(0), II_fread(0), II_fwrite(0),
II_fseek(0), II_ftell(0), II_rewind(0), II_fgetpos(0), II_fsetpos(0),
- II_clearerr(0), II_feof(0), II_ferror(0), II_fileno(0),
- BT_nullfp(0), BT_illegalwhence(0), BT_doubleclose(0),
- BT_ResourceLeak(0) {}
+ II_clearerr(0), II_feof(0), II_ferror(0), II_fileno(0) {}
- static void *getTag() {
- static int x;
- return &x;
- }
-
- virtual bool evalCallExpr(CheckerContext &C, const CallExpr *CE);
- void evalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper);
- void evalEndPath(EndOfFunctionNodeBuilder &B, void *tag, ExprEngine &Eng);
- void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S);
+ bool evalCall(const CallExpr *CE, CheckerContext &C) const;
+ void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
+ void checkEndPath(EndOfFunctionNodeBuilder &B, ExprEngine &Eng) const;
+ void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
private:
- void Fopen(CheckerContext &C, const CallExpr *CE);
- void Tmpfile(CheckerContext &C, const CallExpr *CE);
- void Fclose(CheckerContext &C, const CallExpr *CE);
- void Fread(CheckerContext &C, const CallExpr *CE);
- void Fwrite(CheckerContext &C, const CallExpr *CE);
- void Fseek(CheckerContext &C, const CallExpr *CE);
- void Ftell(CheckerContext &C, const CallExpr *CE);
- void Rewind(CheckerContext &C, const CallExpr *CE);
- void Fgetpos(CheckerContext &C, const CallExpr *CE);
- void Fsetpos(CheckerContext &C, const CallExpr *CE);
- void Clearerr(CheckerContext &C, const CallExpr *CE);
- void Feof(CheckerContext &C, const CallExpr *CE);
- void Ferror(CheckerContext &C, const CallExpr *CE);
- void Fileno(CheckerContext &C, const CallExpr *CE);
-
- void OpenFileAux(CheckerContext &C, const CallExpr *CE);
+ void Fopen(CheckerContext &C, const CallExpr *CE) const;
+ void Tmpfile(CheckerContext &C, const CallExpr *CE) const;
+ void Fclose(CheckerContext &C, const CallExpr *CE) const;
+ void Fread(CheckerContext &C, const CallExpr *CE) const;
+ void Fwrite(CheckerContext &C, const CallExpr *CE) const;
+ void Fseek(CheckerContext &C, const CallExpr *CE) const;
+ void Ftell(CheckerContext &C, const CallExpr *CE) const;
+ void Rewind(CheckerContext &C, const CallExpr *CE) const;
+ void Fgetpos(CheckerContext &C, const CallExpr *CE) const;
+ void Fsetpos(CheckerContext &C, const CallExpr *CE) const;
+ void Clearerr(CheckerContext &C, const CallExpr *CE) const;
+ void Feof(CheckerContext &C, const CallExpr *CE) const;
+ void Ferror(CheckerContext &C, const CallExpr *CE) const;
+ void Fileno(CheckerContext &C, const CallExpr *CE) const;
+
+ void OpenFileAux(CheckerContext &C, const CallExpr *CE) const;
const GRState *CheckNullStream(SVal SV, const GRState *state,
- CheckerContext &C);
+ CheckerContext &C) const;
const GRState *CheckDoubleClose(const CallExpr *CE, const GRState *state,
- CheckerContext &C);
+ CheckerContext &C) const;
};
} // end anonymous namespace
@@ -110,20 +109,12 @@ namespace ento {
template <>
struct GRStateTrait<StreamState>
: public GRStatePartialTrait<llvm::ImmutableMap<SymbolRef, StreamState> > {
- static void *GDMIndex() { return StreamChecker::getTag(); }
+ static void *GDMIndex() { static int x; return &x; }
};
}
}
-static void RegisterStreamChecker(ExprEngine &Eng) {
- Eng.registerCheck(new StreamChecker());
-}
-
-void ento::registerStreamChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterStreamChecker);
-}
-
-bool StreamChecker::evalCallExpr(CheckerContext &C, const CallExpr *CE) {
+bool StreamChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
const GRState *state = C.getState();
const Expr *Callee = CE->getCallee();
SVal L = state->getSVal(Callee);
@@ -221,15 +212,15 @@ bool StreamChecker::evalCallExpr(CheckerContext &C, const CallExpr *CE) {
return false;
}
-void StreamChecker::Fopen(CheckerContext &C, const CallExpr *CE) {
+void StreamChecker::Fopen(CheckerContext &C, const CallExpr *CE) const {
OpenFileAux(C, CE);
}
-void StreamChecker::Tmpfile(CheckerContext &C, const CallExpr *CE) {
+void StreamChecker::Tmpfile(CheckerContext &C, const CallExpr *CE) const {
OpenFileAux(C, CE);
}
-void StreamChecker::OpenFileAux(CheckerContext &C, const CallExpr *CE) {
+void StreamChecker::OpenFileAux(CheckerContext &C, const CallExpr *CE) const {
const GRState *state = C.getState();
unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
SValBuilder &svalBuilder = C.getSValBuilder();
@@ -255,25 +246,25 @@ void StreamChecker::OpenFileAux(CheckerContext &C, const CallExpr *CE) {
}
}
-void StreamChecker::Fclose(CheckerContext &C, const CallExpr *CE) {
+void StreamChecker::Fclose(CheckerContext &C, const CallExpr *CE) const {
const GRState *state = CheckDoubleClose(CE, C.getState(), C);
if (state)
C.addTransition(state);
}
-void StreamChecker::Fread(CheckerContext &C, const CallExpr *CE) {
+void StreamChecker::Fread(CheckerContext &C, const CallExpr *CE) const {
const GRState *state = C.getState();
if (!CheckNullStream(state->getSVal(CE->getArg(3)), state, C))
return;
}
-void StreamChecker::Fwrite(CheckerContext &C, const CallExpr *CE) {
+void StreamChecker::Fwrite(CheckerContext &C, const CallExpr *CE) const {
const GRState *state = C.getState();
if (!CheckNullStream(state->getSVal(CE->getArg(3)), state, C))
return;
}
-void StreamChecker::Fseek(CheckerContext &C, const CallExpr *CE) {
+void StreamChecker::Fseek(CheckerContext &C, const CallExpr *CE) const {
const GRState *state = C.getState();
if (!(state = CheckNullStream(state->getSVal(CE->getArg(0)), state, C)))
return;
@@ -290,65 +281,65 @@ void StreamChecker::Fseek(CheckerContext &C, const CallExpr *CE) {
if (ExplodedNode *N = C.generateNode(state)) {
if (!BT_illegalwhence)
- BT_illegalwhence = new BuiltinBug("Illegal whence argument",
+ BT_illegalwhence.reset(new BuiltinBug("Illegal whence argument",
"The whence argument to fseek() should be "
- "SEEK_SET, SEEK_END, or SEEK_CUR.");
+ "SEEK_SET, SEEK_END, or SEEK_CUR."));
BugReport *R = new BugReport(*BT_illegalwhence,
BT_illegalwhence->getDescription(), N);
C.EmitReport(R);
}
}
-void StreamChecker::Ftell(CheckerContext &C, const CallExpr *CE) {
+void StreamChecker::Ftell(CheckerContext &C, const CallExpr *CE) const {
const GRState *state = C.getState();
if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
return;
}
-void StreamChecker::Rewind(CheckerContext &C, const CallExpr *CE) {
+void StreamChecker::Rewind(CheckerContext &C, const CallExpr *CE) const {
const GRState *state = C.getState();
if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
return;
}
-void StreamChecker::Fgetpos(CheckerContext &C, const CallExpr *CE) {
+void StreamChecker::Fgetpos(CheckerContext &C, const CallExpr *CE) const {
const GRState *state = C.getState();
if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
return;
}
-void StreamChecker::Fsetpos(CheckerContext &C, const CallExpr *CE) {
+void StreamChecker::Fsetpos(CheckerContext &C, const CallExpr *CE) const {
const GRState *state = C.getState();
if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
return;
}
-void StreamChecker::Clearerr(CheckerContext &C, const CallExpr *CE) {
+void StreamChecker::Clearerr(CheckerContext &C, const CallExpr *CE) const {
const GRState *state = C.getState();
if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
return;
}
-void StreamChecker::Feof(CheckerContext &C, const CallExpr *CE) {
+void StreamChecker::Feof(CheckerContext &C, const CallExpr *CE) const {
const GRState *state = C.getState();
if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
return;
}
-void StreamChecker::Ferror(CheckerContext &C, const CallExpr *CE) {
+void StreamChecker::Ferror(CheckerContext &C, const CallExpr *CE) const {
const GRState *state = C.getState();
if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
return;
}
-void StreamChecker::Fileno(CheckerContext &C, const CallExpr *CE) {
+void StreamChecker::Fileno(CheckerContext &C, const CallExpr *CE) const {
const GRState *state = C.getState();
if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
return;
}
const GRState *StreamChecker::CheckNullStream(SVal SV, const GRState *state,
- CheckerContext &C) {
+ CheckerContext &C) const {
const DefinedSVal *DV = dyn_cast<DefinedSVal>(&SV);
if (!DV)
return 0;
@@ -360,8 +351,8 @@ const GRState *StreamChecker::CheckNullStream(SVal SV, const GRState *state,
if (!stateNotNull && stateNull) {
if (ExplodedNode *N = C.generateSink(stateNull)) {
if (!BT_nullfp)
- BT_nullfp = new BuiltinBug("NULL stream pointer",
- "Stream pointer might be NULL.");
+ BT_nullfp.reset(new BuiltinBug("NULL stream pointer",
+ "Stream pointer might be NULL."));
BugReport *R =new BugReport(*BT_nullfp, BT_nullfp->getDescription(), N);
C.EmitReport(R);
}
@@ -372,7 +363,7 @@ const GRState *StreamChecker::CheckNullStream(SVal SV, const GRState *state,
const GRState *StreamChecker::CheckDoubleClose(const CallExpr *CE,
const GRState *state,
- CheckerContext &C) {
+ CheckerContext &C) const {
SymbolRef Sym = state->getSVal(CE->getArg(0)).getAsSymbol();
if (!Sym)
return state;
@@ -389,9 +380,9 @@ const GRState *StreamChecker::CheckDoubleClose(const CallExpr *CE,
ExplodedNode *N = C.generateSink();
if (N) {
if (!BT_doubleclose)
- BT_doubleclose = new BuiltinBug("Double fclose",
+ BT_doubleclose.reset(new BuiltinBug("Double fclose",
"Try to close a file Descriptor already"
- " closed. Cause undefined behaviour.");
+ " closed. Cause undefined behaviour."));
BugReport *R = new BugReport(*BT_doubleclose,
BT_doubleclose->getDescription(), N);
C.EmitReport(R);
@@ -403,7 +394,8 @@ const GRState *StreamChecker::CheckDoubleClose(const CallExpr *CE,
return state->set<StreamState>(Sym, StreamState::getClosed(CE));
}
-void StreamChecker::evalDeadSymbols(CheckerContext &C,SymbolReaper &SymReaper) {
+void StreamChecker::checkDeadSymbols(SymbolReaper &SymReaper,
+ CheckerContext &C) const {
for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
E = SymReaper.dead_end(); I != E; ++I) {
SymbolRef Sym = *I;
@@ -416,8 +408,8 @@ void StreamChecker::evalDeadSymbols(CheckerContext &C,SymbolReaper &SymReaper) {
ExplodedNode *N = C.generateSink();
if (N) {
if (!BT_ResourceLeak)
- BT_ResourceLeak = new BuiltinBug("Resource Leak",
- "Opened File never closed. Potential Resource leak.");
+ BT_ResourceLeak.reset(new BuiltinBug("Resource Leak",
+ "Opened File never closed. Potential Resource leak."));
BugReport *R = new BugReport(*BT_ResourceLeak,
BT_ResourceLeak->getDescription(), N);
C.EmitReport(R);
@@ -426,8 +418,8 @@ void StreamChecker::evalDeadSymbols(CheckerContext &C,SymbolReaper &SymReaper) {
}
}
-void StreamChecker::evalEndPath(EndOfFunctionNodeBuilder &B, void *tag,
- ExprEngine &Eng) {
+void StreamChecker::checkEndPath(EndOfFunctionNodeBuilder &B,
+ ExprEngine &Eng) const {
const GRState *state = B.getState();
typedef llvm::ImmutableMap<SymbolRef, StreamState> SymMap;
SymMap M = state->get<StreamState>();
@@ -435,11 +427,11 @@ void StreamChecker::evalEndPath(EndOfFunctionNodeBuilder &B, void *tag,
for (SymMap::iterator I = M.begin(), E = M.end(); I != E; ++I) {
StreamState SS = I->second;
if (SS.isOpened()) {
- ExplodedNode *N = B.generateNode(state, tag, B.getPredecessor());
+ ExplodedNode *N = B.generateNode(state);
if (N) {
if (!BT_ResourceLeak)
- BT_ResourceLeak = new BuiltinBug("Resource Leak",
- "Opened File never closed. Potential Resource leak.");
+ BT_ResourceLeak.reset(new BuiltinBug("Resource Leak",
+ "Opened File never closed. Potential Resource leak."));
BugReport *R = new BugReport(*BT_ResourceLeak,
BT_ResourceLeak->getDescription(), N);
Eng.getBugReporter().EmitReport(R);
@@ -448,7 +440,7 @@ void StreamChecker::evalEndPath(EndOfFunctionNodeBuilder &B, void *tag,
}
}
-void StreamChecker::PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S) {
+void StreamChecker::checkPreStmt(const ReturnStmt *S, CheckerContext &C) const {
const Expr *RetE = S->getRetValue();
if (!RetE)
return;
@@ -468,3 +460,7 @@ void StreamChecker::PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S) {
C.addTransition(state);
}
+
+void ento::registerStreamChecker(CheckerManager &mgr) {
+ mgr.registerChecker<StreamChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
index a53ebb5..be4fbf6 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
@@ -13,10 +13,11 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
-#include "clang/Basic/TargetInfo.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringSwitch.h"
#include <fcntl.h>
@@ -26,7 +27,7 @@ using namespace ento;
using llvm::Optional;
namespace {
-class UnixAPIChecker : public CheckerVisitor<UnixAPIChecker> {
+class UnixAPIChecker : public CheckerV2< check::PreStmt<CallExpr> > {
enum SubChecks {
OpenFn = 0,
PthreadOnceFn = 1,
@@ -34,27 +35,22 @@ class UnixAPIChecker : public CheckerVisitor<UnixAPIChecker> {
NumChecks
};
- BugType *BTypes[NumChecks];
+ mutable BugType *BTypes[NumChecks];
public:
- Optional<uint64_t> Val_O_CREAT;
+ mutable Optional<uint64_t> Val_O_CREAT;
public:
UnixAPIChecker() { memset(BTypes, 0, sizeof(*BTypes) * NumChecks); }
- static void *getTag() { static unsigned tag = 0; return &tag; }
+ ~UnixAPIChecker() {
+ for (unsigned i=0; i != NumChecks; ++i)
+ delete BTypes[i];
+ }
- void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
+ void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
};
} //end anonymous namespace
-static void RegisterUnixAPIChecker(ExprEngine &Eng) {
- Eng.registerCheck(new UnixAPIChecker());
-}
-
-void ento::registerUnixAPIChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterUnixAPIChecker);
-}
-
//===----------------------------------------------------------------------===//
// Utility functions.
//===----------------------------------------------------------------------===//
@@ -69,7 +65,7 @@ static inline void LazyInitialize(BugType *&BT, const char *name) {
// "open" (man 2 open)
//===----------------------------------------------------------------------===//
-static void CheckOpen(CheckerContext &C, UnixAPIChecker &UC,
+static void CheckOpen(CheckerContext &C, const UnixAPIChecker &UC,
const CallExpr *CE, BugType *&BT) {
// The definition of O_CREAT is platform specific. We need a better way
// of querying this information from the checking environment.
@@ -141,7 +137,7 @@ static void CheckOpen(CheckerContext &C, UnixAPIChecker &UC,
// pthread_once
//===----------------------------------------------------------------------===//
-static void CheckPthreadOnce(CheckerContext &C, UnixAPIChecker &,
+static void CheckPthreadOnce(CheckerContext &C, const UnixAPIChecker &,
const CallExpr *CE, BugType *&BT) {
// This is similar to 'CheckDispatchOnce' in the MacOSXAPIChecker.
@@ -186,7 +182,7 @@ static void CheckPthreadOnce(CheckerContext &C, UnixAPIChecker &,
// FIXME: Eventually this should be rolled into the MallocChecker, but this
// check is more basic and is valuable for widespread use.
-static void CheckMallocZero(CheckerContext &C, UnixAPIChecker &UC,
+static void CheckMallocZero(CheckerContext &C, const UnixAPIChecker &UC,
const CallExpr *CE, BugType *&BT) {
// Sanity check that malloc takes one argument.
@@ -234,16 +230,16 @@ static void CheckMallocZero(CheckerContext &C, UnixAPIChecker &UC,
// Central dispatch function.
//===----------------------------------------------------------------------===//
-typedef void (*SubChecker)(CheckerContext &C, UnixAPIChecker &UC,
+typedef void (*SubChecker)(CheckerContext &C, const UnixAPIChecker &UC,
const CallExpr *CE, BugType *&BT);
namespace {
class SubCheck {
SubChecker SC;
- UnixAPIChecker *UC;
+ const UnixAPIChecker *UC;
BugType **BT;
public:
- SubCheck(SubChecker sc, UnixAPIChecker *uc, BugType *& bt) : SC(sc), UC(uc),
- BT(&bt) {}
+ SubCheck(SubChecker sc, const UnixAPIChecker *uc, BugType *& bt)
+ : SC(sc), UC(uc), BT(&bt) {}
SubCheck() : SC(NULL), UC(NULL), BT(NULL) {}
void run(CheckerContext &C, const CallExpr *CE) const {
@@ -253,7 +249,7 @@ namespace {
};
} // end anonymous namespace
-void UnixAPIChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
+void UnixAPIChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const {
// Get the callee. All the functions we care about are C functions
// with simple identifiers.
const GRState *state = C.getState();
@@ -280,3 +276,11 @@ void UnixAPIChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
SC.run(C, CE);
}
+
+//===----------------------------------------------------------------------===//
+// Registration.
+//===----------------------------------------------------------------------===//
+
+void ento::registerUnixAPIChecker(CheckerManager &mgr) {
+ mgr.registerChecker<UnixAPIChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
index 3038e29..1bc487a 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
@@ -14,15 +14,16 @@
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
-#include "clang/AST/ParentMap.h"
-#include "clang/Basic/Builtins.h"
-#include "clang/Basic/SourceManager.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/AST/ParentMap.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/SmallPtrSet.h"
// The number of CFGBlock pointers we want to reserve memory for. This is used
@@ -33,40 +34,27 @@ using namespace clang;
using namespace ento;
namespace {
-class UnreachableCodeChecker : public Checker {
+class UnreachableCodeChecker : public CheckerV2<check::EndAnalysis> {
public:
- static void *getTag();
- void VisitEndAnalysis(ExplodedGraph &G,
- BugReporter &B,
- ExprEngine &Eng);
+ void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,
+ ExprEngine &Eng) const;
private:
+ typedef llvm::SmallSet<unsigned, DEFAULT_CFGBLOCKS> CFGBlocksSet;
+
static inline const Stmt *getUnreachableStmt(const CFGBlock *CB);
- void FindUnreachableEntryPoints(const CFGBlock *CB);
+ static void FindUnreachableEntryPoints(const CFGBlock *CB,
+ CFGBlocksSet &reachable,
+ CFGBlocksSet &visited);
static bool isInvalidPath(const CFGBlock *CB, const ParentMap &PM);
static inline bool isEmptyCFGBlock(const CFGBlock *CB);
-
- llvm::SmallSet<unsigned, DEFAULT_CFGBLOCKS> reachable;
- llvm::SmallSet<unsigned, DEFAULT_CFGBLOCKS> visited;
};
}
-void *UnreachableCodeChecker::getTag() {
- static int x = 0;
- return &x;
-}
-
-static void RegisterUnreachableCodeChecker(ExprEngine &Eng) {
- Eng.registerCheck(new UnreachableCodeChecker());
-}
-
-void ento::registerUnreachableCodeChecker(CheckerManager &mgr) {
- mgr.addCheckerRegisterFunction(RegisterUnreachableCodeChecker);
-}
-
-void UnreachableCodeChecker::VisitEndAnalysis(ExplodedGraph &G,
+void UnreachableCodeChecker::checkEndAnalysis(ExplodedGraph &G,
BugReporter &B,
- ExprEngine &Eng) {
- // Bail out if we didn't cover all paths
+ ExprEngine &Eng) const {
+ CFGBlocksSet reachable, visited;
+
if (Eng.hasWorkRemaining())
return;
@@ -109,7 +97,7 @@ void UnreachableCodeChecker::VisitEndAnalysis(ExplodedGraph &G,
// Find the entry points for this block
if (!visited.count(CB->getBlockID()))
- FindUnreachableEntryPoints(CB);
+ FindUnreachableEntryPoints(CB, reachable, visited);
// This block may have been pruned; check if we still want to report it
if (reachable.count(CB->getBlockID()))
@@ -155,7 +143,9 @@ void UnreachableCodeChecker::VisitEndAnalysis(ExplodedGraph &G,
}
// Recursively finds the entry point(s) for this dead CFGBlock.
-void UnreachableCodeChecker::FindUnreachableEntryPoints(const CFGBlock *CB) {
+void UnreachableCodeChecker::FindUnreachableEntryPoints(const CFGBlock *CB,
+ CFGBlocksSet &reachable,
+ CFGBlocksSet &visited) {
visited.insert(CB->getBlockID());
for (CFGBlock::const_pred_iterator I = CB->pred_begin(), E = CB->pred_end();
@@ -166,7 +156,7 @@ void UnreachableCodeChecker::FindUnreachableEntryPoints(const CFGBlock *CB) {
reachable.insert(CB->getBlockID());
if (!visited.count((*I)->getBlockID()))
// If we haven't previously visited the unreachable predecessor, recurse
- FindUnreachableEntryPoints(*I);
+ FindUnreachableEntryPoints(*I, reachable, visited);
}
}
}
@@ -226,3 +216,7 @@ bool UnreachableCodeChecker::isEmptyCFGBlock(const CFGBlock *CB) {
&& CB->size() == 0 // No statements
&& CB->getTerminator() == 0; // No terminator
}
+
+void ento::registerUnreachableCodeChecker(CheckerManager &mgr) {
+ mgr.registerChecker<UnreachableCodeChecker>();
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
index 9a84045..672982a 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -1202,16 +1202,8 @@ static void GenerateExtensivePathDiagnostic(PathDiagnostic& PD,
//===----------------------------------------------------------------------===//
// Methods for BugType and subclasses.
//===----------------------------------------------------------------------===//
-BugType::~BugType() {
- // Free up the equivalence class objects. Observe that we get a pointer to
- // the object first before incrementing the iterator, as destroying the
- // node before doing so means we will read from freed memory.
- for (iterator I = begin(), E = end(); I !=E; ) {
- BugReportEquivClass *EQ = &*I;
- ++I;
- delete EQ;
- }
-}
+BugType::~BugType() { }
+
void BugType::FlushReports(BugReporter &BR) {}
//===----------------------------------------------------------------------===//
@@ -1315,28 +1307,30 @@ void BugReporter::FlushReports() {
return;
// First flush the warnings for each BugType. This may end up creating new
- // warnings and new BugTypes. Because ImmutableSet is a functional data
- // structure, we do not need to worry about the iterators being invalidated.
+ // warnings and new BugTypes.
+ // FIXME: Only NSErrorChecker needs BugType's FlushReports.
+ // Turn NSErrorChecker into a proper checker and remove this.
+ llvm::SmallVector<const BugType*, 16> bugTypes;
for (BugTypesTy::iterator I=BugTypes.begin(), E=BugTypes.end(); I!=E; ++I)
+ bugTypes.push_back(*I);
+ for (llvm::SmallVector<const BugType*, 16>::iterator
+ I = bugTypes.begin(), E = bugTypes.end(); I != E; ++I)
const_cast<BugType*>(*I)->FlushReports(*this);
- // Iterate through BugTypes a second time. BugTypes may have been updated
- // with new BugType objects and new warnings.
- for (BugTypesTy::iterator I=BugTypes.begin(), E=BugTypes.end(); I!=E; ++I) {
- BugType *BT = const_cast<BugType*>(*I);
-
- typedef llvm::FoldingSet<BugReportEquivClass> SetTy;
- SetTy& EQClasses = BT->EQClasses;
-
- for (SetTy::iterator EI=EQClasses.begin(), EE=EQClasses.end(); EI!=EE;++EI){
- BugReportEquivClass& EQ = *EI;
- FlushReport(EQ);
- }
-
- // Delete the BugType object.
- delete BT;
+ typedef llvm::FoldingSet<BugReportEquivClass> SetTy;
+ for (SetTy::iterator EI=EQClasses.begin(), EE=EQClasses.end(); EI!=EE;++EI){
+ BugReportEquivClass& EQ = *EI;
+ FlushReport(EQ);
}
+ // BugReporter owns and deletes only BugTypes created implicitly through
+ // EmitBasicReport.
+ // FIXME: There are leaks from checkers that assume that the BugTypes they
+ // create will be destroyed by the BugReporter.
+ for (llvm::StringMap<BugType*>::iterator
+ I = StrBugTypes.begin(), E = StrBugTypes.end(); I != E; ++I)
+ delete I->second;
+
// Remove all references to the BugType objects.
BugTypes = F.getEmptySet();
}
@@ -1632,11 +1626,11 @@ void BugReporter::EmitReport(BugReport* R) {
BugType& BT = R->getBugType();
Register(&BT);
void *InsertPos;
- BugReportEquivClass* EQ = BT.EQClasses.FindNodeOrInsertPos(ID, InsertPos);
+ BugReportEquivClass* EQ = EQClasses.FindNodeOrInsertPos(ID, InsertPos);
if (!EQ) {
EQ = new BugReportEquivClass(R);
- BT.EQClasses.InsertNode(EQ, InsertPos);
+ EQClasses.InsertNode(EQ, InsertPos);
}
else
EQ->AddReport(R);
@@ -1887,10 +1881,24 @@ void BugReporter::EmitBasicReport(llvm::StringRef name,
llvm::StringRef str, SourceLocation Loc,
SourceRange* RBeg, unsigned NumRanges) {
- // 'BT' will be owned by BugReporter as soon as we call 'EmitReport'.
- BugType *BT = new BugType(name, category);
+ // 'BT' is owned by BugReporter.
+ BugType *BT = getBugTypeForName(name, category);
FullSourceLoc L = getContext().getFullLoc(Loc);
RangedBugReport *R = new DiagBugReport(*BT, str, L);
for ( ; NumRanges > 0 ; --NumRanges, ++RBeg) R->addRange(*RBeg);
EmitReport(R);
}
+
+BugType *BugReporter::getBugTypeForName(llvm::StringRef name,
+ llvm::StringRef category) {
+ llvm::SmallString<136> fullDesc;
+ llvm::raw_svector_ostream(fullDesc) << name << ":" << category;
+ llvm::StringMapEntry<BugType *> &
+ entry = StrBugTypes.GetOrCreateValue(fullDesc);
+ BugType *BT = entry.getValue();
+ if (!BT) {
+ BT = new BugType(name, category);
+ entry.setValue(BT);
+ }
+ return BT;
+}
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
index 1989b82..75d331a 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -13,11 +13,17 @@
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/CheckerProvider.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/Analysis/ProgramPoint.h"
#include "clang/AST/DeclBase.h"
using namespace clang;
using namespace ento;
+//===----------------------------------------------------------------------===//
+// Functions for running checkers for AST traversing..
+//===----------------------------------------------------------------------===//
+
void CheckerManager::runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
BugReporter &BR) {
assert(D);
@@ -33,53 +39,398 @@ void CheckerManager::runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
for (unsigned i = 0, e = DeclCheckers.size(); i != e; ++i) {
DeclCheckerInfo &info = DeclCheckers[i];
if (info.IsForDeclFn(D))
- checkers->push_back(std::make_pair(info.Checker, info.CheckFn));
+ checkers->push_back(info.CheckFn);
}
}
assert(checkers);
for (CachedDeclCheckers::iterator
- I = checkers->begin(), E = checkers->end(); I != E; ++I) {
- CheckerRef checker = I->first;
- CheckDeclFunc fn = I->second;
- fn(checker, D, mgr, BR);
- }
+ I = checkers->begin(), E = checkers->end(); I != E; ++I)
+ (*I)(D, mgr, BR);
}
void CheckerManager::runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
BugReporter &BR) {
assert(D && D->hasBody());
- for (unsigned i = 0, e = BodyCheckers.size(); i != e; ++i) {
- CheckerRef checker = BodyCheckers[i].first;
- CheckDeclFunc fn = BodyCheckers[i].second;
- fn(checker, D, mgr, BR);
+ for (unsigned i = 0, e = BodyCheckers.size(); i != e; ++i)
+ BodyCheckers[i](D, mgr, BR);
+}
+
+//===----------------------------------------------------------------------===//
+// Functions for running checkers for path-sensitive checking.
+//===----------------------------------------------------------------------===//
+
+template <typename CHECK_CTX>
+static void expandGraphWithCheckers(CHECK_CTX checkCtx,
+ ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src) {
+
+ typename CHECK_CTX::CheckersTy::const_iterator
+ I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
+ if (I == E) {
+ Dst.insert(Src);
+ return;
+ }
+
+ ExplodedNodeSet Tmp1, Tmp2;
+ const ExplodedNodeSet *PrevSet = &Src;
+
+ for (; I != E; ++I) {
+ ExplodedNodeSet *CurrSet = 0;
+ if (I+1 == E)
+ CurrSet = &Dst;
+ else {
+ CurrSet = (PrevSet == &Tmp1) ? &Tmp2 : &Tmp1;
+ CurrSet->clear();
+ }
+
+ for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
+ NI != NE; ++NI)
+ checkCtx.runChecker(*I, *CurrSet, *NI);
+
+ // Update which NodeSet is the current one.
+ PrevSet = CurrSet;
+ }
+}
+
+namespace {
+ struct CheckStmtContext {
+ typedef llvm::SmallVectorImpl<CheckerManager::CheckStmtFunc> CheckersTy;
+ bool IsPreVisit;
+ const CheckersTy &Checkers;
+ const Stmt *S;
+ ExprEngine &Eng;
+
+ CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
+ CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
+
+ CheckStmtContext(bool isPreVisit, const CheckersTy &checkers,
+ const Stmt *s, ExprEngine &eng)
+ : IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng) { }
+
+ void runChecker(CheckerManager::CheckStmtFunc checkFn,
+ ExplodedNodeSet &Dst, ExplodedNode *Pred) {
+ // FIXME: Remove respondsToCallback from CheckerContext;
+ CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker,
+ IsPreVisit ? ProgramPoint::PreStmtKind :
+ ProgramPoint::PostStmtKind, 0, S);
+ checkFn(S, C);
+ }
+ };
+}
+
+/// \brief Run checkers for visiting Stmts.
+void CheckerManager::runCheckersForStmt(bool isPreVisit,
+ ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ const Stmt *S,
+ ExprEngine &Eng) {
+ CheckStmtContext C(isPreVisit, *getCachedStmtCheckersFor(S, isPreVisit),
+ S, Eng);
+ expandGraphWithCheckers(C, Dst, Src);
+}
+
+namespace {
+ struct CheckObjCMessageContext {
+ typedef std::vector<CheckerManager::CheckObjCMessageFunc> CheckersTy;
+ bool IsPreVisit;
+ const CheckersTy &Checkers;
+ const ObjCMessage &Msg;
+ ExprEngine &Eng;
+
+ CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
+ CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
+
+ CheckObjCMessageContext(bool isPreVisit, const CheckersTy &checkers,
+ const ObjCMessage &msg, ExprEngine &eng)
+ : IsPreVisit(isPreVisit), Checkers(checkers), Msg(msg), Eng(eng) { }
+
+ void runChecker(CheckerManager::CheckObjCMessageFunc checkFn,
+ ExplodedNodeSet &Dst, ExplodedNode *Pred) {
+ CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker,
+ IsPreVisit ? ProgramPoint::PreStmtKind :
+ ProgramPoint::PostStmtKind, 0,
+ Msg.getOriginExpr());
+ checkFn(Msg, C);
+ }
+ };
+}
+
+/// \brief Run checkers for visiting obj-c messages.
+void CheckerManager::runCheckersForObjCMessage(bool isPreVisit,
+ ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ const ObjCMessage &msg,
+ ExprEngine &Eng) {
+ CheckObjCMessageContext C(isPreVisit,
+ isPreVisit ? PreObjCMessageCheckers
+ : PostObjCMessageCheckers,
+ msg, Eng);
+ expandGraphWithCheckers(C, Dst, Src);
+}
+
+namespace {
+ struct CheckLocationContext {
+ typedef std::vector<CheckerManager::CheckLocationFunc> CheckersTy;
+ const CheckersTy &Checkers;
+ SVal Loc;
+ bool IsLoad;
+ const Stmt *S;
+ ExprEngine &Eng;
+
+ CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
+ CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
+
+ CheckLocationContext(const CheckersTy &checkers,
+ SVal loc, bool isLoad, const Stmt *s, ExprEngine &eng)
+ : Checkers(checkers), Loc(loc), IsLoad(isLoad), S(s), Eng(eng) { }
+
+ void runChecker(CheckerManager::CheckLocationFunc checkFn,
+ ExplodedNodeSet &Dst, ExplodedNode *Pred) {
+ CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker,
+ IsLoad ? ProgramPoint::PreLoadKind :
+ ProgramPoint::PreStoreKind, 0, S);
+ checkFn(Loc, IsLoad, C);
+ }
+ };
+}
+
+/// \brief Run checkers for load/store of a location.
+void CheckerManager::runCheckersForLocation(ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ SVal location, bool isLoad,
+ const Stmt *S, ExprEngine &Eng) {
+ CheckLocationContext C(LocationCheckers, location, isLoad, S, Eng);
+ expandGraphWithCheckers(C, Dst, Src);
+}
+
+void CheckerManager::runCheckersForEndAnalysis(ExplodedGraph &G,
+ BugReporter &BR,
+ ExprEngine &Eng) {
+ for (unsigned i = 0, e = EndAnalysisCheckers.size(); i != e; ++i)
+ EndAnalysisCheckers[i](G, BR, Eng);
+}
+
+/// \brief Run checkers for end of path.
+void CheckerManager::runCheckersForEndPath(EndOfFunctionNodeBuilder &B,
+ ExprEngine &Eng) {
+ for (unsigned i = 0, e = EndPathCheckers.size(); i != e; ++i) {
+ CheckEndPathFunc fn = EndPathCheckers[i];
+ EndOfFunctionNodeBuilder specialB = B.withCheckerTag(fn.Checker);
+ fn(specialB, Eng);
+ }
+}
+
+/// \brief Run checkers for live symbols.
+void CheckerManager::runCheckersForLiveSymbols(const GRState *state,
+ SymbolReaper &SymReaper) {
+ for (unsigned i = 0, e = LiveSymbolsCheckers.size(); i != e; ++i)
+ LiveSymbolsCheckers[i](state, SymReaper);
+}
+
+namespace {
+ struct CheckDeadSymbolsContext {
+ typedef std::vector<CheckerManager::CheckDeadSymbolsFunc> CheckersTy;
+ const CheckersTy &Checkers;
+ SymbolReaper &SR;
+ const Stmt *S;
+ ExprEngine &Eng;
+
+ CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
+ CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
+
+ CheckDeadSymbolsContext(const CheckersTy &checkers, SymbolReaper &sr,
+ const Stmt *s, ExprEngine &eng)
+ : Checkers(checkers), SR(sr), S(s), Eng(eng) { }
+
+ void runChecker(CheckerManager::CheckDeadSymbolsFunc checkFn,
+ ExplodedNodeSet &Dst, ExplodedNode *Pred) {
+ CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker,
+ ProgramPoint::PostPurgeDeadSymbolsKind, 0, S);
+ checkFn(SR, C);
+ }
+ };
+}
+
+/// \brief Run checkers for dead symbols.
+void CheckerManager::runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ SymbolReaper &SymReaper,
+ const Stmt *S,
+ ExprEngine &Eng) {
+ CheckDeadSymbolsContext C(DeadSymbolsCheckers, SymReaper, S, Eng);
+ expandGraphWithCheckers(C, Dst, Src);
+}
+
+/// \brief True if at least one checker wants to check region changes.
+bool CheckerManager::wantsRegionChangeUpdate(const GRState *state) {
+ for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i)
+ if (RegionChangesCheckers[i].WantUpdateFn(state))
+ return true;
+
+ return false;
+}
+
+/// \brief Run checkers for region changes.
+const GRState *
+CheckerManager::runCheckersForRegionChanges(const GRState *state,
+ const MemRegion * const *Begin,
+ const MemRegion * const *End) {
+ for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) {
+ // If any checker declares the state infeasible (or if it starts that way),
+ // bail out.
+ if (!state)
+ return NULL;
+ state = RegionChangesCheckers[i].CheckFn(state, Begin, End);
}
+ return state;
}
-void CheckerManager::_registerForDecl(CheckerRef checker, CheckDeclFunc checkfn,
+/// \brief Run checkers for evaluating a call.
+/// Only one checker will evaluate the call.
+void CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ const CallExpr *CE,
+ ExprEngine &Eng,
+ GraphExpander *defaultEval) {
+ if (EvalCallCheckers.empty() && defaultEval == 0) {
+ Dst.insert(Src);
+ return;
+ }
+
+ for (ExplodedNodeSet::iterator
+ NI = Src.begin(), NE = Src.end(); NI != NE; ++NI) {
+
+ ExplodedNode *Pred = *NI;
+ bool anyEvaluated = false;
+ for (std::vector<EvalCallFunc>::iterator
+ EI = EvalCallCheckers.begin(), EE = EvalCallCheckers.end();
+ EI != EE; ++EI) {
+ ExplodedNodeSet checkDst;
+ CheckerContext C(checkDst, Eng.getBuilder(), Eng, Pred, EI->Checker,
+ ProgramPoint::PostStmtKind, 0, CE);
+ bool evaluated = (*EI)(CE, C);
+ assert(!(evaluated && anyEvaluated)
+ && "There are more than one checkers evaluating the call");
+ if (evaluated) {
+ anyEvaluated = true;
+ Dst.insert(checkDst);
+#ifdef NDEBUG
+ break; // on release don't check that no other checker also evals.
+#endif
+ }
+ }
+
+ if (!anyEvaluated) {
+ if (defaultEval)
+ defaultEval->expandGraph(Dst, Pred);
+ else
+ Dst.insert(Pred);
+ }
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Internal registration functions for AST traversing.
+//===----------------------------------------------------------------------===//
+
+void CheckerManager::_registerForDecl(CheckDeclFunc checkfn,
HandlesDeclFunc isForDeclFn) {
- DeclCheckerInfo info = { checker, checkfn, isForDeclFn };
+ DeclCheckerInfo info = { checkfn, isForDeclFn };
DeclCheckers.push_back(info);
}
-void CheckerManager::_registerForBody(CheckerRef checker,
- CheckDeclFunc checkfn) {
- BodyCheckers.push_back(std::make_pair(checker, checkfn));
+void CheckerManager::_registerForBody(CheckDeclFunc checkfn) {
+ BodyCheckers.push_back(checkfn);
}
-void CheckerManager::registerCheckersToEngine(ExprEngine &eng) {
- for (unsigned i = 0, e = Funcs.size(); i != e; ++i)
- Funcs[i](eng);
+//===----------------------------------------------------------------------===//
+// Internal registration functions for path-sensitive checking.
+//===----------------------------------------------------------------------===//
+
+void CheckerManager::_registerForPreStmt(CheckStmtFunc checkfn,
+ HandlesStmtFunc isForStmtFn) {
+ StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/true };
+ StmtCheckers.push_back(info);
+}
+void CheckerManager::_registerForPostStmt(CheckStmtFunc checkfn,
+ HandlesStmtFunc isForStmtFn) {
+ StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/false };
+ StmtCheckers.push_back(info);
}
-CheckerManager::~CheckerManager() {
- for (unsigned i = 0, e = Checkers.size(); i != e; ++i) {
- CheckerRef checker = Checkers[i].first;
- Dtor dtor = Checkers[i].second;
- dtor(checker);
+void CheckerManager::_registerForPreObjCMessage(CheckObjCMessageFunc checkfn) {
+ PreObjCMessageCheckers.push_back(checkfn);
+}
+void CheckerManager::_registerForPostObjCMessage(CheckObjCMessageFunc checkfn) {
+ PostObjCMessageCheckers.push_back(checkfn);
+}
+
+void CheckerManager::_registerForLocation(CheckLocationFunc checkfn) {
+ LocationCheckers.push_back(checkfn);
+}
+
+void CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) {
+ EndAnalysisCheckers.push_back(checkfn);
+}
+
+void CheckerManager::_registerForEndPath(CheckEndPathFunc checkfn) {
+ EndPathCheckers.push_back(checkfn);
+}
+
+void CheckerManager::_registerForLiveSymbols(CheckLiveSymbolsFunc checkfn) {
+ LiveSymbolsCheckers.push_back(checkfn);
+}
+
+void CheckerManager::_registerForDeadSymbols(CheckDeadSymbolsFunc checkfn) {
+ DeadSymbolsCheckers.push_back(checkfn);
+}
+
+void CheckerManager::_registerForRegionChanges(CheckRegionChangesFunc checkfn,
+ WantsRegionChangeUpdateFunc wantUpdateFn) {
+ RegionChangesCheckerInfo info = {checkfn, wantUpdateFn};
+ RegionChangesCheckers.push_back(info);
+}
+
+void CheckerManager::_registerForEvalCall(EvalCallFunc checkfn) {
+ EvalCallCheckers.push_back(checkfn);
+}
+
+//===----------------------------------------------------------------------===//
+// Implementation details.
+//===----------------------------------------------------------------------===//
+
+CheckerManager::CachedStmtCheckers *
+CheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) {
+ assert(S);
+
+ CachedStmtCheckersKey key(S->getStmtClass(), isPreVisit);
+ CachedStmtCheckers *checkers = 0;
+ CachedStmtCheckersMapTy::iterator CCI = CachedStmtCheckersMap.find(key);
+ if (CCI != CachedStmtCheckersMap.end()) {
+ checkers = &(CCI->second);
+ } else {
+ // Find the checkers that should run for this Stmt and cache them.
+ checkers = &CachedStmtCheckersMap[key];
+ for (unsigned i = 0, e = StmtCheckers.size(); i != e; ++i) {
+ StmtCheckerInfo &info = StmtCheckers[i];
+ if (info.IsPreVisit == isPreVisit && info.IsForStmtFn(S))
+ checkers->push_back(info.CheckFn);
+ }
}
+
+ assert(checkers);
+ return checkers;
+}
+
+CheckerManager::~CheckerManager() {
+ for (unsigned i = 0, e = CheckerDtors.size(); i != e; ++i)
+ CheckerDtors[i]();
}
// Anchor for the vtable.
CheckerProvider::~CheckerProvider() { }
+
+// Anchor for the vtable.
+GraphExpander::~GraphExpander() { }
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
index 070042a..08a2068 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
@@ -718,13 +718,14 @@ EndOfFunctionNodeBuilder::~EndOfFunctionNodeBuilder() {
}
ExplodedNode*
-EndOfFunctionNodeBuilder::generateNode(const GRState* State, const void *tag,
- ExplodedNode* P) {
+EndOfFunctionNodeBuilder::generateNode(const GRState* State,
+ ExplodedNode* P, const void *tag) {
hasGeneratedNode = true;
bool IsNew;
ExplodedNode* Node = Eng.G->getNode(BlockEntrance(&B,
- Pred->getLocationContext(), tag), State, &IsNew);
+ Pred->getLocationContext(), tag ? tag : Tag),
+ State, &IsNew);
Node->addPredecessor(P ? P : Pred, *Eng.G);
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp
index ecaff29..1bffa30 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp
@@ -32,6 +32,11 @@ SVal Environment::getSVal(const Stmt *E, SValBuilder& svalBuilder) const {
switch (E->getStmtClass()) {
case Stmt::AddrLabelExprClass:
return svalBuilder.makeLoc(cast<AddrLabelExpr>(E));
+ case Stmt::OpaqueValueExprClass: {
+ const OpaqueValueExpr *ope = cast<OpaqueValueExpr>(E);
+ E = ope->getSourceExpr();
+ continue;
+ }
case Stmt::ParenExprClass:
// ParenExprs are no-ops.
E = cast<ParenExpr>(E)->getSubExpr();
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
index dbfebcc..e3e7ee9 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -175,7 +175,8 @@ public:
virtual void Initialize(ASTContext &Context) {
Ctx = &Context;
- checkerMgr.reset(registerCheckers(Opts, PP.getDiagnostics()));
+ checkerMgr.reset(registerCheckers(Opts, PP.getLangOptions(),
+ PP.getDiagnostics()));
Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(),
PP.getLangOptions(), PD,
CreateStoreMgr, CreateConstraintMgr,
@@ -339,9 +340,6 @@ static void ActionExprEngine(AnalysisConsumer &C, AnalysisManager& mgr,
return;
ExprEngine Eng(mgr, TF.take());
- if (C.Opts.EnableExperimentalInternalChecks)
- RegisterExperimentalInternalChecks(Eng);
-
RegisterNSErrorChecks(Eng.getBugReporter(), Eng, *D);
if (C.Opts.EnableExperimentalChecks)
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
index 6625729..677e20c 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
@@ -12,12 +12,14 @@
//===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h"
+#include "clang/StaticAnalyzer/Frontend/FrontendActions.h"
#include "../Checkers/ClangSACheckerProvider.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/CheckerProvider.h"
#include "clang/Frontend/AnalyzerOptions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Basic/Diagnostic.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallVector.h"
@@ -25,8 +27,9 @@ using namespace clang;
using namespace ento;
CheckerManager *ento::registerCheckers(const AnalyzerOptions &opts,
+ const LangOptions &langOpts,
Diagnostic &diags) {
- llvm::OwningPtr<CheckerManager> checkerMgr(new CheckerManager());
+ llvm::OwningPtr<CheckerManager> checkerMgr(new CheckerManager(langOpts));
llvm::SmallVector<CheckerOptInfo, 8> checkerOpts;
for (unsigned i = 0, e = opts.CheckersControlList.size(); i != e; ++i) {
@@ -48,3 +51,16 @@ CheckerManager *ento::registerCheckers(const AnalyzerOptions &opts,
return checkerMgr.take();
}
+
+void ento::printCheckerHelp(llvm::raw_ostream &OS) {
+ OS << "OVERVIEW: Clang Static Analyzer Checkers List\n";
+ OS << '\n';
+ OS << "USAGE: -analyzer-checker <check1,check2,...>\n";
+ OS << '\n';
+ OS << "CHECKERS:\n";
+
+ llvm::OwningPtr<CheckerProvider> provider(createClangSACheckerProvider());
+ provider->printHelp(OS);
+
+ // FIXME: Load CheckerProviders from plugins.
+}
OpenPOWER on IntegriCloud