• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // This file defines a bunch of recurring problems in the Chromium C++ code.
6 //
7 // Checks that are implemented:
8 // - Constructors/Destructors should not be inlined if they are of a complex
9 //   class type.
10 // - Missing "virtual" keywords on methods that should be virtual.
11 // - Non-annotated overriding virtual methods.
12 // - Virtual methods with nonempty implementations in their headers.
13 // - Classes that derive from base::RefCounted / base::RefCountedThreadSafe
14 //   should have protected or private destructors.
15 // - WeakPtrFactory members that refer to their outer class should be the last
16 //   member.
17 // - Enum types with a xxxx_LAST or xxxxLast const actually have that constant
18 //   have the maximal value for that type.
19 
20 #ifndef TOOLS_CLANG_PLUGINS_FINDBADCONSTRUCTSCONSUMER_H_
21 #define TOOLS_CLANG_PLUGINS_FINDBADCONSTRUCTSCONSUMER_H_
22 
23 #include <memory>
24 
25 #include "clang/AST/AST.h"
26 #include "clang/AST/ASTConsumer.h"
27 #include "clang/AST/Attr.h"
28 #include "clang/AST/CXXInheritance.h"
29 #include "clang/AST/RecursiveASTVisitor.h"
30 #include "clang/AST/TypeLoc.h"
31 #include "clang/Basic/SourceManager.h"
32 #include "clang/Basic/SourceLocation.h"
33 
34 #include "CheckIPCVisitor.h"
35 #include "ChromeClassTester.h"
36 #include "Options.h"
37 #include "SuppressibleDiagnosticBuilder.h"
38 
39 namespace chrome_checker {
40 
41 // Searches for constructs that we know we don't want in the Chromium code base.
42 class FindBadConstructsConsumer
43     : public clang::RecursiveASTVisitor<FindBadConstructsConsumer>,
44       public ChromeClassTester {
45  public:
46   FindBadConstructsConsumer(clang::CompilerInstance& instance,
47                             const Options& options);
48 
49   void Traverse(clang::ASTContext& context);
50 
51   // RecursiveASTVisitor:
52   bool TraverseDecl(clang::Decl* decl);
53   bool VisitTagDecl(clang::TagDecl* tag_decl);
54   bool VisitVarDecl(clang::VarDecl* var_decl);
55   bool VisitTemplateSpecializationType(clang::TemplateSpecializationType* spec);
56   bool VisitCallExpr(clang::CallExpr* call_expr);
57 
58   // ChromeClassTester overrides:
59   void CheckChromeClass(clang::SourceLocation record_location,
60                         clang::CXXRecordDecl* record) override;
61   void CheckChromeEnum(clang::SourceLocation enum_location,
62                        clang::EnumDecl* enum_decl) override;
63 
64  private:
65   // The type of problematic ref-counting pattern that was encountered.
66   enum RefcountIssue { None, ImplicitDestructor, PublicDestructor };
67 
68   void CheckCtorDtorWeight(clang::SourceLocation record_location,
69                            clang::CXXRecordDecl* record);
70 
71   bool InTestingNamespace(const clang::Decl* record);
72   bool IsMethodInBannedOrTestingNamespace(const clang::CXXMethodDecl* method);
73 
74   // Returns a diagnostic builder that only emits the diagnostic if the spelling
75   // location (the actual characters that make up the token) is not in an
76   // ignored file. This is useful for situations where the token might originate
77   // from a macro in a system header: warning isn't useful, since system headers
78   // generally can't be easily updated.
79   SuppressibleDiagnosticBuilder ReportIfSpellingLocNotIgnored(
80       clang::SourceLocation loc,
81       unsigned diagnostic_id);
82 
83   void CheckVirtualMethods(clang::SourceLocation record_location,
84                            clang::CXXRecordDecl* record,
85                            bool warn_on_inline_bodies);
86   void CheckVirtualSpecifiers(const clang::CXXMethodDecl* method);
87   void CheckVirtualBodies(const clang::CXXMethodDecl* method);
88 
89   void CountType(const clang::Type* type,
90                  int* trivial_member,
91                  int* non_trivial_member,
92                  int* templated_non_trivial_member);
93 
94   static RefcountIssue CheckRecordForRefcountIssue(
95       const clang::CXXRecordDecl* record,
96       clang::SourceLocation& loc);
97   bool IsRefCounted(const clang::CXXBaseSpecifier* base,
98                     clang::CXXBasePath& path);
99   static bool HasPublicDtorCallback(const clang::CXXBaseSpecifier* base,
100                                     clang::CXXBasePath& path,
101                                     void* user_data);
102   void PrintInheritanceChain(const clang::CXXBasePath& path);
103   unsigned DiagnosticForIssue(RefcountIssue issue);
104   void CheckRefCountedDtors(clang::SourceLocation record_location,
105                             clang::CXXRecordDecl* record);
106 
107   void CheckWeakPtrFactoryMembers(clang::SourceLocation record_location,
108                                   clang::CXXRecordDecl* record);
109   void CheckVarDecl(clang::VarDecl* decl);
110 
111   void ParseFunctionTemplates(clang::TranslationUnitDecl* decl);
112 
113   unsigned diag_method_requires_override_;
114   unsigned diag_redundant_virtual_specifier_;
115   unsigned diag_base_method_virtual_and_final_;
116   unsigned diag_no_explicit_dtor_;
117   unsigned diag_public_dtor_;
118   unsigned diag_protected_non_virtual_dtor_;
119   unsigned diag_weak_ptr_factory_order_;
120   unsigned diag_bad_enum_last_value_;
121   unsigned diag_auto_deduced_to_a_pointer_type_;
122   unsigned diag_note_inheritance_;
123   unsigned diag_note_implicit_dtor_;
124   unsigned diag_note_public_dtor_;
125   unsigned diag_note_protected_non_virtual_dtor_;
126 
127   std::unique_ptr<CheckIPCVisitor> ipc_visitor_;
128 };
129 
130 }  // namespace chrome_checker
131 
132 #endif  // TOOLS_CLANG_PLUGINS_FINDBADCONSTRUCTSCONSUMER_H_
133