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