aboutsummaryrefslogtreecommitdiff
path: root/include/clang
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang')
-rw-r--r--include/clang/Analysis/ProgramPoint.h18
-rw-r--r--include/clang/Driver/CC1Options.td3
-rw-r--r--include/clang/Frontend/AnalyzerOptions.h2
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h7
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h11
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h4
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h13
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h15
8 files changed, 67 insertions, 6 deletions
diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h
index 413b3cf4ea..e7bcf19bde 100644
--- a/include/clang/Analysis/ProgramPoint.h
+++ b/include/clang/Analysis/ProgramPoint.h
@@ -51,7 +51,8 @@ public:
CallEnterKind,
CallExitKind,
MinPostStmtKind = PostStmtKind,
- MaxPostStmtKind = CallExitKind };
+ MaxPostStmtKind = CallExitKind,
+ EpsilonKind};
private:
std::pair<const void *, const void *> Data;
@@ -380,6 +381,21 @@ public:
}
};
+/// This is a meta program point, which should be skipped by all the diagnostic
+/// reasoning etc.
+class EpsilonPoint : public ProgramPoint {
+public:
+ EpsilonPoint(const LocationContext *L, const void *Data1,
+ const void *Data2 = 0, const ProgramPointTag *tag = 0)
+ : ProgramPoint(Data1, Data2, EpsilonKind, L, tag) {}
+
+ const void *getData() const { return getData1(); }
+
+ static bool classof(const ProgramPoint* Location) {
+ return Location->getKind() == EpsilonKind;
+ }
+};
+
/// ProgramPoints can be "tagged" as representing points specific to a given
/// analysis entity. Tags are abstract annotations, with an associated
/// description and potentially other information.
diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td
index e8ec822715..46c4ed89b5 100644
--- a/include/clang/Driver/CC1Options.td
+++ b/include/clang/Driver/CC1Options.td
@@ -98,6 +98,9 @@ def analyzer_ipa_EQ : Joined<"-analyzer-ipa=">, Alias<analyzer_ipa>;
def analyzer_inlining_mode : Separate<"-analyzer-inlining-mode">,
HelpText<"Specify the function selection heuristic used during inlining">;
def analyzer_inlining_mode_EQ : Joined<"-analyzer-inlining-mode=">, Alias<analyzer_inlining_mode>;
+
+def analyzer_retry_exhausted : Flag<"-analyzer-retry-exhausted">,
+ HelpText<"Re-analyze paths leading to exhausted nodes with a different strategy for better code coverage">;
def analyzer_max_nodes : Separate<"-analyzer-max-nodes">,
HelpText<"The maximum number of nodes the analyzer can generate (150000 default, 0 = no limit)">;
diff --git a/include/clang/Frontend/AnalyzerOptions.h b/include/clang/Frontend/AnalyzerOptions.h
index 4199df0b6e..f152f63968 100644
--- a/include/clang/Frontend/AnalyzerOptions.h
+++ b/include/clang/Frontend/AnalyzerOptions.h
@@ -99,6 +99,7 @@ public:
unsigned CFGAddInitializers : 1;
unsigned EagerlyTrimEGraph : 1;
unsigned PrintStats : 1;
+ unsigned RetryExhausted : 1;
unsigned InlineMaxStackDepth;
unsigned InlineMaxFunctionSize;
AnalysisInliningMode InliningMode;
@@ -123,6 +124,7 @@ public:
CFGAddInitializers = 0;
EagerlyTrimEGraph = 0;
PrintStats = 0;
+ RetryExhausted = 0;
// Cap the stack depth at 4 calls (5 stack frames, base + 4 calls).
InlineMaxStackDepth = 5;
InlineMaxFunctionSize = 200;
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
index 3e19b26328..b77e069041 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
@@ -91,6 +91,10 @@ public:
/// \brief The mode of function selection used during inlining.
AnalysisInliningMode InliningMode;
+ /// \brief Re-analyze paths leading to exhausted nodes with a different
+ /// strategy for better code coverage.
+ bool RetryExhausted;
+
public:
AnalysisManager(ASTContext &ctx, DiagnosticsEngine &diags,
const LangOptions &lang, PathDiagnosticConsumer *pd,
@@ -107,7 +111,8 @@ public:
AnalysisIPAMode ipa,
unsigned inlineMaxStack,
unsigned inlineMaxFunctionSize,
- AnalysisInliningMode inliningMode);
+ AnalysisInliningMode inliningMode,
+ bool retry);
/// Construct a clone of the given AnalysisManager with the given ASTContext
/// and DiagnosticsEngine.
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
index 18ad0078c6..a9a4ae4230 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
@@ -98,9 +98,6 @@ private:
CoreEngine(const CoreEngine&); // Do not implement.
CoreEngine& operator=(const CoreEngine&);
- void enqueueStmtNode(ExplodedNode *N,
- const CFGBlock *Block, unsigned Idx);
-
ExplodedNode *generateCallExitNode(ExplodedNode *N);
public:
@@ -132,6 +129,11 @@ public:
ProgramStateRef InitState,
ExplodedNodeSet &Dst);
+ /// Dispatch the work list item based on the given location information.
+ /// Use Pred parameter as the predecessor state.
+ void dispatchWorkItem(ExplodedNode* Pred, ProgramPoint Loc,
+ const WorkListUnit& WU);
+
// Functions for external checking of whether we have unfinished work
bool wasBlockAborted() const { return !blocksAborted.empty(); }
bool wasBlocksExhausted() const { return !blocksExhausted.empty(); }
@@ -170,6 +172,9 @@ public:
/// \brief enqueue the nodes corresponding to the end of function onto the
/// end of path / work list.
void enqueueEndOfFunction(ExplodedNodeSet &Set);
+
+ /// \brief Enqueue a single node created as a result of statement processing.
+ void enqueueStmtNode(ExplodedNode *N, const CFGBlock *Block, unsigned Idx);
};
// TODO: Turn into a calss.
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
index 1c81af9586..46fbb88212 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
@@ -173,6 +173,10 @@ public:
bool isSink() const { return Succs.getFlag(); }
+ bool hasSinglePred() const {
+ return (pred_size() == 1);
+ }
+
ExplodedNode *getFirstPred() {
return pred_empty() ? NULL : *(pred_begin());
}
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index e8c4688293..2c144109b2 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -20,6 +20,7 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"
@@ -455,7 +456,19 @@ private:
ProgramStateRef St, SVal location,
const ProgramPointTag *tag, bool isLoad);
+ bool shouldInlineDecl(const FunctionDecl *FD, ExplodedNode *Pred);
bool InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE, ExplodedNode *Pred);
+
+ bool replayWithoutInlining(ExplodedNode *P, const LocationContext *CalleeLC);
+};
+
+/// Traits for storing the call processing policy inside GDM.
+/// The GDM stores the corresponding CallExpr pointer.
+struct ReplayWithoutInlining{};
+template <>
+struct ProgramStateTrait<ReplayWithoutInlining> :
+ public ProgramStatePartialTrait<void*> {
+ static void *GDMIndex() { static int index = 0; return &index; }
};
} // end ento namespace
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h
index e79b593584..1c7bedb82f 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h
@@ -176,7 +176,20 @@ namespace ento {
return (void*) (uintptr_t) d;
}
};
-
+
+ // Partial specialization for void*.
+ template <> struct ProgramStatePartialTrait<void*> {
+ typedef void *data_type;
+
+ static inline data_type MakeData(void *const* p) {
+ return p ? *p
+ : data_type();
+ }
+ static inline void *MakeVoidPtr(data_type d) {
+ return d;
+ }
+ };
+
} // end GR namespace
} // end clang namespace