21 #include "llvm/ADT/SmallString.h"
22 #include "llvm/Support/SaveAndRestore.h"
23 #include "llvm/Support/raw_ostream.h"
25 using namespace clang;
40 bool IsInterprocedural =
false;
45 bool ReportPureOnly =
false;
57 enum Kind { NotVisited,
66 llvm::DenseMap<const FunctionDecl *, Kind> VisitedFunctions;
77 :
Checker(checker), BR(br), AC(ac), RootMethod(rootMethod),
78 IsInterprocedural(isInterprocedural), ReportPureOnly(reportPureOnly),
79 visitingCallExpr(nullptr) {
81 assert(isa<CXXConstructorDecl>(rootMethod) ||
82 isa<CXXDestructorDecl>(rootMethod));
85 bool hasWork()
const {
return !WList.empty(); }
93 Kind &K = VisitedFunctions[FD];
97 WList.push_back(WLUnit);
102 assert(!WList.empty());
112 if (VisitedFunctions[FD] == PreVisited) {
120 VisitedFunctions[FD] = PostVisited;
126 assert(VisitedFunctions[FD] == PostVisited);
133 void VisitCXXMemberCallExpr(
CallExpr *CE);
134 void VisitStmt(
Stmt *
S) { VisitChildren(S); }
135 void VisitChildren(
Stmt *
S);
137 void ReportVirtualCall(
const CallExpr *CE,
bool isPure);
146 void WalkAST::VisitChildren(
Stmt *
S) {
152 void WalkAST::VisitCallExpr(
CallExpr *CE) {
154 if (IsInterprocedural)
158 void WalkAST::VisitCXXMemberCallExpr(
CallExpr *CE) {
160 bool callIsNonVirtual =
false;
166 if (CME->getQualifier())
167 callIsNonVirtual =
true;
171 if (!isa<CXXThisExpr>(base))
176 if (base->getBestDynamicClassType()->hasAttr<FinalAttr>())
177 callIsNonVirtual =
true;
184 if (MD && MD->
isVirtual() && !callIsNonVirtual && !MD->
hasAttr<FinalAttr>() &&
186 ReportVirtualCall(CE, MD->
isPure());
188 if (IsInterprocedural)
192 void WalkAST::ReportVirtualCall(
const CallExpr *CE,
bool isPure) {
193 if (ReportPureOnly && !isPure)
197 llvm::raw_svector_ostream os(buf);
202 if (IsInterprocedural) {
203 os <<
"Call Path : ";
208 if (visitingCallExpr)
209 os <<
" <-- " << *visitingCallExpr->getDirectCallee();
212 E = WList.begin();
I !=
E; --
I) {
215 if (VisitedFunctions[FD] == PostVisited)
216 os <<
" <-- " << *FD;
230 os <<
"virtual function during ";
232 if (isa<CXXConstructorDecl>(RootMethod))
233 os <<
"construction ";
235 os <<
"destruction ";
238 os <<
"has undefined behavior";
240 os <<
"will not dispatch to derived class";
242 BR.EmitBasicReport(AC->getDecl(),
Checker,
243 "Call to virtual function during construction or "
245 "C++ Object Lifecycle", os.str(), CELoc, R);
253 class VirtualCallChecker :
public Checker<check::ASTDecl<CXXRecordDecl> > {
263 for (
const auto *
I : RD->
ctors()) {
264 if (!
I->isCopyOrMoveConstructor())
265 if (
Stmt *Body =
I->getBody()) {
266 WalkAST walker(
this, BR, ADC,
I, isInterprocedural, isPureOnly);
274 if (
Stmt *Body = DD->getBody()) {
275 WalkAST walker(
this, BR, ADC, DD, isInterprocedural, isPureOnly);
284 VirtualCallChecker *checker = mgr.
registerChecker<VirtualCallChecker>();
285 checker->isInterprocedural =
289 checker->isPureOnly =
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
Stmt - This represents one statement.
A helper class which wraps a boolean value set to false by default.
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.
bool getBooleanOption(StringRef Name, bool DefaultVal, const ento::CheckerBase *C=nullptr, bool SearchInParents=false)
Interprets an option's string value as a boolean.
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
AnalyzerOptions & getAnalyzerOptions()
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.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
A trivial tuple used to represent a source range.