2011-08-20 05:59:58 +00:00
|
|
|
//===- ExprEngineCXX.cpp - ExprEngine support for C++ -----------*- C++ -*-===//
|
2010-04-19 12:51:02 +00:00
|
|
|
//
|
|
|
|
// 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 C++ expression evaluation engine.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2011-03-01 01:16:03 +00:00
|
|
|
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
|
2011-02-10 01:03:03 +00:00
|
|
|
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
|
|
|
|
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
|
2012-07-02 19:27:35 +00:00
|
|
|
#include "clang/StaticAnalyzer/Core/PathSensitive/Calls.h"
|
2010-04-19 12:51:02 +00:00
|
|
|
#include "clang/AST/DeclCXX.h"
|
2012-03-10 01:34:17 +00:00
|
|
|
#include "clang/AST/StmtCXX.h"
|
2010-04-19 12:51:02 +00:00
|
|
|
|
|
|
|
using namespace clang;
|
2010-12-23 07:20:52 +00:00
|
|
|
using namespace ento;
|
2010-04-19 12:51:02 +00:00
|
|
|
|
2011-07-28 23:07:36 +00:00
|
|
|
void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME,
|
|
|
|
ExplodedNode *Pred,
|
|
|
|
ExplodedNodeSet &Dst) {
|
2011-10-24 21:19:59 +00:00
|
|
|
StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
|
2011-10-02 00:54:48 +00:00
|
|
|
const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens();
|
2012-01-26 21:29:00 +00:00
|
|
|
ProgramStateRef state = Pred->getState();
|
2012-01-06 22:09:28 +00:00
|
|
|
const LocationContext *LCtx = Pred->getLocationContext();
|
2010-04-19 12:51:02 +00:00
|
|
|
|
2011-10-02 00:54:48 +00:00
|
|
|
// Bind the temporary object to the value of the expression. Then bind
|
|
|
|
// the expression to the location of the object.
|
2012-01-06 22:09:28 +00:00
|
|
|
SVal V = state->getSVal(tempExpr, Pred->getLocationContext());
|
2010-04-19 12:51:02 +00:00
|
|
|
|
2011-10-02 00:54:48 +00:00
|
|
|
const MemRegion *R =
|
2012-01-06 22:09:28 +00:00
|
|
|
svalBuilder.getRegionManager().getCXXTempObjectRegion(ME, LCtx);
|
2010-04-19 12:51:02 +00:00
|
|
|
|
2011-10-02 00:54:48 +00:00
|
|
|
state = state->bindLoc(loc::MemRegionVal(R), V);
|
2012-01-06 22:09:28 +00:00
|
|
|
Bldr.generateNode(ME, Pred, state->BindExpr(ME, LCtx, loc::MemRegionVal(R)));
|
2010-04-19 12:51:02 +00:00
|
|
|
}
|
|
|
|
|
2012-01-28 12:06:22 +00:00
|
|
|
void ExprEngine::VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *expr,
|
|
|
|
ExplodedNode *Pred,
|
|
|
|
ExplodedNodeSet &Dst) {
|
|
|
|
VisitCXXConstructExpr(expr, 0, Pred, Dst);
|
|
|
|
}
|
|
|
|
|
2012-07-02 19:28:12 +00:00
|
|
|
void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
|
2011-04-08 22:42:35 +00:00
|
|
|
const MemRegion *Dest,
|
|
|
|
ExplodedNode *Pred,
|
|
|
|
ExplodedNodeSet &destNodes) {
|
2012-07-02 19:28:12 +00:00
|
|
|
CXXConstructorCall Call(CE, Dest, Pred->getState(),
|
|
|
|
Pred->getLocationContext());
|
2010-04-19 12:51:02 +00:00
|
|
|
|
2012-07-02 19:28:12 +00:00
|
|
|
ExplodedNodeSet DstPreVisit;
|
|
|
|
getCheckerManager().runCheckersForPreStmt(DstPreVisit, Pred, CE, *this);
|
2012-07-02 19:28:16 +00:00
|
|
|
ExplodedNodeSet DstPreCall;
|
|
|
|
getCheckerManager().runCheckersForPreCall(DstPreCall, DstPreVisit,
|
|
|
|
Call, *this);
|
2011-04-08 22:42:35 +00:00
|
|
|
|
2012-07-02 19:28:12 +00:00
|
|
|
ExplodedNodeSet DstInvalidated;
|
2012-07-02 19:28:16 +00:00
|
|
|
for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
|
2012-07-02 19:28:12 +00:00
|
|
|
I != E; ++I)
|
|
|
|
defaultEvalCall(DstInvalidated, *I, Call);
|
2011-04-08 22:42:35 +00:00
|
|
|
|
2012-07-02 19:28:16 +00:00
|
|
|
ExplodedNodeSet DstPostCall;
|
|
|
|
getCheckerManager().runCheckersForPostCall(DstPostCall, DstInvalidated,
|
|
|
|
Call, *this);
|
|
|
|
getCheckerManager().runCheckersForPostStmt(destNodes, DstPostCall, CE, *this);
|
2010-04-19 12:51:02 +00:00
|
|
|
}
|
|
|
|
|
2010-12-22 18:53:44 +00:00
|
|
|
void ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD,
|
2011-10-24 18:26:19 +00:00
|
|
|
const MemRegion *Dest,
|
|
|
|
const Stmt *S,
|
|
|
|
ExplodedNode *Pred,
|
|
|
|
ExplodedNodeSet &Dst) {
|
2011-10-24 21:19:59 +00:00
|
|
|
StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
|
2011-05-06 20:44:56 +00:00
|
|
|
if (!(DD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall()))
|
2010-11-20 06:53:12 +00:00
|
|
|
return;
|
2011-10-23 02:31:52 +00:00
|
|
|
|
2010-11-20 06:53:12 +00:00
|
|
|
// Create the context for 'this' region.
|
2011-10-23 02:31:52 +00:00
|
|
|
const StackFrameContext *SFC =
|
2011-10-24 01:32:45 +00:00
|
|
|
AnalysisDeclContexts.getContext(DD)->
|
2011-10-23 02:31:52 +00:00
|
|
|
getStackFrame(Pred->getLocationContext(), S,
|
2011-10-24 18:26:19 +00:00
|
|
|
currentBuilderContext->getBlock(), currentStmtIdx);
|
2010-11-20 06:53:12 +00:00
|
|
|
|
2010-11-24 08:53:20 +00:00
|
|
|
CallEnter PP(S, SFC, Pred->getLocationContext());
|
2012-01-26 21:29:00 +00:00
|
|
|
ProgramStateRef state = Pred->getState();
|
2012-06-22 23:55:50 +00:00
|
|
|
state = state->bindLoc(svalBuilder.getCXXThis(DD->getParent(), SFC),
|
|
|
|
loc::MemRegionVal(Dest));
|
2011-10-24 18:26:19 +00:00
|
|
|
Bldr.generateNode(PP, Pred, state);
|
2010-11-20 06:53:12 +00:00
|
|
|
}
|
|
|
|
|
2010-12-22 18:53:44 +00:00
|
|
|
void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
|
2010-04-19 12:51:02 +00:00
|
|
|
ExplodedNodeSet &Dst) {
|
2012-07-02 22:21:47 +00:00
|
|
|
// FIXME: Much of this should eventually migrate to CXXAllocatorCall.
|
|
|
|
// Also, we need to decide how allocators actually work -- they're not
|
|
|
|
// really part of the CXXNewExpr because they happen BEFORE the
|
|
|
|
// CXXConstructExpr subexpression. See PR12014 for some discussion.
|
2011-10-24 21:19:59 +00:00
|
|
|
StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
|
2011-03-31 04:04:48 +00:00
|
|
|
|
2011-10-24 18:26:19 +00:00
|
|
|
unsigned blockCount = currentBuilderContext->getCurrentBlockCount();
|
2012-02-17 23:13:45 +00:00
|
|
|
const LocationContext *LCtx = Pred->getLocationContext();
|
2010-12-02 07:49:45 +00:00
|
|
|
DefinedOrUnknownSVal symVal =
|
2012-07-02 22:21:47 +00:00
|
|
|
svalBuilder.getConjuredSymbolVal(0, CNE, LCtx, CNE->getType(), blockCount);
|
2012-06-20 01:32:01 +00:00
|
|
|
ProgramStateRef State = Pred->getState();
|
2011-03-31 04:04:48 +00:00
|
|
|
|
2012-07-02 22:21:47 +00:00
|
|
|
// Invalidate placement args.
|
|
|
|
CXXAllocatorCall Call(CNE, State, LCtx);
|
|
|
|
State = Call.invalidateRegions(blockCount);
|
|
|
|
|
2011-03-31 04:04:48 +00:00
|
|
|
if (CNE->isArray()) {
|
|
|
|
// FIXME: allocating an array requires simulating the constructors.
|
|
|
|
// For now, just return a symbolicated region.
|
2012-07-02 22:21:47 +00:00
|
|
|
const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion();
|
|
|
|
QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
|
|
|
|
const ElementRegion *EleReg =
|
|
|
|
getStoreManager().GetElementZeroRegion(NewReg, ObjTy);
|
2012-06-20 01:32:01 +00:00
|
|
|
State = State->BindExpr(CNE, Pred->getLocationContext(),
|
2012-01-06 22:09:28 +00:00
|
|
|
loc::MemRegionVal(EleReg));
|
2012-06-20 01:32:01 +00:00
|
|
|
Bldr.generateNode(CNE, Pred, State);
|
2011-03-31 04:04:48 +00:00
|
|
|
return;
|
|
|
|
}
|
2010-04-19 12:51:02 +00:00
|
|
|
|
2012-07-02 22:21:47 +00:00
|
|
|
// FIXME: Once we have proper support for CXXConstructExprs inside
|
|
|
|
// CXXNewExpr, we need to make sure that the constructed object is not
|
|
|
|
// immediately invalidated here. (The placement call should happen before
|
|
|
|
// the constructor call anyway.)
|
2012-06-20 01:32:01 +00:00
|
|
|
FunctionDecl *FD = CNE->getOperatorNew();
|
|
|
|
if (FD && FD->isReservedGlobalPlacementOperator()) {
|
|
|
|
// Non-array placement new should always return the placement location.
|
|
|
|
SVal PlacementLoc = State->getSVal(CNE->getPlacementArg(0), LCtx);
|
|
|
|
State = State->BindExpr(CNE, LCtx, PlacementLoc);
|
2012-07-02 22:21:47 +00:00
|
|
|
} else {
|
|
|
|
State = State->BindExpr(CNE, LCtx, symVal);
|
2012-06-20 01:32:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Bldr.generateNode(CNE, Pred, State);
|
2010-04-19 12:51:02 +00:00
|
|
|
}
|
|
|
|
|
2010-12-22 18:53:44 +00:00
|
|
|
void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,
|
2011-10-24 18:26:19 +00:00
|
|
|
ExplodedNode *Pred, ExplodedNodeSet &Dst) {
|
2012-02-29 08:42:57 +00:00
|
|
|
StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
|
|
|
|
ProgramStateRef state = Pred->getState();
|
|
|
|
Bldr.generateNode(CDE, Pred, state);
|
2010-04-21 02:17:31 +00:00
|
|
|
}
|
2010-04-19 12:51:02 +00:00
|
|
|
|
2012-03-10 01:34:17 +00:00
|
|
|
void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS,
|
|
|
|
ExplodedNode *Pred,
|
|
|
|
ExplodedNodeSet &Dst) {
|
|
|
|
const VarDecl *VD = CS->getExceptionDecl();
|
2012-03-16 05:58:15 +00:00
|
|
|
if (!VD) {
|
|
|
|
Dst.Add(Pred);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-03-10 01:34:17 +00:00
|
|
|
const LocationContext *LCtx = Pred->getLocationContext();
|
|
|
|
SVal V = svalBuilder.getConjuredSymbolVal(CS, LCtx, VD->getType(),
|
|
|
|
currentBuilderContext->getCurrentBlockCount());
|
|
|
|
ProgramStateRef state = Pred->getState();
|
|
|
|
state = state->bindLoc(state->getLValue(VD, LCtx), V);
|
|
|
|
|
|
|
|
StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
|
|
|
|
Bldr.generateNode(CS, Pred, state);
|
|
|
|
}
|
|
|
|
|
2010-12-22 18:53:44 +00:00
|
|
|
void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
|
2010-04-21 02:17:31 +00:00
|
|
|
ExplodedNodeSet &Dst) {
|
2011-10-24 21:19:59 +00:00
|
|
|
StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
|
2011-10-24 18:26:19 +00:00
|
|
|
|
2010-04-19 12:51:02 +00:00
|
|
|
// Get the this object region from StoreManager.
|
2012-01-06 22:09:28 +00:00
|
|
|
const LocationContext *LCtx = Pred->getLocationContext();
|
2010-04-19 12:51:02 +00:00
|
|
|
const MemRegion *R =
|
2010-12-02 07:49:45 +00:00
|
|
|
svalBuilder.getRegionManager().getCXXThisRegion(
|
2010-04-19 12:51:02 +00:00
|
|
|
getContext().getCanonicalType(TE->getType()),
|
2012-01-06 22:09:28 +00:00
|
|
|
LCtx);
|
2010-04-19 12:51:02 +00:00
|
|
|
|
2012-01-26 21:29:00 +00:00
|
|
|
ProgramStateRef state = Pred->getState();
|
2010-04-19 12:51:02 +00:00
|
|
|
SVal V = state->getSVal(loc::MemRegionVal(R));
|
2012-01-06 22:09:28 +00:00
|
|
|
Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V));
|
2010-04-19 12:51:02 +00:00
|
|
|
}
|