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 VisitEnumDecl(clang::EnumDecl* enum_decl);
54   bool VisitTagDecl(clang::TagDecl* tag_decl);
55   bool VisitVarDecl(clang::VarDecl* var_decl);
56   bool VisitTemplateSpecializationType(clang::TemplateSpecializationType* spec);
57   bool VisitCallExpr(clang::CallExpr* call_expr);
58 
59   // ChromeClassTester overrides:
60   void CheckChromeClass(LocationType location_type,
61                         clang::SourceLocation record_location,
62                         clang::CXXRecordDecl* record) 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   // Returns a diagnostic builder that only emits the diagnostic if the spelling
72   // location (the actual characters that make up the token) is not in an
73   // ignored file. This is useful for situations where the token might originate
74   // from a macro in a system header: warning isn't useful, since system headers
75   // generally can't be easily updated.
76   SuppressibleDiagnosticBuilder ReportIfSpellingLocNotIgnored(
77       clang::SourceLocation loc,
78       unsigned diagnostic_id);
79 
80   void CheckVirtualMethods(clang::SourceLocation record_location,
81                            clang::CXXRecordDecl* record,
82                            bool warn_on_inline_bodies);
83   void CheckVirtualSpecifiers(const clang::CXXMethodDecl* method);
84   void CheckVirtualBodies(const clang::CXXMethodDecl* method);
85 
86   void CountType(const clang::Type* type,
87                  int* trivial_member,
88                  int* non_trivial_member,
89                  int* templated_non_trivial_member);
90 
91   static RefcountIssue CheckRecordForRefcountIssue(
92       const clang::CXXRecordDecl* record,
93       clang::SourceLocation& loc);
94   bool IsRefCounted(const clang::CXXBaseSpecifier* base,
95                     clang::CXXBasePath& path);
96   static bool HasPublicDtorCallback(const clang::CXXBaseSpecifier* base,
97                                     clang::CXXBasePath& path,
98                                     void* user_data);
99   void PrintInheritanceChain(const clang::CXXBasePath& path);
100   unsigned DiagnosticForIssue(RefcountIssue issue);
101   void CheckRefCountedDtors(clang::SourceLocation record_location,
102                             clang::CXXRecordDecl* record);
103 
104   void CheckWeakPtrFactoryMembers(clang::SourceLocation record_location,
105                                   clang::CXXRecordDecl* record);
106   void CheckEnumMaxValue(clang::EnumDecl* decl);
107   void CheckVarDecl(clang::VarDecl* decl);
108 
109   void ParseFunctionTemplates(clang::TranslationUnitDecl* decl);
110 
111   unsigned diag_method_requires_override_;
112   unsigned diag_redundant_virtual_specifier_;
113   unsigned diag_will_be_redundant_virtual_specifier_;
114   unsigned diag_base_method_virtual_and_final_;
115   unsigned diag_virtual_with_inline_body_;
116   unsigned diag_no_explicit_ctor_;
117   unsigned diag_no_explicit_copy_ctor_;
118   unsigned diag_inline_complex_ctor_;
119   unsigned diag_no_explicit_dtor_;
120   unsigned diag_inline_complex_dtor_;
121   unsigned diag_refcounted_needs_explicit_dtor_;
122   unsigned diag_refcounted_with_public_dtor_;
123   unsigned diag_refcounted_with_protected_non_virtual_dtor_;
124   unsigned diag_weak_ptr_factory_order_;
125   unsigned diag_bad_enum_max_value_;
126   unsigned diag_enum_max_value_unique_;
127   unsigned diag_auto_deduced_to_a_pointer_type_;
128   unsigned diag_note_inheritance_;
129   unsigned diag_note_implicit_dtor_;
130   unsigned diag_note_public_dtor_;
131   unsigned diag_note_protected_non_virtual_dtor_;
132 
133   std::unique_ptr<CheckIPCVisitor> ipc_visitor_;
134 };
135 
136 }  // namespace chrome_checker
137 
138 #endif  // TOOLS_CLANG_PLUGINS_FINDBADCONSTRUCTSCONSUMER_H_
139