summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer
diff options
context:
space:
mode:
authorArtem Dergachev <artem.dergachev@gmail.com>2018-08-01 01:58:15 +0000
committerArtem Dergachev <artem.dergachev@gmail.com>2018-08-01 01:58:15 +0000
commitb21b479653fdd3adc350c15f1ee69b078f717024 (patch)
tree569ed351c460c692c6edd3352c34f3f08eefda8f /clang/lib/StaticAnalyzer
parentc4581f4e92797db5fb8d15520ecbc3fa938f8b79 (diff)
downloadbcm5719-llvm-b21b479653fdd3adc350c15f1ee69b078f717024.tar.gz
bcm5719-llvm-b21b479653fdd3adc350c15f1ee69b078f717024.zip
[analyzer] CallEvent: Add helper methods for obtaining the callee stack frame.
Newly added methods allow reasoning about the stack frame of the call (as opposed to the stack frame on which the call was made, which was always available) - obtain the stack frame context, obtain parameter regions - even if the call is not going to be (or was not) inlined, i.e. even if the analysis has never actually entered the stack frame. Differential Revision: https://reviews.llvm.org/D49715 llvm-svn: 338474
Diffstat (limited to 'clang/lib/StaticAnalyzer')
-rw-r--r--clang/lib/StaticAnalyzer/Core/CallEvent.cpp63
1 files changed, 63 insertions, 0 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
index 8db7b06f186..fe9260e32dd 100644
--- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -27,6 +27,7 @@
#include "clang/AST/Type.h"
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/CFGStmtMap.h"
#include "clang/Analysis/ProgramPoint.h"
#include "clang/CrossTU/CrossTranslationUnit.h"
#include "clang/Basic/IdentifierTable.h"
@@ -166,6 +167,68 @@ bool CallEvent::isGlobalCFunction(StringRef FunctionName) const {
return CheckerContext::isCLibraryFunction(FD, FunctionName);
}
+AnalysisDeclContext *CallEvent::getCalleeAnalysisDeclContext() const {
+ const Decl *D = getDecl();
+
+ // If the callee is completely unknown, we cannot construct the stack frame.
+ if (!D)
+ return nullptr;
+
+ // FIXME: Skip virtual functions for now. There's no easy procedure to foresee
+ // the exact decl that should be used, especially when it's not a definition.
+ if (const Decl *RD = getRuntimeDefinition().getDecl())
+ if (RD != D)
+ return nullptr;
+
+ return LCtx->getAnalysisDeclContext()->getManager()->getContext(D);
+}
+
+const StackFrameContext *CallEvent::getCalleeStackFrame() const {
+ AnalysisDeclContext *ADC = getCalleeAnalysisDeclContext();
+ if (!ADC)
+ return nullptr;
+
+ const Expr *E = getOriginExpr();
+ if (!E)
+ return nullptr;
+
+ // Recover CFG block via reverse lookup.
+ // TODO: If we were to keep CFG element information as part of the CallEvent
+ // instead of doing this reverse lookup, we would be able to build the stack
+ // frame for non-expression-based calls, and also we wouldn't need the reverse
+ // lookup.
+ CFGStmtMap *Map = LCtx->getAnalysisDeclContext()->getCFGStmtMap();
+ const CFGBlock *B = Map->getBlock(E);
+ assert(B);
+
+ // Also recover CFG index by scanning the CFG block.
+ unsigned Idx = 0, Sz = B->size();
+ for (; Idx < Sz; ++Idx)
+ if (auto StmtElem = (*B)[Idx].getAs<CFGStmt>())
+ if (StmtElem->getStmt() == E)
+ break;
+ assert(Idx < Sz);
+
+ return ADC->getManager()->getStackFrame(ADC, LCtx, E, B, Idx);
+}
+
+const VarRegion *CallEvent::getParameterLocation(unsigned Index) const {
+ const StackFrameContext *SFC = getCalleeStackFrame();
+ // We cannot construct a VarRegion without a stack frame.
+ if (!SFC)
+ return nullptr;
+
+ const ParmVarDecl *PVD = parameters()[Index];
+ const VarRegion *VR =
+ State->getStateManager().getRegionManager().getVarRegion(PVD, SFC);
+
+ // This sanity check would fail if our parameter declaration doesn't
+ // correspond to the stack frame's function declaration.
+ assert(VR->getStackFrame() == SFC);
+
+ return VR;
+}
+
/// Returns true if a type is a pointer-to-const or reference-to-const
/// with no further indirection.
static bool isPointerToConst(QualType Ty) {
OpenPOWER on IntegriCloud