diff options
Diffstat (limited to 'lib/StaticAnalyzer/Core/ExprEngine.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngine.cpp | 150 |
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 { |