21 #include "llvm/ADT/SmallString.h"
22 #include "llvm/Support/SaveAndRestore.h"
23 #include "llvm/Support/raw_ostream.h"
25 using namespace clang;
45 enum Kind { NotVisited,
54 llvm::DenseMap<const FunctionDecl *, Kind> VisitedFunctions;
64 :
Checker(checker), BR(br), AC(ac), visitingCallExpr(nullptr) {}
66 bool hasWork()
const {
return !WList.empty(); }
74 Kind &K = VisitedFunctions[FD];
78 WList.push_back(WLUnit);
83 assert(!WList.empty());
93 if (VisitedFunctions[FD] == PreVisited) {
101 VisitedFunctions[FD] = PostVisited;
107 assert(VisitedFunctions[FD] == PostVisited);
114 void VisitCXXMemberCallExpr(
CallExpr *CE);
115 void VisitStmt(
Stmt *
S) { VisitChildren(S); }
116 void VisitChildren(
Stmt *
S);
118 void ReportVirtualCall(
const CallExpr *CE,
bool isPure);
127 void WalkAST::VisitChildren(
Stmt *
S) {
128 for (
Stmt *Child : S->children())
133 void WalkAST::VisitCallExpr(
CallExpr *CE) {
138 void WalkAST::VisitCXXMemberCallExpr(
CallExpr *CE) {
140 bool callIsNonVirtual =
false;
146 if (CME->getQualifier())
147 callIsNonVirtual =
true;
151 if (!isa<CXXThisExpr>(base))
156 if (base->getBestDynamicClassType()->hasAttr<FinalAttr>())
157 callIsNonVirtual =
true;
163 if (MD && MD->
isVirtual() && !callIsNonVirtual && !MD->hasAttr<FinalAttr>() &&
165 ReportVirtualCall(CE, MD->
isPure());
170 void WalkAST::ReportVirtualCall(
const CallExpr *CE,
bool isPure) {
172 llvm::raw_svector_ostream os(buf);
174 os <<
"Call Path : ";
179 if (visitingCallExpr)
180 os <<
" <-- " << *visitingCallExpr->getDirectCallee();
183 E = WList.begin();
I !=
E; --
I) {
186 if (VisitedFunctions[FD] == PostVisited)
187 os <<
" <-- " << *FD;
195 os <<
"\n" <<
"Call pure virtual functions during construction or "
196 <<
"destruction may leads undefined behaviour";
197 BR.EmitBasicReport(AC->getDecl(),
Checker,
198 "Call pure virtual function during construction or "
200 "Cplusplus", os.str(), CELoc, R);
204 os <<
"\n" <<
"Call virtual functions during construction or "
205 <<
"destruction will never go to a more derived class";
206 BR.EmitBasicReport(AC->getDecl(),
Checker,
207 "Call virtual function during construction or "
209 "Cplusplus", os.str(), CELoc, R);
219 class VirtualCallChecker :
public Checker<check::ASTDecl<CXXRecordDecl> > {
226 for (
const auto *
I : RD->
ctors()) {
227 if (!
I->isCopyOrMoveConstructor())
228 if (
Stmt *Body =
I->getBody()) {
236 if (
Stmt *Body = DD->getBody()) {
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
const Expr * getCallee() const
Expr * IgnoreImpCasts() LLVM_READONLY
IgnoreImpCasts - Skip past any implicit casts which might surround this expression.
AnalysisDeclContext contains the context data for the function or method under analysis.
bool isPure() const
Whether this virtual function is pure, i.e.
const CXXRecordDecl * getParent() const
Returns the parent of this method declaration, which is the class in which this method is defined...
detail::InMemoryDirectory::const_iterator I
AnalysisDeclContext * getAnalysisDeclContext(const Decl *D)
Expr - This represents one expression.
Represents a C++ destructor within a class.
BugReporter is a utility class for generating PathDiagnostics for analysis.
Stmt * getBody(const FunctionDecl *&Definition) const
getBody - Retrieve the body (definition) of the function.
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)
Create a location for the beginning of the declaration.
CHECKER * registerChecker()
Used to register checkers.
Represents a static or instance method of a struct/union/class.
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return 0.
CXXDestructorDecl * getDestructor() const
Returns the destructor decl for this class.
detail::InMemoryDirectory::const_iterator E
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Represents a C++ struct/union/class.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
A trivial tuple used to represent a source range.