1de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek//=======- VirtualCallChecker.cpp --------------------------------*- C++ -*-==// 2de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek// 3de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek// The LLVM Compiler Infrastructure 4de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek// 5de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek// This file is distributed under the University of Illinois Open Source 6de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek// License. See LICENSE.TXT for details. 7de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek// 8de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek//===----------------------------------------------------------------------===// 9de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek// 10de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek// This file defines a checker that checks virtual function calls during 11de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek// construction or destruction of C++ objects. 12de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek// 13de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek//===----------------------------------------------------------------------===// 14de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 15de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek#include "ClangSACheckers.h" 16de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek#include "clang/AST/DeclCXX.h" 17de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek#include "clang/AST/StmtVisitor.h" 18de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" 1955fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/StaticAnalyzer/Core/Checker.h" 2055fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" 218fe83e1df954d72c0f4ffc15d20a5222ec151c21Benjamin Kramer#include "llvm/ADT/SmallString.h" 2255fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/Support/SaveAndRestore.h" 23a93d0f280693b8418bc88cf7a8c93325f7fcf4c6Benjamin Kramer#include "llvm/Support/raw_ostream.h" 24de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 25de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenekusing namespace clang; 26de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenekusing namespace ento; 27de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 28de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremeneknamespace { 29de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 30de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenekclass WalkAST : public StmtVisitor<WalkAST> { 31651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const CheckerBase *Checker; 32de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek BugReporter &BR; 33de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek AnalysisDeclContext *AC; 34de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 35de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek typedef const CallExpr * WorkListUnit; 36de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek typedef SmallVector<WorkListUnit, 20> DFSWorkList; 37de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 38de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek /// A vector representing the worklist which has a chain of CallExprs. 39de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek DFSWorkList WList; 40de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 41de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek // PreVisited : A CallExpr to this FunctionDecl is in the worklist, but the 42de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek // body has not been visited yet. 43de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek // PostVisited : A CallExpr to this FunctionDecl is in the worklist, and the 44de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek // body has been visited. 45de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek enum Kind { NotVisited, 46de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek PreVisited, /**< A CallExpr to this FunctionDecl is in the 47de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek worklist, but the body has not yet been 48de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek visited. */ 49de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek PostVisited /**< A CallExpr to this FunctionDecl is in the 50de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek worklist, and the body has been visited. */ 51facde171ae4b8926622a1bffa833732a06f1875bBenjamin Kramer }; 52de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 53de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek /// A DenseMap that records visited states of FunctionDecls. 54de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek llvm::DenseMap<const FunctionDecl *, Kind> VisitedFunctions; 55de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 56de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek /// The CallExpr whose body is currently being visited. This is used for 57de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek /// generating bug reports. This is null while visiting the body of a 58de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek /// constructor or destructor. 59de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek const CallExpr *visitingCallExpr; 60de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 61de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenekpublic: 62651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines WalkAST(const CheckerBase *checker, BugReporter &br, 63651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines AnalysisDeclContext *ac) 646bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines : Checker(checker), BR(br), AC(ac), visitingCallExpr(nullptr) {} 65651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 66de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek bool hasWork() const { return !WList.empty(); } 67de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 68de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek /// This method adds a CallExpr to the worklist and marks the callee as 69de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek /// being PreVisited. 70de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek void Enqueue(WorkListUnit WLUnit) { 71de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek const FunctionDecl *FD = WLUnit->getDirectCallee(); 72de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek if (!FD || !FD->getBody()) 73de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek return; 74de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek Kind &K = VisitedFunctions[FD]; 75de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek if (K != NotVisited) 76de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek return; 77de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek K = PreVisited; 78de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek WList.push_back(WLUnit); 79de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek } 80de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 81de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek /// This method returns an item from the worklist without removing it. 82de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek WorkListUnit Dequeue() { 83de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek assert(!WList.empty()); 84de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek return WList.back(); 85de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek } 86de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 87de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek void Execute() { 88de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek while (hasWork()) { 89de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek WorkListUnit WLUnit = Dequeue(); 90de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek const FunctionDecl *FD = WLUnit->getDirectCallee(); 91de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek assert(FD && FD->getBody()); 92de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 93de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek if (VisitedFunctions[FD] == PreVisited) { 94de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek // If the callee is PreVisited, walk its body. 95de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek // Visit the body. 96de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek SaveAndRestore<const CallExpr *> SaveCall(visitingCallExpr, WLUnit); 97de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek Visit(FD->getBody()); 98de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 99de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek // Mark the function as being PostVisited to indicate we have 100de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek // scanned the body. 101de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek VisitedFunctions[FD] = PostVisited; 102de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek continue; 103de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek } 104de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 105de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek // Otherwise, the callee is PostVisited. 106de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek // Remove it from the worklist. 107de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek assert(VisitedFunctions[FD] == PostVisited); 108de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek WList.pop_back(); 109de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek } 110de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek } 111de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 112de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek // Stmt visitor methods. 113de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek void VisitCallExpr(CallExpr *CE); 114de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek void VisitCXXMemberCallExpr(CallExpr *CE); 115de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek void VisitStmt(Stmt *S) { VisitChildren(S); } 116de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek void VisitChildren(Stmt *S); 117de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 118de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek void ReportVirtualCall(const CallExpr *CE, bool isPure); 119de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 120de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek}; 121de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek} // end anonymous namespace 122de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 123de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek//===----------------------------------------------------------------------===// 124de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek// AST walking. 125de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek//===----------------------------------------------------------------------===// 126de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 127de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenekvoid WalkAST::VisitChildren(Stmt *S) { 128de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I) 129de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek if (Stmt *child = *I) 130de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek Visit(child); 131de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek} 132de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 133de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenekvoid WalkAST::VisitCallExpr(CallExpr *CE) { 134de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek VisitChildren(CE); 135de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek Enqueue(CE); 136de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek} 137de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 138de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenekvoid WalkAST::VisitCXXMemberCallExpr(CallExpr *CE) { 139de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek VisitChildren(CE); 140de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek bool callIsNonVirtual = false; 141de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 142de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek // Several situations to elide for checking. 143de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek if (MemberExpr *CME = dyn_cast<MemberExpr>(CE->getCallee())) { 144de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek // If the member access is fully qualified (i.e., X::F), then treat 145de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek // this as a non-virtual call and do not warn. 146de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek if (CME->getQualifier()) 147de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek callIsNonVirtual = true; 148de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 149de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek // Elide analyzing the call entirely if the base pointer is not 'this'. 150de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek if (Expr *base = CME->getBase()->IgnoreImpCasts()) 151de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek if (!isa<CXXThisExpr>(base)) 152de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek return; 153de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek } 154de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 155de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek // Get the callee. 156de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CE->getDirectCallee()); 157de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek if (MD && MD->isVirtual() && !callIsNonVirtual) 158de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek ReportVirtualCall(CE, MD->isPure()); 159de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 160de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek Enqueue(CE); 161de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek} 162de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 163de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenekvoid WalkAST::ReportVirtualCall(const CallExpr *CE, bool isPure) { 164f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<100> buf; 165de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek llvm::raw_svector_ostream os(buf); 166de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 167de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek os << "Call Path : "; 168de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek // Name of current visiting CallExpr. 169a59d20b135bfde058a5a69045bab5ec4e2553f74Benjamin Kramer os << *CE->getDirectCallee(); 170de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 171de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek // Name of the CallExpr whose body is current walking. 172de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek if (visitingCallExpr) 173a59d20b135bfde058a5a69045bab5ec4e2553f74Benjamin Kramer os << " <-- " << *visitingCallExpr->getDirectCallee(); 174de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek // Names of FunctionDecls in worklist with state PostVisited. 175de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek for (SmallVectorImpl<const CallExpr *>::iterator I = WList.end(), 176de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek E = WList.begin(); I != E; --I) { 177de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek const FunctionDecl *FD = (*(I-1))->getDirectCallee(); 178de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek assert(FD); 179de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek if (VisitedFunctions[FD] == PostVisited) 180a59d20b135bfde058a5a69045bab5ec4e2553f74Benjamin Kramer os << " <-- " << *FD; 181de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek } 182de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 183de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek PathDiagnosticLocation CELoc = 184de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC); 185de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek SourceRange R = CE->getCallee()->getSourceRange(); 186de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 187de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek if (isPure) { 188de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek os << "\n" << "Call pure virtual functions during construction or " 189de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek << "destruction may leads undefined behaviour"; 190651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines BR.EmitBasicReport(AC->getDecl(), Checker, 19107189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek "Call pure virtual function during construction or " 192de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek "Destruction", 193651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "Cplusplus", os.str(), CELoc, R); 194de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek return; 195de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek } 196de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek else { 197de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek os << "\n" << "Call virtual functions during construction or " 198de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek << "destruction will never go to a more derived class"; 199651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines BR.EmitBasicReport(AC->getDecl(), Checker, 20007189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek "Call virtual function during construction or " 201de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek "Destruction", 202651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "Cplusplus", os.str(), CELoc, R); 203de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek return; 204de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek } 205de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek} 206de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 207de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek//===----------------------------------------------------------------------===// 208de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek// VirtualCallChecker 209de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek//===----------------------------------------------------------------------===// 210de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 211de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremeneknamespace { 212de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenekclass VirtualCallChecker : public Checker<check::ASTDecl<CXXRecordDecl> > { 213de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenekpublic: 214de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek void checkASTDecl(const CXXRecordDecl *RD, AnalysisManager& mgr, 215de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek BugReporter &BR) const { 216651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines WalkAST walker(this, BR, mgr.getAnalysisDeclContext(RD)); 217de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 218de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek // Check the constructors. 219651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto *I : RD->ctors()) { 220de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek if (!I->isCopyOrMoveConstructor()) 221de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek if (Stmt *Body = I->getBody()) { 222de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek walker.Visit(Body); 223de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek walker.Execute(); 224de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek } 225de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek } 226de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 227de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek // Check the destructor. 228de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek if (CXXDestructorDecl *DD = RD->getDestructor()) 229de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek if (Stmt *Body = DD->getBody()) { 230de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek walker.Visit(Body); 231de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek walker.Execute(); 232de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek } 233de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek } 234de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek}; 235de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek} 236de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek 237de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenekvoid ento::registerVirtualCallChecker(CheckerManager &mgr) { 238de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek mgr.registerChecker<VirtualCallChecker>(); 239de9f25365ca1fbc146eefeb839053b1cf9b75ae1Ted Kremenek} 240