aboutsummaryrefslogtreecommitdiff
path: root/include/clang
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2012-09-21 00:09:11 +0000
committerTed Kremenek <kremenek@apple.com>2012-09-21 00:09:11 +0000
commita43df9539644bf1c258e12710cd69d79b0b078cd (patch)
tree1c77ba3f0325a80410c1568dc939c1306e80491a /include/clang
parent445895a97ae3f1d7bad3480839d31ed3ebcc9c83 (diff)
Implement faux-body-synthesis of well-known functions in the static analyzer when
their implementations are unavailable. Start by simulating dispatch_sync(). This change is largely a bunch of plumbing around something very simple. We use AnalysisDeclContext to conjure up a fake function body (using the current ASTContext) when one does not exist. This is controlled under the analyzer-config option "faux-bodies", which is off by default. The plumbing in this patch is largely to pass the necessary machinery around. CallEvent needs the AnalysisDeclContextManager to get the function definition, as one may get conjured up lazily. BugReporter and PathDiagnosticLocation needed to be relaxed to handle invalid locations, as the conjured body has no real source locations. We do some primitive recovery in diagnostic generation to generate some reasonable locations (for arrows and events), but it can be improved. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@164339 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/clang')
-rw-r--r--include/clang/Analysis/AnalysisContext.h11
-rw-r--r--include/clang/StaticAnalyzer/Core/AnalyzerOptions.h4
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h3
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h12
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h33
5 files changed, 45 insertions, 18 deletions
diff --git a/include/clang/Analysis/AnalysisContext.h b/include/clang/Analysis/AnalysisContext.h
index 45dd24718a..0185e8b69a 100644
--- a/include/clang/Analysis/AnalysisContext.h
+++ b/include/clang/Analysis/AnalysisContext.h
@@ -376,12 +376,17 @@ class AnalysisDeclContextManager {
ContextMap Contexts;
LocationContextManager LocContexts;
CFG::BuildOptions cfgBuildOptions;
+
+ /// Flag to indicate whether or not bodies should be synthesized
+ /// for well-known functions.
+ bool SynthesizeBodies;
public:
AnalysisDeclContextManager(bool useUnoptimizedCFG = false,
bool addImplicitDtors = false,
bool addInitializers = false,
- bool addTemporaryDtors = false);
+ bool addTemporaryDtors = false,
+ bool synthesizeBodies = false);
~AnalysisDeclContextManager();
@@ -394,6 +399,10 @@ public:
CFG::BuildOptions &getCFGBuildOptions() {
return cfgBuildOptions;
}
+
+ /// Return true if faux bodies should be synthesized for well-known
+ /// functions.
+ bool synthesizeBodies() const { return SynthesizeBodies; }
const StackFrameContext *getStackFrame(AnalysisDeclContext *Ctx,
LocationContext const *Parent,
diff --git a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
index 718f54c75a..924bbf9d1c 100644
--- a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
+++ b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
@@ -231,6 +231,10 @@ public:
//
// This is controlled by "ipa-always-inline-size" analyzer-config option.
unsigned getAlwaysInlineSize() const;
+
+ /// Returns true if the analyzer engine should synthesize fake bodies
+ /// for well-known functions.
+ bool shouldSynthesizeBodies() const;
public:
AnalyzerOptions() : CXXMemberInliningMode() {
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
index 0e1d15253c..4d054df705 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
@@ -396,7 +396,8 @@ public:
PathDiagnosticConsumer &PC,
ArrayRef<BugReport *> &bugReports) {}
- bool RemoveUneededCalls(PathPieces &pieces, BugReport *R);
+ bool RemoveUneededCalls(PathPieces &pieces, BugReport *R,
+ PathDiagnosticCallPiece *CallWithLoc = 0);
void Register(BugType *BT);
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
index 43b39bf8f9..1ed975fc47 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
@@ -137,8 +137,6 @@ private:
Kind kind)
: K(kind), S(0), D(0), SM(&sm),
Loc(genLocation(L)), Range(genRange()) {
- assert(Loc.isValid());
- assert(Range.isValid());
}
FullSourceLoc
@@ -157,12 +155,14 @@ public:
PathDiagnosticLocation(const Stmt *s,
const SourceManager &sm,
LocationOrAnalysisDeclContext lac)
- : K(StmtK), S(s), D(0), SM(&sm),
+ : K(s->getLocStart().isValid() ? StmtK : SingleLocK),
+ S(K == StmtK ? s : 0),
+ D(0), SM(&sm),
Loc(genLocation(SourceLocation(), lac)),
Range(genRange(lac)) {
- assert(S);
- assert(Loc.isValid());
- assert(Range.isValid());
+ assert(K == SingleLocK || S);
+ assert(K == SingleLocK || Loc.isValid());
+ assert(K == SingleLocK || Range.isValid());
}
/// Create a location corresponding to the given declaration.
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
index 9dc9491cfd..1b9a33eb0b 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
@@ -20,6 +20,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/Analysis/AnalysisContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "llvm/ADT/PointerIntPair.h"
@@ -191,7 +192,8 @@ public:
/// \brief Returns the definition of the function or method that will be
/// called.
- virtual RuntimeDefinition getRuntimeDefinition() const = 0;
+ virtual RuntimeDefinition
+ getRuntimeDefinition(AnalysisDeclContextManager &M) const = 0;
/// \brief Returns the expression whose value will be the result of this call.
/// May be null.
@@ -364,11 +366,17 @@ public:
return cast<FunctionDecl>(CallEvent::getDecl());
}
- virtual RuntimeDefinition getRuntimeDefinition() const {
+ virtual RuntimeDefinition
+ getRuntimeDefinition(AnalysisDeclContextManager &M) const {
const FunctionDecl *FD = getDecl();
- // Note that hasBody() will fill FD with the definition FunctionDecl.
- if (FD && FD->hasBody(FD))
- return RuntimeDefinition(FD);
+ // Note that the AnalysisDeclContext will have the FunctionDecl with
+ // the definition (if one exists).
+ if (FD) {
+ AnalysisDeclContext *AD = M.getContext(FD);
+ if (AD->getBody())
+ return RuntimeDefinition(AD->getDecl());
+ }
+
return RuntimeDefinition();
}
@@ -468,7 +476,8 @@ public:
return BR->getDecl();
}
- virtual RuntimeDefinition getRuntimeDefinition() const {
+ virtual RuntimeDefinition
+ getRuntimeDefinition(AnalysisDeclContextManager &M) const {
return RuntimeDefinition(getBlockDecl());
}
@@ -510,7 +519,8 @@ public:
virtual const FunctionDecl *getDecl() const;
- virtual RuntimeDefinition getRuntimeDefinition() const;
+ virtual RuntimeDefinition
+ getRuntimeDefinition(AnalysisDeclContextManager &M) const;
virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
BindingsTy &Bindings) const;
@@ -552,7 +562,8 @@ public:
virtual const Expr *getCXXThisExpr() const;
- virtual RuntimeDefinition getRuntimeDefinition() const;
+ virtual RuntimeDefinition
+ getRuntimeDefinition(AnalysisDeclContextManager &M) const;
virtual Kind getKind() const { return CE_CXXMember; }
@@ -632,7 +643,8 @@ public:
virtual SourceRange getSourceRange() const { return Location; }
virtual unsigned getNumArgs() const { return 0; }
- virtual RuntimeDefinition getRuntimeDefinition() const;
+ virtual RuntimeDefinition
+ getRuntimeDefinition(AnalysisDeclContextManager &M) const;
/// \brief Returns the value of the implicit 'this' object.
virtual SVal getCXXThisVal() const;
@@ -838,7 +850,8 @@ public:
llvm_unreachable("Unknown message kind");
}
- virtual RuntimeDefinition getRuntimeDefinition() const;
+ virtual RuntimeDefinition
+ getRuntimeDefinition(AnalysisDeclContextManager &M) const;
virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
BindingsTy &Bindings) const;