19#include "llvm/ADT/SmallString.h"
20#include "llvm/Support/raw_ostream.h"
30 const RecordType *RT = T->getAsCanonical<RecordType>();
59 return TD->
getName() ==
"string";
79 const TemplateSpecializationType *TS = T->getAs<TemplateSpecializationType>();
89 return TD->
getName() ==
"vector";
93 const TemplateSpecializationType *TS = T->getAs<TemplateSpecializationType>();
103 return TD->
getName() ==
"SmallVector";
112class StringRefCheckerVisitor :
public StmtVisitor<StringRefCheckerVisitor> {
113 const Decl *DeclWithIssue;
115 const CheckerBase *Checker;
118 StringRefCheckerVisitor(
const Decl *declWithIssue, BugReporter &br,
119 const CheckerBase *checker)
120 : DeclWithIssue(declWithIssue), BR(br), Checker(checker) {}
121 void VisitChildren(Stmt *S) {
126 void VisitStmt(Stmt *S) { VisitChildren(S); }
127 void VisitDeclStmt(DeclStmt *DS);
129 void VisitVarDecl(VarDecl *VD);
135 StringRefCheckerVisitor walker(D, BR,
Checker);
139void StringRefCheckerVisitor::VisitDeclStmt(
DeclStmt *S) {
142 for (
auto *I : S->
decls())
143 if (VarDecl *VD = dyn_cast<VarDecl>(I))
147void StringRefCheckerVisitor::VisitVarDecl(VarDecl *VD) {
156 ExprWithCleanups *Ex1 = dyn_cast<ExprWithCleanups>(
Init);
159 CXXConstructExpr *Ex2 = dyn_cast<CXXConstructExpr>(Ex1->
getSubExpr());
162 ImplicitCastExpr *Ex3 = dyn_cast<ImplicitCastExpr>(Ex2->
getArg(0));
165 CXXConstructExpr *Ex4 = dyn_cast<CXXConstructExpr>(Ex3->
getSubExpr());
168 ImplicitCastExpr *Ex5 = dyn_cast<ImplicitCastExpr>(Ex4->
getArg(0));
171 CXXBindTemporaryExpr *Ex6 = dyn_cast<CXXBindTemporaryExpr>(Ex5->
getSubExpr());
176 const char *desc =
"StringRef should not be bound to temporary "
177 "std::string that it outlives";
178 PathDiagnosticLocation VDLoc =
180 BR.
EmitBasicReport(DeclWithIssue, Checker, desc,
"LLVM Conventions", desc,
181 VDLoc,
Init->getSourceRange());
198 for (
const auto &BS : R->bases())
199 if (
const auto *baseD = BS.getType()->getAsCXXRecordDecl();
207class ASTFieldVisitor {
208 SmallVector<FieldDecl*, 10> FieldChain;
209 const CXXRecordDecl *Root;
211 const CheckerBase *Checker;
214 ASTFieldVisitor(
const CXXRecordDecl *root, BugReporter &br,
215 const CheckerBase *checker)
216 : Root(root), BR(br), Checker(checker) {}
218 void Visit(FieldDecl *D);
219 void ReportError(QualType T);
228 for (
auto *I : R->fields()) {
229 ASTFieldVisitor walker(R, BR,
Checker);
234void ASTFieldVisitor::Visit(FieldDecl *D) {
235 FieldChain.push_back(D);
243 for (
auto *I : RD->fields())
246 FieldChain.pop_back();
249void ASTFieldVisitor::ReportError(QualType T) {
250 SmallString<1024> buf;
251 llvm::raw_svector_ostream os(buf);
253 os <<
"AST class '" << Root->
getName() <<
"' has a field '"
254 << FieldChain.front()->getName() <<
"' that allocates heap memory";
255 if (FieldChain.size() > 1) {
256 os <<
" via the following chain: ";
258 for (SmallVectorImpl<FieldDecl*>::iterator I=FieldChain.begin(),
259 E=FieldChain.end(); I!=E; ++I) {
264 os << (*I)->getName();
267 os <<
" (type " << FieldChain.back()->getType() <<
")";
279 "LLVM Conventions", os.str(), L);
287class LLVMConventionsChecker :
public Checker<
288 check::ASTDecl<CXXRecordDecl>,
289 check::ASTCodeBody > {
291 void checkASTDecl(
const CXXRecordDecl *R, AnalysisManager& mgr,
292 BugReporter &BR)
const {
293 if (
R->isCompleteDefinition())
297 void checkASTCodeBody(
const Decl *D, AnalysisManager& mgr,
298 BugReporter &BR)
const {
304void ento::registerLLVMConventionsChecker(CheckerManager &mgr) {
308bool ento::shouldRegisterLLVMConventionsChecker(
const CheckerManager &mgr) {
Defines the C++ template declaration subclasses.
static bool IsStdVector(QualType T)
static bool IsClangType(const RecordDecl *RD)
static bool AllocatesMemory(QualType T)
static bool IsClangStmt(const RecordDecl *RD)
static bool InNamespace(const Decl *D, StringRef NS)
Check whether the declaration is semantically inside the top-level namespace named by ns.
static bool IsClangAttr(const RecordDecl *RD)
static bool IsStdString(QualType T)
static bool IsClangDecl(const RecordDecl *RD)
static void CheckASTMemory(const CXXRecordDecl *R, BugReporter &BR, const CheckerBase *Checker)
static bool IsPartOfAST(const CXXRecordDecl *R)
static bool IsSmallVector(QualType T)
static void CheckStringRefAssignedTemporary(const Decl *D, BugReporter &BR, const CheckerBase *Checker)
static bool IsLLVMStringRef(QualType T)
Expr * getArg(unsigned Arg)
Return the specified argument.
unsigned getNumArgs() const
Return the number of arguments to the constructor call.
Represents a C++ struct/union/class.
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Decl - This represents one declaration (or definition), e.g.
bool isInStdNamespace() const
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
DeclContext * getDeclContext()
const Expr * getSubExpr() const
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Represent a C++ namespace.
A (possibly-)qualified type.
Represents a struct/union/class.
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
The base class of all kinds of template declarations (e.g., class, function, etc.).
Represents a C++ template name within the type system.
TemplateDecl * getAsTemplateDecl(bool IgnoreDeduced=false) const
Retrieve the underlying template declaration that this template name refers to, if known.
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
const T * getAs() const
Member-template getAs<specific type>'.
Base class for declarations which introduce a typedef-name.
TypedefNameDecl * getDecl() const
const Expr * getInit() const
BugReporter is a utility class for generating PathDiagnostics for analysis.
const SourceManager & getSourceManager()
void EmitBasicReport(const Decl *DeclWithIssue, const CheckerFrontend *Checker, StringRef BugName, StringRef BugCategory, StringRef BugStr, PathDiagnosticLocation Loc, ArrayRef< SourceRange > Ranges={}, ArrayRef< FixItHint > Fixits={})
The non-templated common ancestor of all the simple Checker<...> classes.
CHECKER * registerChecker(AT &&...Args)
Register a single-part checker (derived from Checker): construct its singleton instance,...
Simple checker classes that implement one frontend (i.e.
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)
Create a location for the beginning of the declaration.
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
llvm::StringRef getAsString(SyncScope S)