summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
diff options
context:
space:
mode:
authorGabor Horvath <xazax.hun@gmail.com>2015-09-11 16:55:01 +0000
committerGabor Horvath <xazax.hun@gmail.com>2015-09-11 16:55:01 +0000
commit15843343b67a37c8859bd7f84d2f34b0f7eead85 (patch)
treed78eac474e240b69e50692102685ac4a4dd54113 /clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
parent62921286982916bf03158f31fb053882faee7bf1 (diff)
downloadbcm5719-llvm-15843343b67a37c8859bd7f84d2f34b0f7eead85.tar.gz
bcm5719-llvm-15843343b67a37c8859bd7f84d2f34b0f7eead85.zip
[Static Analyzer] Lambda support.
Differential Revision: http://reviews.llvm.org/D12652 llvm-svn: 247426
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core/ExprEngine.cpp')
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngine.cpp40
1 files changed, 37 insertions, 3 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index d4f2e40605f..00d9c7a9616 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -769,7 +769,6 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::SEHTryStmtClass:
case Stmt::SEHExceptStmtClass:
case Stmt::SEHLeaveStmtClass:
- case Stmt::LambdaExprClass:
case Stmt::SEHFinallyStmtClass: {
const ExplodedNode *node = Bldr.generateSink(S, Pred, Pred->getState());
Engine.addAbortedBlock(node, currBldrCtx->getBlock());
@@ -1013,6 +1012,17 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
Bldr.addNodes(Dst);
break;
+ case Stmt::LambdaExprClass:
+ if (AMgr.options.shouldInlineLambdas()) {
+ Bldr.takeNodes(Pred);
+ VisitLambdaExpr(cast<LambdaExpr>(S), Pred, Dst);
+ Bldr.addNodes(Dst);
+ } else {
+ const ExplodedNode *node = Bldr.generateSink(S, Pred, Pred->getState());
+ Engine.addAbortedBlock(node, currBldrCtx->getBlock());
+ }
+ break;
+
case Stmt::BinaryOperatorClass: {
const BinaryOperator* B = cast<BinaryOperator>(S);
if (B->isLogicalOp()) {
@@ -1853,11 +1863,35 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
// C permits "extern void v", and if you cast the address to a valid type,
// you can even do things with it. We simply pretend
assert(Ex->isGLValue() || VD->getType()->isVoidType());
- SVal V = state->getLValue(VD, Pred->getLocationContext());
+ const LocationContext *LocCtxt = Pred->getLocationContext();
+ const Decl *D = LocCtxt->getDecl();
+ const auto *MD = D ? dyn_cast<CXXMethodDecl>(D) : nullptr;
+ const auto *DeclRefEx = dyn_cast<DeclRefExpr>(Ex);
+ SVal V;
+ bool CaptureByReference = false;
+ if (AMgr.options.shouldInlineLambdas() && DeclRefEx &&
+ DeclRefEx->refersToEnclosingVariableOrCapture() && MD &&
+ MD->getParent()->isLambda()) {
+ // Lookup the field of the lambda.
+ const CXXRecordDecl *CXXRec = MD->getParent();
+ llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields;
+ FieldDecl *LambdaThisCaptureField;
+ CXXRec->getCaptureFields(LambdaCaptureFields, LambdaThisCaptureField);
+ const FieldDecl *FD = LambdaCaptureFields[VD];
+ Loc CXXThis =
+ svalBuilder.getCXXThis(MD, LocCtxt->getCurrentStackFrame());
+ SVal CXXThisVal = state->getSVal(CXXThis);
+ V = state->getLValue(FD, CXXThisVal);
+ if (FD->getType()->isReferenceType() &&
+ !VD->getType()->isReferenceType())
+ CaptureByReference = true;
+ } else {
+ V = state->getLValue(VD, LocCtxt);
+ }
// For references, the 'lvalue' is the pointer address stored in the
// reference region.
- if (VD->getType()->isReferenceType()) {
+ if (VD->getType()->isReferenceType() || CaptureByReference) {
if (const MemRegion *R = V.getAsRegion())
V = state->getSVal(R);
else
OpenPOWER on IntegriCloud