diff options
Diffstat (limited to 'lib/StaticAnalyzer/Core/CoreEngine.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Core/CoreEngine.cpp | 63 |
1 files changed, 57 insertions, 6 deletions
diff --git a/lib/StaticAnalyzer/Core/CoreEngine.cpp b/lib/StaticAnalyzer/Core/CoreEngine.cpp index 196854cb09da..94cf74de8293 100644 --- a/lib/StaticAnalyzer/Core/CoreEngine.cpp +++ b/lib/StaticAnalyzer/Core/CoreEngine.cpp @@ -1,9 +1,8 @@ //===- CoreEngine.cpp - Path-Sensitive Dataflow Engine --------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -217,6 +216,25 @@ void CoreEngine::HandleBlockEdge(const BlockEdge &L, ExplodedNode *Pred) { LC->getDecl(), LC->getCFG()->getNumBlockIDs()); + // Display a prunable path note to the user if it's a virtual bases branch + // and we're taking the path that skips virtual base constructors. + if (L.getSrc()->getTerminator().isVirtualBaseBranch() && + L.getDst() == *L.getSrc()->succ_begin()) { + ProgramPoint P = L.withTag(getNoteTags().makeNoteTag( + [](BugReporterContext &, BugReport &) -> std::string { + // TODO: Just call out the name of the most derived class + // when we know it. + return "Virtual base initialization skipped because " + "it has already been handled by the most derived class"; + }, /*IsPrunable=*/true)); + // Perform the transition. + ExplodedNodeSet Dst; + NodeBuilder Bldr(Pred, Dst, BuilderCtx); + Pred = Bldr.generateNode(P, Pred->getState(), Pred); + if (!Pred) + return; + } + // Check if we are entering the EXIT block. if (Blk == &(L.getLocationContext()->getCFG()->getExit())) { assert(L.getLocationContext()->getCFG()->getExit().empty() && @@ -276,14 +294,14 @@ void CoreEngine::HandleBlockEntrance(const BlockEntrance &L, } void CoreEngine::HandleBlockExit(const CFGBlock * B, ExplodedNode *Pred) { - if (const Stmt *Term = B->getTerminator()) { + if (const Stmt *Term = B->getTerminatorStmt()) { switch (Term->getStmtClass()) { default: llvm_unreachable("Analysis for this terminator not implemented."); case Stmt::CXXBindTemporaryExprClass: HandleCleanupTemporaryBranch( - cast<CXXBindTemporaryExpr>(B->getTerminator().getStmt()), B, Pred); + cast<CXXBindTemporaryExpr>(Term), B, Pred); return; // Model static initializers. @@ -378,9 +396,19 @@ void CoreEngine::HandleBlockExit(const CFGBlock * B, ExplodedNode *Pred) { case Stmt::WhileStmtClass: HandleBranch(cast<WhileStmt>(Term)->getCond(), Term, B, Pred); return; + + case Stmt::GCCAsmStmtClass: + assert(cast<GCCAsmStmt>(Term)->isAsmGoto() && "Encountered GCCAsmStmt without labels"); + // TODO: Handle jumping to labels + return; } } + if (B->getTerminator().isVirtualBaseBranch()) { + HandleVirtualBaseBranch(B, Pred); + return; + } + assert(B->succ_size() == 1 && "Blocks with no terminator should have at most 1 successor."); @@ -440,6 +468,29 @@ void CoreEngine::HandlePostStmt(const CFGBlock *B, unsigned StmtIdx, } } +void CoreEngine::HandleVirtualBaseBranch(const CFGBlock *B, + ExplodedNode *Pred) { + const LocationContext *LCtx = Pred->getLocationContext(); + if (const auto *CallerCtor = dyn_cast_or_null<CXXConstructExpr>( + LCtx->getStackFrame()->getCallSite())) { + switch (CallerCtor->getConstructionKind()) { + case CXXConstructExpr::CK_NonVirtualBase: + case CXXConstructExpr::CK_VirtualBase: { + BlockEdge Loc(B, *B->succ_begin(), LCtx); + HandleBlockEdge(Loc, Pred); + return; + } + default: + break; + } + } + + // We either don't see a parent stack frame because we're in the top frame, + // or the parent stack frame doesn't initialize our virtual bases. + BlockEdge Loc(B, *(B->succ_begin() + 1), LCtx); + HandleBlockEdge(Loc, Pred); +} + /// generateNode - Utility method to generate nodes, hook up successors, /// and add nodes to the worklist. void CoreEngine::generateNode(const ProgramPoint &Loc, |