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)