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