20 #include "llvm/ADT/SmallString.h" 21 #include "llvm/Support/raw_ostream.h" 23 using namespace clang;
45 if (!II || !II->
getName().equals(NS))
52 T = QT->getNamedType();
63 return TD->
getName() ==
"string";
93 return TD->
getName() ==
"vector";
107 return TD->
getName() ==
"SmallVector";
116 class StringRefCheckerVisitor :
public StmtVisitor<StringRefCheckerVisitor> {
117 const Decl *DeclWithIssue;
119 const CheckerBase *Checker;
122 StringRefCheckerVisitor(
const Decl *declWithIssue, BugReporter &br,
123 const CheckerBase *checker)
124 : DeclWithIssue(declWithIssue), BR(br), Checker(checker) {}
125 void VisitChildren(
Stmt *S) {
130 void VisitStmt(
Stmt *S) { VisitChildren(S); }
133 void VisitVarDecl(
VarDecl *VD);
138 const CheckerBase *Checker) {
139 StringRefCheckerVisitor walker(D, BR, Checker);
143 void StringRefCheckerVisitor::VisitDeclStmt(
DeclStmt *S) {
146 for (
auto *I : S->
decls())
147 if (
VarDecl *VD = dyn_cast<VarDecl>(I))
151 void StringRefCheckerVisitor::VisitVarDecl(
VarDecl *VD) {
180 const char *desc =
"StringRef should not be bound to temporary " 181 "std::string that it outlives";
182 PathDiagnosticLocation VDLoc =
184 BR.EmitBasicReport(DeclWithIssue, Checker, desc,
"LLVM Conventions", desc,
202 for (
const auto &BS : R->
bases()) {
205 CXXRecordDecl *baseD = cast<CXXRecordDecl>(baseT->getDecl());
215 class ASTFieldVisitor {
219 const CheckerBase *Checker;
223 const CheckerBase *checker)
224 : Root(root), BR(br), Checker(checker) {}
232 const CheckerBase *Checker) {
236 for (
auto *I : R->
fields()) {
237 ASTFieldVisitor walker(R, BR, Checker);
242 void ASTFieldVisitor::Visit(
FieldDecl *D) {
243 FieldChain.push_back(D);
252 for (
auto *I : RD->
fields())
256 FieldChain.pop_back();
259 void ASTFieldVisitor::ReportError(
QualType T) {
261 llvm::raw_svector_ostream os(buf);
263 os <<
"AST class '" << Root->getName() <<
"' has a field '" 264 << FieldChain.front()->getName() <<
"' that allocates heap memory";
265 if (FieldChain.size() > 1) {
266 os <<
" via the following chain: ";
269 E=FieldChain.end(); I!=E; ++I) {
274 os << (*I)->getName();
277 os <<
" (type " << FieldChain.back()->getType().getAsString() <<
")";
287 FieldChain.front(), BR.getSourceManager());
288 BR.EmitBasicReport(Root, Checker,
"AST node allocates heap memory",
289 "LLVM Conventions", os.str(), L);
297 class LLVMConventionsChecker :
public Checker<
298 check::ASTDecl<CXXRecordDecl>,
299 check::ASTCodeBody > {
301 void checkASTDecl(
const CXXRecordDecl *R, AnalysisManager& mgr,
302 BugReporter &BR)
const {
307 void checkASTCodeBody(
const Decl *D, AnalysisManager& mgr,
308 BugReporter &BR)
const {
314 void ento::registerLLVMConventionsChecker(CheckerManager &mgr) {
315 mgr.registerChecker<LLVMConventionsChecker>();
const Expr * getSubExpr() const
Represents a type that was referred to using an elaborated type keyword, e.g., struct S...
A (possibly-)qualified type.
static void CheckASTMemory(const CXXRecordDecl *R, BugReporter &BR, const CheckerBase *Checker)
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
Stmt - This represents one statement.
Decl - This represents one declaration (or definition), e.g.
Defines the C++ template declaration subclasses.
Represent a C++ namespace.
Represents a call to a C++ constructor.
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
Represents a variable declaration or definition.
const T * getAs() const
Member-template getAs<specific type>'.
Represents an expression – generally a full-expression – that introduces cleanups to be run at the ...
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Represents a struct/union/class.
One of these records is kept for each identifier that is lexed.
TemplateDecl * getAsTemplateDecl() const
Retrieve the underlying template declaration that this template name refers to, if known...
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
field_range fields() const
Represents a member of a struct/union/class.
TemplateName getTemplateName() const
Retrieve the name of the template that we are specializing.
Represents binding an expression to a temporary.
static bool IsPartOfAST(const CXXRecordDecl *R)
static bool IsStdString(QualType T)
This represents one expression.
llvm::StringRef getAsString(SyncScope S)
DeclContext * getDeclContext()
Represents a C++ template name within the type system.
static bool IsClangType(const RecordDecl *RD)
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)
Create a location for the beginning of the declaration.
static bool IsSmallVector(QualType T)
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
static bool IsStdVector(QualType T)
static bool IsClangDecl(const RecordDecl *RD)
static bool IsClangStmt(const RecordDecl *RD)
StringRef getName() const
Return the actual identifier string.
Base class for declarations which introduce a typedef-name.
Dataflow Directional Tag Classes.
The base class of all kinds of template declarations (e.g., class, function, etc.).
const Expr * getInit() const
static bool InNamespace(const Decl *D, StringRef NS)
Check whether the declaration is semantically inside the top-level namespace named by ns...
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
static bool IsLLVMStringRef(QualType T)
Expr * getArg(unsigned Arg)
Return the specified argument.
TypedefNameDecl * getDecl() const
Represents a C++ struct/union/class.
static void CheckStringRefAssignedTemporary(const Decl *D, BugReporter &BR, const CheckerBase *Checker)
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
static bool AllocatesMemory(QualType T)
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Represents a type template specialization; the template must be a class template, a type alias templa...
unsigned getNumArgs() const
Return the number of arguments to the constructor call.
bool isInStdNamespace() const
static bool IsClangAttr(const RecordDecl *RD)