LLVMConventionsChecker.cpp revision ec8605f1d7ec846dbf51047bfd5c56d32d1ff91c
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//=== LLVMConventionsChecker.cpp - Check LLVM codebase conventions ---*- C++ -*- 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The LLVM Compiler Infrastructure 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file is distributed under the University of Illinois Open Source 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// License. See LICENSE.TXT for details. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This defines LLVMConventionsChecker, a bunch of small little checks 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for checking specific coding conventions in the LLVM/Clang codebase. 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ClangSACheckers.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/Checker.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/AST/DeclTemplate.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/AST/StmtVisitor.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "llvm/ADT/StringRef.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace clang; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace ento; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Generic type checking routines. 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool IsLLVMStringRef(QualType T) { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const RecordType *RT = T->getAs<RecordType>(); 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!RT) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return llvm::StringRef(QualType(RT, 0).getAsString()) == 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "class llvm::StringRef"; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// Check whether the declaration is semantically inside the top-level 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// namespace named by ns. 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool InNamespace(const Decl *D, llvm::StringRef NS) { 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(D->getDeclContext()); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ND) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const IdentifierInfo *II = ND->getIdentifier(); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!II || !II->getName().equals(NS)) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return isa<TranslationUnitDecl>(ND->getDeclContext()); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool IsStdString(QualType T) { 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (const ElaboratedType *QT = T->getAs<ElaboratedType>()) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) T = QT->getNamedType(); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TypedefType *TT = T->getAs<TypedefType>(); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!TT) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TypedefDecl *TD = TT->getDecl(); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!InNamespace(TD, "std")) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TD->getName() == "string"; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool IsClangType(const RecordDecl *RD) { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return RD->getName() == "Type" && InNamespace(RD, "clang"); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool IsClangDecl(const RecordDecl *RD) { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return RD->getName() == "Decl" && InNamespace(RD, "clang"); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool IsClangStmt(const RecordDecl *RD) { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return RD->getName() == "Stmt" && InNamespace(RD, "clang"); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool IsClangAttr(const RecordDecl *RD) { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return RD->getName() == "Attr" && InNamespace(RD, "clang"); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool IsStdVector(QualType T) { 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TemplateSpecializationType *TS = T->getAs<TemplateSpecializationType>(); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!TS) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateName TM = TS->getTemplateName(); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateDecl *TD = TM.getAsTemplateDecl(); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!TD || !InNamespace(TD, "std")) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TD->getName() == "vector"; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool IsSmallVector(QualType T) { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TemplateSpecializationType *TS = T->getAs<TemplateSpecializationType>(); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!TS) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateName TM = TS->getTemplateName(); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateDecl *TD = TM.getAsTemplateDecl(); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!TD || !InNamespace(TD, "llvm")) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TD->getName() == "SmallVector"; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CHECK: a llvm::StringRef should not be bound to a temporary std::string whose 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// lifetime is shorter than the StringRef's. 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class StringRefCheckerVisitor : public StmtVisitor<StringRefCheckerVisitor> { 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BugReporter &BR; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public: 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringRefCheckerVisitor(BugReporter &br) : BR(br) {} 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void VisitChildren(Stmt *S) { 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Stmt::child_iterator I = S->child_begin(), E = S->child_end() ; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) I != E; ++I) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (Stmt *child = *I) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Visit(child); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void VisitStmt(Stmt *S) { VisitChildren(S); } 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void VisitDeclStmt(DeclStmt *DS); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)private: 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void VisitVarDecl(VarDecl *VD); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // end anonymous namespace 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void CheckStringRefAssignedTemporary(const Decl *D, BugReporter &BR) { 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringRefCheckerVisitor walker(BR); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) walker.Visit(D->getBody()); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void StringRefCheckerVisitor::VisitDeclStmt(DeclStmt *S) { 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitChildren(S); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (DeclStmt::decl_iterator I = S->decl_begin(), E = S->decl_end();I!=E; ++I) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (VarDecl *VD = dyn_cast<VarDecl>(*I)) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVarDecl(VD); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void StringRefCheckerVisitor::VisitVarDecl(VarDecl *VD) { 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Expr *Init = VD->getInit(); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!Init) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Pattern match for: 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // llvm::StringRef x = call() (where call returns std::string) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsLLVMStringRef(VD->getType())) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExprWithCleanups *Ex1 = dyn_cast<ExprWithCleanups>(Init); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!Ex1) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CXXConstructExpr *Ex2 = dyn_cast<CXXConstructExpr>(Ex1->getSubExpr()); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!Ex2 || Ex2->getNumArgs() != 1) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ImplicitCastExpr *Ex3 = dyn_cast<ImplicitCastExpr>(Ex2->getArg(0)); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!Ex3) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CXXConstructExpr *Ex4 = dyn_cast<CXXConstructExpr>(Ex3->getSubExpr()); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!Ex4 || Ex4->getNumArgs() != 1) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ImplicitCastExpr *Ex5 = dyn_cast<ImplicitCastExpr>(Ex4->getArg(0)); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!Ex5) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CXXBindTemporaryExpr *Ex6 = dyn_cast<CXXBindTemporaryExpr>(Ex5->getSubExpr()); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!Ex6 || !IsStdString(Ex6->getType())) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Okay, badness! Report an error. 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *desc = "StringRef should not be bound to temporary " 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "std::string that it outlives"; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BR.EmitBasicReport(desc, "LLVM Conventions", desc, 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VD->getLocStart(), Init->getSourceRange()); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CHECK: Clang AST nodes should not have fields that can allocate 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// memory. 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool AllocatesMemory(QualType T) { 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return IsStdVector(T) || IsStdString(T) || IsSmallVector(T); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This type checking could be sped up via dynamic programming. 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool IsPartOfAST(const CXXRecordDecl *R) { 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsClangStmt(R) || IsClangType(R) || IsClangDecl(R) || IsClangAttr(R)) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (CXXRecordDecl::base_class_const_iterator I = R->bases_begin(), 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) E = R->bases_end(); I!=E; ++I) { 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CXXBaseSpecifier BS = *I; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QualType T = BS.getType(); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (const RecordType *baseT = T->getAs<RecordType>()) { 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CXXRecordDecl *baseD = cast<CXXRecordDecl>(baseT->getDecl()); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsPartOfAST(baseD)) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ASTFieldVisitor { 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) llvm::SmallVector<FieldDecl*, 10> FieldChain; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CXXRecordDecl *Root; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BugReporter &BR; 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public: 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASTFieldVisitor(const CXXRecordDecl *root, BugReporter &br) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : Root(root), BR(br) {} 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Visit(FieldDecl *D); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ReportError(QualType T); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // end anonymous namespace 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void CheckASTMemory(const CXXRecordDecl *R, BugReporter &BR) { 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsPartOfAST(R)) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (RecordDecl::field_iterator I = R->field_begin(), E = R->field_end(); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) I != E; ++I) { 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASTFieldVisitor walker(R, BR); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) walker.Visit(*I); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ASTFieldVisitor::Visit(FieldDecl *D) { 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FieldChain.push_back(D); 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QualType T = D->getType(); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (AllocatesMemory(T)) 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportError(T); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (const RecordType *RT = T->getAs<RecordType>()) { 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const RecordDecl *RD = RT->getDecl()->getDefinition(); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) I != E; ++I) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Visit(*I); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FieldChain.pop_back(); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ASTFieldVisitor::ReportError(QualType T) { 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) llvm::SmallString<1024> buf; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) llvm::raw_svector_ostream os(buf); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os << "AST class '" << Root->getName() << "' has a field '" 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << FieldChain.front()->getName() << "' that allocates heap memory"; 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FieldChain.size() > 1) { 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os << " via the following chain: "; 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool isFirst = true; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (llvm::SmallVectorImpl<FieldDecl*>::iterator I=FieldChain.begin(), 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) E=FieldChain.end(); I!=E; ++I) { 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!isFirst) 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os << '.'; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) isFirst = false; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os << (*I)->getName(); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os << " (type " << FieldChain.back()->getType().getAsString() << ")"; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os.flush(); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that this will fire for every translation unit that uses this 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // class. This is suboptimal, but at least scan-build will merge 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // duplicate HTML reports. In the future we need a unified way of merging 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // duplicate reports across translation units. For C++ classes we cannot 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // just report warnings when we see an out-of-line method definition for a 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // class, as that heuristic doesn't always work (the complete definition of 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the class may be in the header file, for example). 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BR.EmitBasicReport("AST node allocates heap memory", "LLVM Conventions", 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os.str(), FieldChain.front()->getLocStart()); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LLVMConventionsChecker 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class LLVMConventionsChecker : public Checker< 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) check::ASTDecl<CXXRecordDecl>, 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) check::ASTCodeBody > { 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public: 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void checkASTDecl(const CXXRecordDecl *R, AnalysisManager& mgr, 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BugReporter &BR) const { 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (R->isDefinition()) 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckASTMemory(R, BR); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BugReporter &BR) const { 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckStringRefAssignedTemporary(D, BR); 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ento::registerLLVMConventionsChecker(CheckerManager &mgr) { 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mgr.registerChecker<LLVMConventionsChecker>(); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)