static PathDiagnosticLocation getLocationForCaller(const StackFrameContext *SFC, const LocationContext *CallerCtx, const SourceManager &SM) { const CFGBlock &Block = *SFC->getCallSiteBlock(); CFGElement Source = Block[SFC->getIndex()]; switch (Source.getKind()) { case CFGElement::Statement: return PathDiagnosticLocation(Source.castAs<CFGStmt>().getStmt(), SM, CallerCtx); case CFGElement::Initializer: { const CFGInitializer &Init = Source.castAs<CFGInitializer>(); return PathDiagnosticLocation(Init.getInitializer()->getInit(), SM, CallerCtx); } case CFGElement::AutomaticObjectDtor: { const CFGAutomaticObjDtor &Dtor = Source.castAs<CFGAutomaticObjDtor>(); return PathDiagnosticLocation::createEnd(Dtor.getTriggerStmt(), SM, CallerCtx); } case CFGElement::BaseDtor: case CFGElement::MemberDtor: { const AnalysisDeclContext *CallerInfo = CallerCtx->getAnalysisDeclContext(); if (const Stmt *CallerBody = CallerInfo->getBody()) return PathDiagnosticLocation::createEnd(CallerBody, SM, CallerCtx); return PathDiagnosticLocation::create(CallerInfo->getDecl(), SM); } case CFGElement::TemporaryDtor: llvm_unreachable("not yet implemented!"); } llvm_unreachable("Unknown CFGElement kind"); }
static PathDiagnosticLocation getLocationForCaller(const StackFrameContext *SFC, const LocationContext *CallerCtx, const SourceManager &SM) { const CFGBlock &Block = *SFC->getCallSiteBlock(); CFGElement Source = Block[SFC->getIndex()]; switch (Source.getKind()) { case CFGElement::Statement: case CFGElement::Constructor: case CFGElement::CXXRecordTypedCall: return PathDiagnosticLocation(Source.castAs<CFGStmt>().getStmt(), SM, CallerCtx); case CFGElement::Initializer: { const CFGInitializer &Init = Source.castAs<CFGInitializer>(); return PathDiagnosticLocation(Init.getInitializer()->getInit(), SM, CallerCtx); } case CFGElement::AutomaticObjectDtor: { const CFGAutomaticObjDtor &Dtor = Source.castAs<CFGAutomaticObjDtor>(); return PathDiagnosticLocation::createEnd(Dtor.getTriggerStmt(), SM, CallerCtx); } case CFGElement::DeleteDtor: { const CFGDeleteDtor &Dtor = Source.castAs<CFGDeleteDtor>(); return PathDiagnosticLocation(Dtor.getDeleteExpr(), SM, CallerCtx); } case CFGElement::BaseDtor: case CFGElement::MemberDtor: { const AnalysisDeclContext *CallerInfo = CallerCtx->getAnalysisDeclContext(); if (const Stmt *CallerBody = CallerInfo->getBody()) return PathDiagnosticLocation::createEnd(CallerBody, SM, CallerCtx); return PathDiagnosticLocation::create(CallerInfo->getDecl(), SM); } case CFGElement::NewAllocator: { const CFGNewAllocator &Alloc = Source.castAs<CFGNewAllocator>(); return PathDiagnosticLocation(Alloc.getAllocatorExpr(), SM, CallerCtx); } case CFGElement::TemporaryDtor: { // Temporary destructors are for temporaries. They die immediately at around // the location of CXXBindTemporaryExpr. If they are lifetime-extended, // they'd be dealt with via an AutomaticObjectDtor instead. const auto &Dtor = Source.castAs<CFGTemporaryDtor>(); return PathDiagnosticLocation::createEnd(Dtor.getBindTemporaryExpr(), SM, CallerCtx); } case CFGElement::ScopeBegin: case CFGElement::ScopeEnd: llvm_unreachable("not yet implemented!"); case CFGElement::LifetimeEnds: case CFGElement::LoopExit: llvm_unreachable("CFGElement kind should not be on callsite!"); } llvm_unreachable("Unknown CFGElement kind"); }
/// Returns true if the initializer for \Elem can be a direct /// constructor. static bool canHaveDirectConstructor(CFGElement Elem){ // DeclStmts and CXXCtorInitializers for fields can be directly constructed. if (Optional<CFGStmt> StmtElem = Elem.getAs<CFGStmt>()) { if (isa<DeclStmt>(StmtElem->getStmt())) { return true; } } if (Elem.getKind() == CFGElement::Initializer) { return true; } return false; }