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 {
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.
field_range fields() const
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
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.
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)
const FunctionProtoType * T
llvm::StringRef getAsString(SyncScope S)