summaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core/ExprEngine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/StaticAnalyzer/Core/ExprEngine.cpp')
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngine.cpp150
1 files changed, 53 insertions, 97 deletions
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 188316c096e38..2b4bdd754fdbc 100644
--- a/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -117,56 +117,42 @@ STATISTIC(NumTimesRetriedWithoutInlining,
/// the construction context was present and contained references to these
/// AST nodes.
class ConstructedObjectKey {
- typedef std::pair<
- llvm::PointerUnion<const Stmt *, const CXXCtorInitializer *>,
- const LocationContext *> ConstructedObjectKeyImpl;
+ typedef std::pair<ConstructionContextItem, const LocationContext *>
+ ConstructedObjectKeyImpl;
- ConstructedObjectKeyImpl Impl;
+ const ConstructedObjectKeyImpl Impl;
const void *getAnyASTNodePtr() const {
- if (const Stmt *S = getStmt())
+ if (const Stmt *S = getItem().getStmtOrNull())
return S;
else
- return getCXXCtorInitializer();
+ return getItem().getCXXCtorInitializer();
}
public:
- ConstructedObjectKey(
- llvm::PointerUnion<const Stmt *, const CXXCtorInitializer *> P,
- const LocationContext *LC)
- : Impl(P, LC) {
- // This is the full list of statements that require additional actions when
- // encountered. This list may be expanded when new actions are implemented.
- assert(getCXXCtorInitializer() || isa<DeclStmt>(getStmt()) ||
- isa<CXXNewExpr>(getStmt()) || isa<CXXBindTemporaryExpr>(getStmt()) ||
- isa<MaterializeTemporaryExpr>(getStmt()) ||
- isa<CXXConstructExpr>(getStmt()));
- }
-
- const Stmt *getStmt() const {
- return Impl.first.dyn_cast<const Stmt *>();
- }
+ explicit ConstructedObjectKey(const ConstructionContextItem &Item,
+ const LocationContext *LC)
+ : Impl(Item, LC) {}
- const CXXCtorInitializer *getCXXCtorInitializer() const {
- return Impl.first.dyn_cast<const CXXCtorInitializer *>();
- }
-
- const LocationContext *getLocationContext() const {
- return Impl.second;
- }
+ const ConstructionContextItem &getItem() const { return Impl.first; }
+ const LocationContext *getLocationContext() const { return Impl.second; }
void print(llvm::raw_ostream &OS, PrinterHelper *Helper, PrintingPolicy &PP) {
- OS << '(' << getLocationContext() << ',' << getAnyASTNodePtr() << ") ";
- if (const Stmt *S = getStmt()) {
+ OS << '(' << getLocationContext() << ',' << getAnyASTNodePtr() << ','
+ << getItem().getKindAsString();
+ if (getItem().getKind() == ConstructionContextItem::ArgumentKind)
+ OS << " #" << getItem().getIndex();
+ OS << ") ";
+ if (const Stmt *S = getItem().getStmtOrNull()) {
S->printPretty(OS, Helper, PP);
} else {
- const CXXCtorInitializer *I = getCXXCtorInitializer();
+ const CXXCtorInitializer *I = getItem().getCXXCtorInitializer();
OS << I->getAnyMember()->getNameAsString();
}
}
void Profile(llvm::FoldingSetNodeID &ID) const {
- ID.AddPointer(Impl.first.getOpaqueValue());
+ ID.Add(Impl.first);
ID.AddPointer(Impl.second);
}
@@ -184,15 +170,6 @@ typedef llvm::ImmutableMap<ConstructedObjectKey, SVal>
REGISTER_TRAIT_WITH_PROGRAMSTATE(ObjectsUnderConstruction,
ObjectsUnderConstructionMap)
-// Additionally, track a set of destructors that correspond to elided
-// constructors when copy elision occurs.
-typedef std::pair<const CXXBindTemporaryExpr *, const LocationContext *>
- ElidedDestructorItem;
-typedef llvm::ImmutableSet<ElidedDestructorItem>
- ElidedDestructorSet;
-REGISTER_TRAIT_WITH_PROGRAMSTATE(ElidedDestructors,
- ElidedDestructorSet)
-
//===----------------------------------------------------------------------===//
// Engine construction and deletion.
//===----------------------------------------------------------------------===//
@@ -449,31 +426,32 @@ ExprEngine::createTemporaryRegionIfNeeded(ProgramStateRef State,
return State;
}
-ProgramStateRef ExprEngine::addObjectUnderConstruction(
- ProgramStateRef State,
- llvm::PointerUnion<const Stmt *, const CXXCtorInitializer *> P,
- const LocationContext *LC, SVal V) {
- ConstructedObjectKey Key(P, LC->getStackFrame());
+ProgramStateRef
+ExprEngine::addObjectUnderConstruction(ProgramStateRef State,
+ const ConstructionContextItem &Item,
+ const LocationContext *LC, SVal V) {
+ ConstructedObjectKey Key(Item, LC->getStackFrame());
// FIXME: Currently the state might already contain the marker due to
// incorrect handling of temporaries bound to default parameters.
assert(!State->get<ObjectsUnderConstruction>(Key) ||
- isa<CXXBindTemporaryExpr>(Key.getStmt()));
+ Key.getItem().getKind() ==
+ ConstructionContextItem::TemporaryDestructorKind);
return State->set<ObjectsUnderConstruction>(Key, V);
}
-Optional<SVal> ExprEngine::getObjectUnderConstruction(
- ProgramStateRef State,
- llvm::PointerUnion<const Stmt *, const CXXCtorInitializer *> P,
- const LocationContext *LC) {
- ConstructedObjectKey Key(P, LC->getStackFrame());
+Optional<SVal>
+ExprEngine::getObjectUnderConstruction(ProgramStateRef State,
+ const ConstructionContextItem &Item,
+ const LocationContext *LC) {
+ ConstructedObjectKey Key(Item, LC->getStackFrame());
return Optional<SVal>::create(State->get<ObjectsUnderConstruction>(Key));
}
-ProgramStateRef ExprEngine::finishObjectConstruction(
- ProgramStateRef State,
- llvm::PointerUnion<const Stmt *, const CXXCtorInitializer *> P,
- const LocationContext *LC) {
- ConstructedObjectKey Key(P, LC->getStackFrame());
+ProgramStateRef
+ExprEngine::finishObjectConstruction(ProgramStateRef State,
+ const ConstructionContextItem &Item,
+ const LocationContext *LC) {
+ ConstructedObjectKey Key(Item, LC->getStackFrame());
assert(State->contains<ObjectsUnderConstruction>(Key));
return State->remove<ObjectsUnderConstruction>(Key);
}
@@ -481,25 +459,26 @@ ProgramStateRef ExprEngine::finishObjectConstruction(
ProgramStateRef ExprEngine::elideDestructor(ProgramStateRef State,
const CXXBindTemporaryExpr *BTE,
const LocationContext *LC) {
- ElidedDestructorItem I(BTE, LC);
- assert(!State->contains<ElidedDestructors>(I));
- return State->add<ElidedDestructors>(I);
+ ConstructedObjectKey Key({BTE, /*IsElided=*/true}, LC);
+ // FIXME: Currently the state might already contain the marker due to
+ // incorrect handling of temporaries bound to default parameters.
+ return State->set<ObjectsUnderConstruction>(Key, UnknownVal());
}
ProgramStateRef
ExprEngine::cleanupElidedDestructor(ProgramStateRef State,
const CXXBindTemporaryExpr *BTE,
const LocationContext *LC) {
- ElidedDestructorItem I(BTE, LC);
- assert(State->contains<ElidedDestructors>(I));
- return State->remove<ElidedDestructors>(I);
+ ConstructedObjectKey Key({BTE, /*IsElided=*/true}, LC);
+ assert(State->contains<ObjectsUnderConstruction>(Key));
+ return State->remove<ObjectsUnderConstruction>(Key);
}
bool ExprEngine::isDestructorElided(ProgramStateRef State,
const CXXBindTemporaryExpr *BTE,
const LocationContext *LC) {
- ElidedDestructorItem I(BTE, LC);
- return State->contains<ElidedDestructors>(I);
+ ConstructedObjectKey Key({BTE, /*IsElided=*/true}, LC);
+ return State->contains<ObjectsUnderConstruction>(Key);
}
bool ExprEngine::areAllObjectsFullyConstructed(ProgramStateRef State,
@@ -512,10 +491,6 @@ bool ExprEngine::areAllObjectsFullyConstructed(ProgramStateRef State,
if (I.first.getLocationContext() == LC)
return false;
- for (auto I: State->get<ElidedDestructors>())
- if (I.second == LC)
- return false;
-
LC = LC->getParent();
}
return true;
@@ -560,14 +535,6 @@ static void printObjectsUnderConstructionForContext(raw_ostream &Out,
Key.print(Out, nullptr, PP);
Out << " : " << Value << NL;
}
-
- for (auto I : State->get<ElidedDestructors>()) {
- if (I.second != LC)
- continue;
- Out << '(' << I.second << ',' << (const void *)I.first << ") ";
- I.first->printPretty(Out, nullptr, PP);
- Out << " : (constructor elided)" << NL;
- }
}
void ExprEngine::printState(raw_ostream &Out, ProgramStateRef State,
@@ -2252,25 +2219,14 @@ void ExprEngine::processEndOfFunction(NodeBuilderContext& BC,
for (auto I : State->get<ObjectsUnderConstruction>())
if (I.first.getLocationContext() == LC) {
// The comment above only pardons us for not cleaning up a
- // CXXBindTemporaryExpr. If any other statements are found here,
+ // temporary destructor. If any other statements are found here,
// it must be a separate problem.
- assert(isa<CXXBindTemporaryExpr>(I.first.getStmt()));
+ assert(I.first.getItem().getKind() ==
+ ConstructionContextItem::TemporaryDestructorKind ||
+ I.first.getItem().getKind() ==
+ ConstructionContextItem::ElidedDestructorKind);
State = State->remove<ObjectsUnderConstruction>(I.first);
- // Also cleanup the elided destructor info.
- ElidedDestructorItem Item(
- cast<CXXBindTemporaryExpr>(I.first.getStmt()),
- I.first.getLocationContext());
- State = State->remove<ElidedDestructors>(Item);
}
-
- // Also suppress the assertion for elided destructors when temporary
- // destructors are not provided at all by the CFG, because there's no
- // good place to clean them up.
- if (!AMgr.getAnalyzerOptions().includeTemporaryDtorsInCFG())
- for (auto I : State->get<ElidedDestructors>())
- if (I.second == LC)
- State = State->remove<ElidedDestructors>(I);
-
LC = LC->getParent();
}
if (State != Pred->getState()) {
@@ -2338,7 +2294,7 @@ void ExprEngine::processSwitch(SwitchNodeBuilder& builder) {
// Evaluate the LHS of the case value.
llvm::APSInt V1 = Case->getLHS()->EvaluateKnownConstInt(getContext());
assert(V1.getBitWidth() == getContext().getIntWidth(CondE->getType()));
-
+
// Get the RHS of the case, if it exists.
llvm::APSInt V2;
if (const Expr *E = Case->getRHS())
@@ -2538,12 +2494,12 @@ void ExprEngine::VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred,
ExplodedNodeSet CheckedSet;
getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, M, *this);
- ExplodedNodeSet EvalSet;
- ValueDecl *Member = M->getMemberDecl();
+ ExplodedNodeSet EvalSet;
+ ValueDecl *Member = M->getMemberDecl();
// Handle static member variables and enum constants accessed via
// member syntax.
- if (isa<VarDecl>(Member) || isa<EnumConstantDecl>(Member)) {
+ if (isa<VarDecl>(Member) || isa<EnumConstantDecl>(Member)) {
for (const auto I : CheckedSet)
VisitCommonDeclRefExpr(M, Member, I, EvalSet);
} else {