aboutsummaryrefslogtreecommitdiff
path: root/include/clang/StaticAnalyzer
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2013-12-22 00:07:40 +0000
committerDimitry Andric <dim@FreeBSD.org>2013-12-22 00:07:40 +0000
commitbfef399519ca9b8a4b4c6b563253bad7e0eeffe0 (patch)
treedf8df0b0067b381eab470a3b8f28d14a552a6340 /include/clang/StaticAnalyzer
parent6a0372513edbc473b538d2f724efac50405d6fef (diff)
downloadsrc-bfef399519ca9b8a4b4c6b563253bad7e0eeffe0.tar.gz
src-bfef399519ca9b8a4b4c6b563253bad7e0eeffe0.zip
Vendor import of clang release_34 branch r197841 (effectively, 3.4 RC3):vendor/clang/clang-release_34-r197841
Notes
Notes: svn path=/vendor/clang/dist/; revision=259701 svn path=/vendor/clang/clang-release_34-r197841/; revision=259703; tag=vendor/clang/clang-release_34-r197841
Diffstat (limited to 'include/clang/StaticAnalyzer')
-rw-r--r--include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h223
-rw-r--r--include/clang/StaticAnalyzer/Core/Analyses.def12
-rw-r--r--include/clang/StaticAnalyzer/Core/AnalyzerOptions.h25
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h19
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/BugType.h11
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h (renamed from include/clang/StaticAnalyzer/Checkers/CommonBugCategories.h)11
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h56
-rw-r--r--include/clang/StaticAnalyzer/Core/Checker.h63
-rw-r--r--include/clang/StaticAnalyzer/Core/CheckerManager.h64
-rw-r--r--include/clang/StaticAnalyzer/Core/CheckerRegistry.h7
-rw-r--r--include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h18
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h4
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h33
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h2
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h6
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h48
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h22
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h3
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h2
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/Store.h19
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h2
21 files changed, 468 insertions, 182 deletions
diff --git a/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h b/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h
new file mode 100644
index 000000000000..5978299701cf
--- /dev/null
+++ b/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h
@@ -0,0 +1,223 @@
+//==-- ObjCRetainCount.h - Retain count summaries for Cocoa -------*- C++ -*--//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the core data structures for retain count "summaries"
+// for Objective-C and Core Foundation APIs. These summaries are used
+// by the static analyzer to summarize the retain/release effects of
+// function and method calls. This drives a path-sensitive typestate
+// analysis in the static analyzer, but can also potentially be used by
+// other clients.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_OBJCRETAINCOUNT_H
+#define LLVM_CLANG_OBJCRETAINCOUNT_H
+
+namespace clang { namespace ento { namespace objc_retain {
+
+/// An ArgEffect summarizes the retain count behavior on an argument or receiver
+/// to a function or method.
+enum ArgEffect {
+ /// There is no effect.
+ DoNothing,
+
+ /// The argument is treated as if an -autorelease message had been sent to
+ /// the referenced object.
+ Autorelease,
+
+ /// The argument is treated as if an -dealloc message had been sent to
+ /// the referenced object.
+ Dealloc,
+
+ /// The argument has its reference count decreased by 1. This is as
+ /// if CFRelease has been called on the argument.
+ DecRef,
+
+ /// The argument has its reference count decreased by 1. This is as
+ /// if a -release message has been sent to the argument. This differs
+ /// in behavior from DecRef when GC is enabled.
+ DecRefMsg,
+
+ /// The argument has its reference count decreased by 1 to model
+ /// a transferred bridge cast under ARC.
+ DecRefBridgedTransferred,
+
+ /// The argument has its reference count increased by 1. This is as
+ /// if a -retain message has been sent to the argument. This differs
+ /// in behavior from IncRef when GC is enabled.
+ IncRefMsg,
+
+ /// The argument has its reference count increased by 1. This is as
+ /// if CFRetain has been called on the argument.
+ IncRef,
+
+ /// The argument acts as if has been passed to CFMakeCollectable, which
+ /// transfers the object to the Garbage Collector under GC.
+ MakeCollectable,
+
+ /// The argument is treated as potentially escaping, meaning that
+ /// even when its reference count hits 0 it should be treated as still
+ /// possibly being alive as someone else *may* be holding onto the object.
+ MayEscape,
+
+ /// All typestate tracking of the object ceases. This is usually employed
+ /// when the effect of the call is completely unknown.
+ StopTracking,
+
+ /// All typestate tracking of the object ceases. Unlike StopTracking,
+ /// this is also enforced when the method body is inlined.
+ ///
+ /// In some cases, we obtain a better summary for this checker
+ /// by looking at the call site than by inlining the function.
+ /// Signifies that we should stop tracking the symbol even if
+ /// the function is inlined.
+ StopTrackingHard,
+
+ /// Performs the combined functionality of DecRef and StopTrackingHard.
+ ///
+ /// The models the effect that the called function decrements the reference
+ /// count of the argument and all typestate tracking on that argument
+ /// should cease.
+ DecRefAndStopTrackingHard,
+
+ /// Performs the combined functionality of DecRefMsg and StopTrackingHard.
+ ///
+ /// The models the effect that the called function decrements the reference
+ /// count of the argument and all typestate tracking on that argument
+ /// should cease.
+ DecRefMsgAndStopTrackingHard
+};
+
+/// RetEffect summarizes a call's retain/release behavior with respect
+/// to its return value.
+class RetEffect {
+public:
+ enum Kind {
+ /// Indicates that no retain count information is tracked for
+ /// the return value.
+ NoRet,
+ /// Indicates that the returned value is an owned (+1) symbol.
+ OwnedSymbol,
+ /// Indicates that the returned value is an owned (+1) symbol and
+ /// that it should be treated as freshly allocated.
+ OwnedAllocatedSymbol,
+ /// Indicates that the returned value is an object with retain count
+ /// semantics but that it is not owned (+0). This is the default
+ /// for getters, etc.
+ NotOwnedSymbol,
+ /// Indicates that the object is not owned and controlled by the
+ /// Garbage collector.
+ GCNotOwnedSymbol,
+ /// Indicates that the object is not owned and controlled by ARC.
+ ARCNotOwnedSymbol,
+ /// Indicates that the return value is an owned object when the
+ /// receiver is also a tracked object.
+ OwnedWhenTrackedReceiver,
+ // Treat this function as returning a non-tracked symbol even if
+ // the function has been inlined. This is used where the call
+ // site summary is more presise than the summary indirectly produced
+ // by inlining the function
+ NoRetHard
+ };
+
+ /// Determines the object kind of a tracked object.
+ enum ObjKind {
+ /// Indicates that the tracked object is a CF object. This is
+ /// important between GC and non-GC code.
+ CF,
+ /// Indicates that the tracked object is an Objective-C object.
+ ObjC,
+ /// Indicates that the tracked object could be a CF or Objective-C object.
+ AnyObj
+ };
+
+private:
+ Kind K;
+ ObjKind O;
+
+ RetEffect(Kind k, ObjKind o = AnyObj) : K(k), O(o) {}
+
+public:
+ Kind getKind() const { return K; }
+
+ ObjKind getObjKind() const { return O; }
+
+ bool isOwned() const {
+ return K == OwnedSymbol || K == OwnedAllocatedSymbol ||
+ K == OwnedWhenTrackedReceiver;
+ }
+
+ bool notOwned() const {
+ return K == NotOwnedSymbol || K == ARCNotOwnedSymbol;
+ }
+
+ bool operator==(const RetEffect &Other) const {
+ return K == Other.K && O == Other.O;
+ }
+
+ static RetEffect MakeOwnedWhenTrackedReceiver() {
+ return RetEffect(OwnedWhenTrackedReceiver, ObjC);
+ }
+
+ static RetEffect MakeOwned(ObjKind o, bool isAllocated = false) {
+ return RetEffect(isAllocated ? OwnedAllocatedSymbol : OwnedSymbol, o);
+ }
+ static RetEffect MakeNotOwned(ObjKind o) {
+ return RetEffect(NotOwnedSymbol, o);
+ }
+ static RetEffect MakeGCNotOwned() {
+ return RetEffect(GCNotOwnedSymbol, ObjC);
+ }
+ static RetEffect MakeARCNotOwned() {
+ return RetEffect(ARCNotOwnedSymbol, ObjC);
+ }
+ static RetEffect MakeNoRet() {
+ return RetEffect(NoRet);
+ }
+ static RetEffect MakeNoRetHard() {
+ return RetEffect(NoRetHard);
+ }
+};
+
+/// Encapsulates the retain count semantics on the arguments, return value,
+/// and receiver (if any) of a function/method call.
+///
+/// Note that construction of these objects is not highly efficient. That
+/// is okay for clients where creating these objects isn't really a bottleneck.
+/// The purpose of the API is to provide something simple. The actual
+/// static analyzer checker that implements retain/release typestate
+/// tracking uses something more efficient.
+class CallEffects {
+ llvm::SmallVector<ArgEffect, 10> Args;
+ RetEffect Ret;
+ ArgEffect Receiver;
+
+ CallEffects(const RetEffect &R) : Ret(R) {}
+
+public:
+ /// Returns the argument effects for a call.
+ llvm::ArrayRef<ArgEffect> getArgs() const { return Args; }
+
+ /// Returns the effects on the receiver.
+ ArgEffect getReceiver() const { return Receiver; }
+
+ /// Returns the effect on the return value.
+ RetEffect getReturnValue() const { return Ret; }
+
+ /// Return the CallEfect for a given Objective-C method.
+ static CallEffects getEffect(const ObjCMethodDecl *MD);
+
+ /// Return the CallEfect for a given C/C++ function.
+ static CallEffects getEffect(const FunctionDecl *FD);
+};
+
+}}}
+
+#endif
+
diff --git a/include/clang/StaticAnalyzer/Core/Analyses.def b/include/clang/StaticAnalyzer/Core/Analyses.def
index dc7945016b1a..3355f4b6949c 100644
--- a/include/clang/StaticAnalyzer/Core/Analyses.def
+++ b/include/clang/StaticAnalyzer/Core/Analyses.def
@@ -24,14 +24,14 @@ ANALYSIS_STORE(RegionStore, "region", "Use region-based analyzer store", CreateR
ANALYSIS_CONSTRAINTS(RangeConstraints, "range", "Use constraint tracking of concrete value ranges", CreateRangeConstraintManager)
#ifndef ANALYSIS_DIAGNOSTICS
-#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE)
+#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN)
#endif
-ANALYSIS_DIAGNOSTICS(HTML, "html", "Output analysis results using HTML", createHTMLDiagnosticConsumer, false)
-ANALYSIS_DIAGNOSTICS(PLIST, "plist", "Output analysis results using Plists", createPlistDiagnosticConsumer, true)
-ANALYSIS_DIAGNOSTICS(PLIST_MULTI_FILE, "plist-multi-file", "Output analysis results using Plists (allowing for mult-file bugs)", createPlistMultiFileDiagnosticConsumer, true)
-ANALYSIS_DIAGNOSTICS(PLIST_HTML, "plist-html", "Output analysis results using HTML wrapped with Plists", createPlistHTMLDiagnosticConsumer, true)
-ANALYSIS_DIAGNOSTICS(TEXT, "text", "Text output of analysis results", createTextPathDiagnosticConsumer, true)
+ANALYSIS_DIAGNOSTICS(HTML, "html", "Output analysis results using HTML", createHTMLDiagnosticConsumer)
+ANALYSIS_DIAGNOSTICS(PLIST, "plist", "Output analysis results using Plists", createPlistDiagnosticConsumer)
+ANALYSIS_DIAGNOSTICS(PLIST_MULTI_FILE, "plist-multi-file", "Output analysis results using Plists (allowing for mult-file bugs)", createPlistMultiFileDiagnosticConsumer)
+ANALYSIS_DIAGNOSTICS(PLIST_HTML, "plist-html", "Output analysis results using HTML wrapped with Plists", createPlistHTMLDiagnosticConsumer)
+ANALYSIS_DIAGNOSTICS(TEXT, "text", "Text output of analysis results", createTextPathDiagnosticConsumer)
#ifndef ANALYSIS_PURGE
#define ANALYSIS_PURGE(NAME, CMDFLAG, DESC)
diff --git a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
index fb35f518ef02..618782e5d78c 100644
--- a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
+++ b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
@@ -52,7 +52,7 @@ NumConstraints
/// AnalysisDiagClients - Set of available diagnostic clients for rendering
/// analysis results.
enum AnalysisDiagClients {
-#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN, AUTOCREAT) PD_##NAME,
+#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN) PD_##NAME,
#include "clang/StaticAnalyzer/Core/Analyses.def"
NUM_ANALYSIS_DIAG_CLIENTS
};
@@ -201,6 +201,9 @@ private:
/// \sa mayInlineCXXContainerCtorsAndDtors
Optional<bool> InlineCXXContainerCtorsAndDtors;
+ /// \sa mayInlineCXXSharedPtrDtor
+ Optional<bool> InlineCXXSharedPtrDtor;
+
/// \sa mayInlineObjCMethod
Optional<bool> ObjCInliningMode;
@@ -223,6 +226,9 @@ private:
/// \sa shouldSuppressFromCXXStandardLibrary
Optional<bool> SuppressFromCXXStandardLibrary;
+ /// \sa reportIssuesInMainSourceFile
+ Optional<bool> ReportIssuesInMainSourceFile;
+
/// \sa getGraphTrimInterval
Optional<unsigned> GraphTrimInterval;
@@ -291,6 +297,16 @@ public:
/// accepts the values "true" and "false".
bool mayInlineCXXContainerCtorsAndDtors();
+ /// Returns whether or not the destructor of C++ 'shared_ptr' may be
+ /// considered for inlining.
+ ///
+ /// This covers std::shared_ptr, std::tr1::shared_ptr, and boost::shared_ptr,
+ /// and indeed any destructor named "~shared_ptr".
+ ///
+ /// This is controlled by the 'c++-shared_ptr-inlining' config option, which
+ /// accepts the values "true" and "false".
+ bool mayInlineCXXSharedPtrDtor();
+
/// Returns whether or not paths that go through null returns should be
/// suppressed.
///
@@ -326,6 +342,13 @@ public:
/// which accepts the values "true" and "false".
bool shouldSuppressFromCXXStandardLibrary();
+ /// Returns whether or not the diagnostic report should be always reported
+ /// in the main source file and not the headers.
+ ///
+ /// This is controlled by the 'report-in-main-source-file' config option,
+ /// which accepts the values "true" and "false".
+ bool shouldReportIssuesInMainSourceFile();
+
/// Returns whether irrelevant parts of a bug report path should be pruned
/// out of the final output.
///
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
index 5c560b2f0ec9..9584b8baf4f1 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
@@ -16,6 +16,7 @@
#define LLVM_CLANG_GR_BUGREPORTER
#include "clang/Basic/SourceLocation.h"
+#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h"
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
@@ -375,6 +376,7 @@ public:
virtual ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() = 0;
virtual ASTContext &getASTContext() = 0;
virtual SourceManager& getSourceManager() = 0;
+ virtual AnalyzerOptions& getAnalyzerOptions() = 0;
};
/// BugReporter is a utility class for generating PathDiagnostics for analysis.
@@ -442,6 +444,8 @@ public:
SourceManager& getSourceManager() { return D.getSourceManager(); }
+ AnalyzerOptions& getAnalyzerOptions() { return D.getAnalyzerOptions(); }
+
virtual bool generatePathDiagnostic(PathDiagnostic& pathDiagnostic,
PathDiagnosticConsumer &PC,
ArrayRef<BugReport *> &bugReports) {
@@ -462,20 +466,7 @@ public:
void EmitBasicReport(const Decl *DeclWithIssue,
StringRef BugName, StringRef BugCategory,
StringRef BugStr, PathDiagnosticLocation Loc,
- SourceRange* RangeBeg, unsigned NumRanges);
-
- void EmitBasicReport(const Decl *DeclWithIssue,
- StringRef BugName, StringRef BugCategory,
- StringRef BugStr, PathDiagnosticLocation Loc) {
- EmitBasicReport(DeclWithIssue, BugName, BugCategory, BugStr, Loc, 0, 0);
- }
-
- void EmitBasicReport(const Decl *DeclWithIssue,
- StringRef BugName, StringRef Category,
- StringRef BugStr, PathDiagnosticLocation Loc,
- SourceRange R) {
- EmitBasicReport(DeclWithIssue, BugName, Category, BugStr, Loc, &R, 1);
- }
+ ArrayRef<SourceRange> Ranges = None);
private:
llvm::StringMap<BugType *> StrBugTypes;
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
index 644aa3159301..49f9c83ba950 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_ANALYSIS_BUGTYPE
#define LLVM_CLANG_ANALYSIS_BUGTYPE
+#include "clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/FoldingSet.h"
#include <string>
@@ -31,10 +32,12 @@ private:
const std::string Name;
const std::string Category;
bool SuppressonSink;
+
+ virtual void anchor();
public:
BugType(StringRef name, StringRef cat)
: Name(name), Category(cat), SuppressonSink(false) {}
- virtual ~BugType();
+ virtual ~BugType() {}
// FIXME: Should these be made strings as well?
StringRef getName() const { return Name; }
@@ -50,14 +53,14 @@ public:
};
class BuiltinBug : public BugType {
- virtual void anchor();
const std::string desc;
+ virtual void anchor();
public:
BuiltinBug(const char *name, const char *description)
- : BugType(name, "Logic error"), desc(description) {}
+ : BugType(name, categories::LogicError), desc(description) {}
BuiltinBug(const char *name)
- : BugType(name, "Logic error"), desc(name) {}
+ : BugType(name, categories::LogicError), desc(name) {}
StringRef getDescription() const { return desc; }
};
diff --git a/include/clang/StaticAnalyzer/Checkers/CommonBugCategories.h b/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h
index 9d4251b1a757..3f0fe968cc11 100644
--- a/include/clang/StaticAnalyzer/Checkers/CommonBugCategories.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h
@@ -7,16 +7,17 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_STATIC_ANALYZER_CHECKER_CATEGORIES_H
-#define LLVM_CLANG_STATIC_ANALYZER_CHECKER_CATEGORIES_H
+#ifndef LLVM_CLANG_STATIC_ANALYZER_BUG_CATEGORIES_H
+#define LLVM_CLANG_STATIC_ANALYZER_BUG_CATEGORIES_H
// Common strings used for the "category" of many static analyzer issues.
namespace clang {
namespace ento {
namespace categories {
- extern const char *CoreFoundationObjectiveC;
- extern const char *MemoryCoreFoundationObjectiveC;
- extern const char *UnixAPI;
+ extern const char * const CoreFoundationObjectiveC;
+ extern const char * const LogicError;
+ extern const char * const MemoryCoreFoundationObjectiveC;
+ extern const char * const UnixAPI;
}
}
}
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
index a80b5a7a248c..b0670dad240d 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
@@ -38,6 +38,7 @@ class ParentMap;
class ProgramPoint;
class SourceManager;
class Stmt;
+class CallExpr;
namespace ento {
@@ -97,7 +98,6 @@ public:
enum PathGenerationScheme { None, Minimal, Extensive, AlternateExtensive };
virtual PathGenerationScheme getGenerationScheme() const { return Minimal; }
virtual bool supportsLogicalOpControlFlow() const { return false; }
- virtual bool supportsAllBlockEdges() const { return false; }
/// Return true if the PathDiagnosticConsumer supports individual
/// PathDiagnostics that span multiple files.
@@ -285,11 +285,13 @@ public:
void Profile(llvm::FoldingSetNodeID &ID) const;
+ void dump() const;
+
/// \brief Given an exploded node, retrieve the statement that should be used
/// for the diagnostic location.
static const Stmt *getStmt(const ExplodedNode *N);
- /// \brief Retrieve the statement corresponding to the sucessor node.
+ /// \brief Retrieve the statement corresponding to the successor node.
static const Stmt *getNextStmt(const ExplodedNode *N);
};
@@ -331,6 +333,10 @@ private:
const std::string str;
const Kind kind;
const DisplayHint Hint;
+
+ /// \brief In the containing bug report, this piece is the last piece from
+ /// the main source file.
+ bool LastInMainSourceFile;
/// A constant string that can be used to tag the PathDiagnosticPiece,
/// typically with the identification of the creator. The actual pointer
@@ -389,6 +395,16 @@ public:
ArrayRef<SourceRange> getRanges() const { return ranges; }
virtual void Profile(llvm::FoldingSetNodeID &ID) const;
+
+ void setAsLastInMainSourceFile() {
+ LastInMainSourceFile = true;
+ }
+
+ bool isLastInMainSourceFile() const {
+ return LastInMainSourceFile;
+ }
+
+ virtual void dump() const = 0;
};
@@ -403,6 +419,8 @@ public:
flattenTo(Result, Result, ShouldFlattenMacros);
return Result;
}
+
+ LLVM_ATTRIBUTE_USED void dump() const;
};
class PathDiagnosticSpotPiece : public PathDiagnosticPiece {
@@ -421,7 +439,7 @@ public:
PathDiagnosticLocation getLocation() const { return Pos; }
virtual void flattenLocations() { Pos.flatten(); }
-
+
virtual void Profile(llvm::FoldingSetNodeID &ID) const;
static bool classof(const PathDiagnosticPiece *P) {
@@ -504,7 +522,7 @@ public:
}
bool hasCallStackHint() {
- return (CallStackHint != 0);
+ return CallStackHint.isValid();
}
/// Produce the hint for the given node. The node contains
@@ -515,6 +533,8 @@ public:
return "";
}
+ virtual void dump() const;
+
static inline bool classof(const PathDiagnosticPiece *P) {
return P->getKind() == Event;
}
@@ -582,6 +602,8 @@ public:
static PathDiagnosticCallPiece *construct(PathPieces &pieces,
const Decl *caller);
+ virtual void dump() const;
+
virtual void Profile(llvm::FoldingSetNodeID &ID) const;
static inline bool classof(const PathDiagnosticPiece *P) {
@@ -649,7 +671,9 @@ public:
static inline bool classof(const PathDiagnosticPiece *P) {
return P->getKind() == ControlFlow;
}
-
+
+ virtual void dump() const;
+
virtual void Profile(llvm::FoldingSetNodeID &ID) const;
};
@@ -673,7 +697,9 @@ public:
static inline bool classof(const PathDiagnosticPiece *P) {
return P->getKind() == Macro;
}
-
+
+ virtual void dump() const;
+
virtual void Profile(llvm::FoldingSetNodeID &ID) const;
};
@@ -687,7 +713,10 @@ class PathDiagnostic : public llvm::FoldingSetNode {
std::string ShortDesc;
std::string Category;
std::deque<std::string> OtherDesc;
+
+ /// \brief Loc The location of the path diagnostic report.
PathDiagnosticLocation Loc;
+
PathPieces pathImpl;
SmallVector<PathPieces *, 3> pathStack;
@@ -735,12 +764,23 @@ public:
getActivePath().push_back(EndPiece);
}
+ void appendToDesc(StringRef S) {
+ if (!ShortDesc.empty())
+ ShortDesc.append(S);
+ VerboseDesc.append(S);
+ }
+
void resetPath() {
pathStack.clear();
pathImpl.clear();
Loc = PathDiagnosticLocation();
}
-
+
+ /// \brief If the last piece of the report point to the header file, resets
+ /// the location of the report to be the last location in the main source
+ /// file.
+ void resetDiagnosticLocationToMainFile();
+
StringRef getVerboseDescription() const { return VerboseDesc; }
StringRef getShortDescription() const {
return ShortDesc.empty() ? VerboseDesc : ShortDesc;
@@ -759,7 +799,7 @@ public:
void addMeta(StringRef s) { OtherDesc.push_back(s); }
PathDiagnosticLocation getLocation() const {
- assert(Loc.isValid() && "No end-of-path location set yet!");
+ assert(Loc.isValid() && "No report location set yet!");
return Loc;
}
diff --git a/include/clang/StaticAnalyzer/Core/Checker.h b/include/clang/StaticAnalyzer/Core/Checker.h
index 0dbaab033d2d..cf7cf051d225 100644
--- a/include/clang/StaticAnalyzer/Core/Checker.h
+++ b/include/clang/StaticAnalyzer/Core/Checker.h
@@ -320,18 +320,35 @@ public:
class PointerEscape {
template <typename CHECKER>
static ProgramStateRef
- _checkPointerEscape(void *checker,
+ _checkPointerEscape(void *Checker,
ProgramStateRef State,
const InvalidatedSymbols &Escaped,
const CallEvent *Call,
PointerEscapeKind Kind,
- bool IsConst) {
- if (!IsConst)
- return ((const CHECKER *)checker)->checkPointerEscape(State,
+ RegionAndSymbolInvalidationTraits *ETraits) {
+
+ if (!ETraits)
+ return ((const CHECKER *)Checker)->checkPointerEscape(State,
Escaped,
Call,
Kind);
- return State;
+
+ InvalidatedSymbols RegularEscape;
+ for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
+ E = Escaped.end(); I != E; ++I)
+ if (!ETraits->hasTrait(*I,
+ RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
+ !ETraits->hasTrait(*I,
+ RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
+ RegularEscape.insert(*I);
+
+ if (RegularEscape.empty())
+ return State;
+
+ return ((const CHECKER *)Checker)->checkPointerEscape(State,
+ RegularEscape,
+ Call,
+ Kind);
}
public:
@@ -346,18 +363,32 @@ public:
class ConstPointerEscape {
template <typename CHECKER>
static ProgramStateRef
- _checkConstPointerEscape(void *checker,
+ _checkConstPointerEscape(void *Checker,
ProgramStateRef State,
const InvalidatedSymbols &Escaped,
const CallEvent *Call,
PointerEscapeKind Kind,
- bool IsConst) {
- if (IsConst)
- return ((const CHECKER *)checker)->checkConstPointerEscape(State,
- Escaped,
- Call,
- Kind);
- return State;
+ RegionAndSymbolInvalidationTraits *ETraits) {
+
+ if (!ETraits)
+ return State;
+
+ InvalidatedSymbols ConstEscape;
+ for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
+ E = Escaped.end(); I != E; ++I)
+ if (ETraits->hasTrait(*I,
+ RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
+ !ETraits->hasTrait(*I,
+ RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
+ ConstEscape.insert(*I);
+
+ if (ConstEscape.empty())
+ return State;
+
+ return ((const CHECKER *)Checker)->checkConstPointerEscape(State,
+ ConstEscape,
+ Call,
+ Kind);
}
public:
@@ -502,10 +533,14 @@ struct ImplicitNullDerefEvent {
};
/// \brief A helper class which wraps a boolean value set to false by default.
+///
+/// This class should behave exactly like 'bool' except that it doesn't need to
+/// be explicitly initialized.
struct DefaultBool {
bool val;
DefaultBool() : val(false) {}
- operator bool() const { return val; }
+ /*implicit*/ operator bool&() { return val; }
+ /*implicit*/ operator const bool&() const { return val; }
DefaultBool &operator=(bool b) { val = b; return *this; }
};
diff --git a/include/clang/StaticAnalyzer/Core/CheckerManager.h b/include/clang/StaticAnalyzer/Core/CheckerManager.h
index b2411e6e6544..8ad67c118f01 100644
--- a/include/clang/StaticAnalyzer/Core/CheckerManager.h
+++ b/include/clang/StaticAnalyzer/Core/CheckerManager.h
@@ -19,7 +19,6 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/SmallVector.h"
#include <vector>
@@ -366,14 +365,16 @@ public:
/// \param Escaped The list of escaped symbols.
/// \param Call The corresponding CallEvent, if the symbols escape as
/// parameters to the given call.
- /// \param IsConst Specifies if the pointer is const.
+ /// \param Kind The reason of pointer escape.
+ /// \param ITraits Information about invalidation for a particular
+ /// region/symbol.
/// \returns Checkers can modify the state by returning a new one.
ProgramStateRef
runCheckersForPointerEscape(ProgramStateRef State,
const InvalidatedSymbols &Escaped,
const CallEvent *Call,
PointerEscapeKind Kind,
- bool IsConst = false);
+ RegionAndSymbolInvalidationTraits *ITraits);
/// \brief Run checkers for handling assumptions on symbolic values.
ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state,
@@ -465,7 +466,7 @@ public:
const InvalidatedSymbols &Escaped,
const CallEvent *Call,
PointerEscapeKind Kind,
- bool IsConst)>
+ RegionAndSymbolInvalidationTraits *ITraits)>
CheckPointerEscapeFunc;
typedef CheckerFn<ProgramStateRef (ProgramStateRef,
@@ -581,35 +582,12 @@ private:
};
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 SmallVector<CheckStmtFunc, 4> CachedStmtCheckers;
- typedef llvm::DenseMap<CachedStmtCheckersKey, CachedStmtCheckers>
- CachedStmtCheckersMapTy;
+ typedef llvm::DenseMap<unsigned, CachedStmtCheckers> CachedStmtCheckersMapTy;
CachedStmtCheckersMapTy CachedStmtCheckersMap;
- CachedStmtCheckers *getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit);
+ const CachedStmtCheckers &getCachedStmtCheckersFor(const Stmt *S,
+ bool isPreVisit);
std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers;
std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers;
@@ -659,30 +637,4 @@ private:
} // 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/include/clang/StaticAnalyzer/Core/CheckerRegistry.h b/include/clang/StaticAnalyzer/Core/CheckerRegistry.h
index 4557aa40ea80..ca68a74fef96 100644
--- a/include/clang/StaticAnalyzer/Core/CheckerRegistry.h
+++ b/include/clang/StaticAnalyzer/Core/CheckerRegistry.h
@@ -54,10 +54,6 @@
//
// For a complete working example, see examples/analyzer-plugin.
-
-namespace clang {
-namespace ento {
-
#ifndef CLANG_ANALYZER_API_VERSION_STRING
// FIXME: The Clang version string is not particularly granular;
// the analyzer infrastructure can change a lot between releases.
@@ -67,6 +63,9 @@ namespace ento {
#define CLANG_ANALYZER_API_VERSION_STRING CLANG_VERSION_STRING
#endif
+namespace clang {
+namespace ento {
+
class CheckerOptInfo;
/// Manages a set of available checkers for running a static analysis.
diff --git a/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h b/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h
index b856de7dc612..43e9166b3cdc 100644
--- a/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h
+++ b/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h
@@ -27,18 +27,12 @@ namespace ento {
class PathDiagnosticConsumer;
typedef std::vector<PathDiagnosticConsumer*> PathDiagnosticConsumers;
-#define CREATE_CONSUMER(NAME)\
-void create ## NAME ## DiagnosticConsumer(AnalyzerOptions &AnalyzerOpts,\
- PathDiagnosticConsumers &C,\
- const std::string& prefix,\
- const Preprocessor &PP);
-
-CREATE_CONSUMER(HTML)
-CREATE_CONSUMER(Plist)
-CREATE_CONSUMER(PlistMultiFile)
-CREATE_CONSUMER(TextPath)
-
-#undef CREATE_CONSUMER
+#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN)\
+void CREATEFN(AnalyzerOptions &AnalyzerOpts,\
+ PathDiagnosticConsumers &C,\
+ const std::string &Prefix,\
+ const Preprocessor &PP);
+#include "clang/StaticAnalyzer/Core/Analyses.def"
} // end 'ento' namespace
} // end 'clang' namespace
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
index 458c8966e79e..d7d83ce8b17d 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
@@ -65,6 +65,10 @@ public:
StoreManagerCreator getStoreManagerCreator() {
return CreateStoreMgr;
}
+
+ AnalyzerOptions& getAnalyzerOptions() {
+ return options;
+ }
ConstraintManagerCreator getConstraintManagerCreator() {
return CreateConstraintMgr;
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
index f990b8dcd0ec..cfaf085b5f34 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
@@ -228,11 +228,6 @@ public:
return false;
}
- /// \brief Returns true if this is a call to a variadic function or method.
- virtual bool isVariadic() const {
- return false;
- }
-
/// \brief Returns a source range for the entire call, suitable for
/// outputting in diagnostics.
virtual SourceRange getSourceRange() const {
@@ -341,6 +336,11 @@ public:
/// This will return a null QualType if the result type cannot be determined.
static QualType getDeclaredResultType(const Decl *D);
+ /// \brief Returns true if the given decl is known to be variadic.
+ ///
+ /// \p D must not be null.
+ static bool isVariadic(const Decl *D);
+
// Iterator access to formal parameters and their types.
private:
typedef std::const_mem_fun_t<QualType, ParmVarDecl> get_type_fun;
@@ -350,19 +350,13 @@ public:
/// Returns an iterator over the call's formal parameters.
///
- /// If UseDefinitionParams is set, this will return the parameter decls
- /// used in the callee's definition (suitable for inlining). Most of the
- /// time it is better to use the decl found by name lookup, which likely
- /// carries more annotations.
- ///
/// Remember that the number of formal parameters may not match the number
/// of arguments for all calls. However, the first parameter will always
/// correspond with the argument value returned by \c getArgSVal(0).
///
- /// If the call has no accessible declaration (or definition, if
- /// \p UseDefinitionParams is set), \c param_begin() will be equal to
- /// \c param_end().
- virtual param_iterator param_begin() const =0;
+ /// If the call has no accessible declaration, \c param_begin() will be equal
+ /// to \c param_end().
+ virtual param_iterator param_begin() const = 0;
/// \sa param_begin()
virtual param_iterator param_end() const = 0;
@@ -423,10 +417,6 @@ public:
return RuntimeDefinition();
}
- virtual bool isVariadic() const {
- return getDecl()->isVariadic();
- }
-
virtual bool argumentsMayEscape() const;
virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
@@ -527,10 +517,6 @@ public:
return RuntimeDefinition(getBlockDecl());
}
- virtual bool isVariadic() const {
- return getBlockDecl()->isVariadic();
- }
-
virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
BindingsTy &Bindings) const;
@@ -849,9 +835,6 @@ public:
virtual const Expr *getArgExpr(unsigned Index) const {
return getOriginExpr()->getArg(Index);
}
- virtual bool isVariadic() const {
- return getDecl()->isVariadic();
- }
bool isInstanceMessage() const {
return getOriginExpr()->isInstanceMessage();
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
index edcfc8a6c097..bf17cd807d65 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
@@ -184,7 +184,7 @@ public:
bool isSink() const { return Succs.getFlag(); }
- bool hasSinglePred() const {
+ bool hasSinglePred() const {
return (pred_size() == 1);
}
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index 33e4431eb4be..d89dffe63b0a 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -203,6 +203,8 @@ public:
void ProcessAutomaticObjDtor(const CFGAutomaticObjDtor D,
ExplodedNode *Pred, ExplodedNodeSet &Dst);
+ void ProcessDeleteDtor(const CFGDeleteDtor D,
+ ExplodedNode *Pred, ExplodedNodeSet &Dst);
void ProcessBaseDtor(const CFGBaseDtor D,
ExplodedNode *Pred, ExplodedNodeSet &Dst);
void ProcessMemberDtor(const CFGMemberDtor D,
@@ -476,14 +478,14 @@ protected:
SVal Loc, SVal Val);
/// Call PointerEscape callback when a value escapes as a result of
/// region invalidation.
- /// \param[in] IsConst Specifies that the pointer is const.
+ /// \param[in] ITraits Specifies invalidation traits for regions/symbols.
ProgramStateRef notifyCheckersOfPointerEscape(
ProgramStateRef State,
const InvalidatedSymbols *Invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
const CallEvent *Call,
- bool IsConst);
+ RegionAndSymbolInvalidationTraits &ITraits);
public:
// FIXME: 'tag' should be removed, and a LocationContext should be used
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
index 9b4f77dd679f..cc790c1b6b39 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
@@ -635,12 +635,14 @@ class BlockDataRegion : public TypedRegion {
friend class MemRegionManager;
const BlockTextRegion *BC;
const LocationContext *LC; // Can be null */
+ unsigned BlockCount;
void *ReferencedVars;
void *OriginalVars;
BlockDataRegion(const BlockTextRegion *bc, const LocationContext *lc,
- const MemRegion *sreg)
+ unsigned count, const MemRegion *sreg)
: TypedRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc),
+ BlockCount(count),
ReferencedVars(0), OriginalVars(0) {}
public:
@@ -692,7 +694,8 @@ public:
void Profile(llvm::FoldingSetNodeID& ID) const;
static void ProfileRegion(llvm::FoldingSetNodeID&, const BlockTextRegion *,
- const LocationContext *, const MemRegion *);
+ const LocationContext *, unsigned,
+ const MemRegion *);
static bool classof(const MemRegion* R) {
return R->getKind() == BlockDataRegionKind;
@@ -1270,7 +1273,13 @@ public:
/// argument is allowed to be NULL for cases where we have no known
/// context.
const BlockDataRegion *getBlockDataRegion(const BlockTextRegion *bc,
- const LocationContext *lc = NULL);
+ const LocationContext *lc,
+ unsigned blockCount);
+
+ /// Create a CXXTempObjectRegion for temporaries which are lifetime-extended
+ /// by static references. This differs from getCXXTempObjectRegion in the
+ /// super-region used.
+ const CXXTempObjectRegion *getCXXStaticTempObjectRegion(const Expr *Ex);
private:
template <typename RegionTy, typename A1>
@@ -1304,6 +1313,39 @@ private:
inline ASTContext &MemRegion::getContext() const {
return getMemRegionManager()->getContext();
}
+
+//===----------------------------------------------------------------------===//
+// Means for storing region/symbol handling traits.
+//===----------------------------------------------------------------------===//
+
+/// Information about invalidation for a particular region/symbol.
+class RegionAndSymbolInvalidationTraits {
+ typedef unsigned char StorageTypeForKinds;
+ llvm::DenseMap<const MemRegion *, StorageTypeForKinds> MRTraitsMap;
+ llvm::DenseMap<SymbolRef, StorageTypeForKinds> SymTraitsMap;
+
+ typedef llvm::DenseMap<const MemRegion *, StorageTypeForKinds>::const_iterator
+ const_region_iterator;
+ typedef llvm::DenseMap<SymbolRef, StorageTypeForKinds>::const_iterator
+ const_symbol_iterator;
+
+public:
+ /// \brief Describes different invalidation traits.
+ enum InvalidationKinds {
+ /// Tells that a region's contents is not changed.
+ TK_PreserveContents = 0x1,
+ /// Suppress pointer-escaping of a region.
+ TK_SuppressEscape = 0x2
+
+ // Do not forget to extend StorageTypeForKinds if number of traits exceed
+ // the number of bits StorageTypeForKinds can store.
+ };
+
+ void setTrait(SymbolRef Sym, InvalidationKinds IK);
+ void setTrait(const MemRegion *MR, InvalidationKinds IK);
+ bool hasTrait(SymbolRef Sym, InvalidationKinds IK);
+ bool hasTrait(const MemRegion *MR, InvalidationKinds IK);
+};
} // end GR namespace
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
index 42ef1db45591..03739ed9284d 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
@@ -232,22 +232,21 @@ public:
/// \param IS the set of invalidated symbols.
/// \param Call if non-null, the invalidated regions represent parameters to
/// the call and should be considered directly invalidated.
- /// \param ConstRegions the set of regions whose contents are accessible,
- /// even though the regions themselves should not be invalidated.
+ /// \param ITraits information about special handling for a particular
+ /// region/symbol.
ProgramStateRef
invalidateRegions(ArrayRef<const MemRegion *> Regions, const Expr *E,
unsigned BlockCount, const LocationContext *LCtx,
bool CausesPointerEscape, InvalidatedSymbols *IS = 0,
const CallEvent *Call = 0,
- ArrayRef<const MemRegion *> ConstRegions =
- ArrayRef<const MemRegion *>()) const;
+ RegionAndSymbolInvalidationTraits *ITraits = 0) const;
ProgramStateRef
invalidateRegions(ArrayRef<SVal> Regions, const Expr *E,
unsigned BlockCount, const LocationContext *LCtx,
bool CausesPointerEscape, InvalidatedSymbols *IS = 0,
const CallEvent *Call = 0,
- ArrayRef<SVal> ConstRegions = ArrayRef<SVal>()) const;
+ RegionAndSymbolInvalidationTraits *ITraits = 0) const;
/// enterStackFrame - Returns the state for entry to the given stack frame,
/// preserving the current state.
@@ -425,9 +424,9 @@ private:
const Expr *E, unsigned BlockCount,
const LocationContext *LCtx,
bool ResultsInSymbolEscape,
- InvalidatedSymbols &IS,
- const CallEvent *Call,
- ArrayRef<SVal> ConstValues) const;
+ InvalidatedSymbols *IS,
+ RegionAndSymbolInvalidationTraits *HTraits,
+ const CallEvent *Call) const;
};
//===----------------------------------------------------------------------===//
@@ -516,8 +515,8 @@ public:
public:
- SVal ArrayToPointer(Loc Array) {
- return StoreMgr->ArrayToPointer(Array);
+ SVal ArrayToPointer(Loc Array, QualType ElementTy) {
+ return StoreMgr->ArrayToPointer(Array, ElementTy);
}
// Methods that manipulate the GDM.
@@ -798,7 +797,7 @@ CB ProgramState::scanReachableSymbols(const MemRegion * const *beg,
/// A Utility class that allows to visit the reachable symbols using a custom
/// SymbolVisitor.
class ScanReachableSymbols {
- typedef llvm::DenseMap<const void*, unsigned> VisitedItems;
+ typedef llvm::DenseSet<const void*> VisitedItems;
VisitedItems visited;
ProgramStateRef state;
@@ -808,6 +807,7 @@ public:
ScanReachableSymbols(ProgramStateRef st, SymbolVisitor& v)
: state(st), visitor(v) {}
+ bool scan(nonloc::LazyCompoundVal val);
bool scan(nonloc::CompoundVal val);
bool scan(SVal val);
bool scan(const MemRegion *R);
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
index bbb56885af04..c5d0a92cabdd 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
@@ -200,7 +200,8 @@ public:
DefinedSVal getFunctionPointer(const FunctionDecl *func);
DefinedSVal getBlockPointer(const BlockDecl *block, CanQualType locTy,
- const LocationContext *locContext);
+ const LocationContext *locContext,
+ unsigned blockCount);
/// Returns the value of \p E, if it can be determined in a non-path-sensitive
/// manner.
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
index 326e784e83d4..5a426ef00197 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
@@ -290,7 +290,7 @@ public:
static inline bool isLocType(QualType T) {
return T->isAnyPointerType() || T->isBlockPointerType() ||
- T->isReferenceType();
+ T->isReferenceType() || T->isNullPtrType();
}
private:
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
index b219495d5f06..530dae59892a 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
@@ -111,7 +111,7 @@ public:
/// ArrayToPointer - Used by ExprEngine::VistCast to handle implicit
/// conversions between arrays and pointers.
- virtual SVal ArrayToPointer(Loc Array) = 0;
+ virtual SVal ArrayToPointer(Loc Array, QualType ElementTy) = 0;
/// Evaluates a chain of derived-to-base casts through the path specified in
/// \p Cast.
@@ -164,8 +164,6 @@ public:
/// the given regions. Optionally, invalidates non-static globals as well.
/// \param[in] store The initial store
/// \param[in] Values The values to invalidate.
- /// \param[in] ConstValues The values to invalidate; these are known to be
- /// const, so only regions accesible from them should be invalidated.
/// \param[in] E The current statement being evaluated. Used to conjure
/// symbols to mark the values of invalidated regions.
/// \param[in] Count The current block count. Used to conjure
@@ -174,13 +172,10 @@ public:
/// globals should get invalidated.
/// \param[in,out] IS A set to fill with any symbols that are no longer
/// accessible. Pass \c NULL if this information will not be used.
- /// \param[in,out] ConstIS A set to fill with any symbols corresponding to
- /// the ConstValues.
+ /// \param[in] ITraits Information about invalidation for a particular
+ /// region/symbol.
/// \param[in,out] InvalidatedTopLevel A vector to fill with regions
- //// explicitely being invalidated. Pass \c NULL if this
- /// information will not be used.
- /// \param[in,out] InvalidatedTopLevelConst A vector to fill with const
- //// regions explicitely being invalidated. Pass \c NULL if this
+ //// explicitly being invalidated. Pass \c NULL if this
/// information will not be used.
/// \param[in,out] Invalidated A vector to fill with any regions being
/// invalidated. This should include any regions explicitly invalidated
@@ -188,14 +183,12 @@ public:
/// information will not be used.
virtual StoreRef invalidateRegions(Store store,
ArrayRef<SVal> Values,
- ArrayRef<SVal> ConstValues,
const Expr *E, unsigned Count,
const LocationContext *LCtx,
const CallEvent *Call,
InvalidatedSymbols &IS,
- InvalidatedSymbols &ConstIS,
+ RegionAndSymbolInvalidationTraits &ITraits,
InvalidatedRegions *InvalidatedTopLevel,
- InvalidatedRegions *InvalidatedTopLevelConst,
InvalidatedRegions *Invalidated) = 0;
/// enterStackFrame - Let the StoreManager to do something when execution
@@ -231,7 +224,7 @@ public:
bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R,
SVal val);
- operator bool() { return First && Binding; }
+ LLVM_EXPLICIT operator bool() { return First && Binding; }
const MemRegion *getRegion() { return Binding; }
};
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
index d4100634a785..f653c70a30f3 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
@@ -134,7 +134,7 @@ public:
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
const CallEvent *Call,
- bool IsConst = false) = 0;
+ RegionAndSymbolInvalidationTraits &HTraits) = 0;
/// printState - Called by ProgramStateManager to print checker-specific data.
virtual void printState(raw_ostream &Out, ProgramStateRef State,