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