[email protected] | 28cf60b | 2014-06-19 21:14:37 | [diff] [blame] | 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 | |
dcheng | 80484b1d | 2015-05-09 18:39:43 | [diff] [blame] | 20 | #ifndef TOOLS_CLANG_PLUGINS_FINDBADCONSTRUCTSCONSUMER_H_ |
| 21 | #define TOOLS_CLANG_PLUGINS_FINDBADCONSTRUCTSCONSUMER_H_ |
| 22 | |
dskiba | 2bc8946 | 2016-04-06 15:51:06 | [diff] [blame] | 23 | #include <memory> |
| 24 | |
[email protected] | 28cf60b | 2014-06-19 21:14:37 | [diff] [blame] | 25 | #include "clang/AST/AST.h" |
| 26 | #include "clang/AST/ASTConsumer.h" |
| 27 | #include "clang/AST/Attr.h" |
| 28 | #include "clang/AST/CXXInheritance.h" |
dcheng | 80f54dc | 2015-01-07 19:13:49 | [diff] [blame] | 29 | #include "clang/AST/RecursiveASTVisitor.h" |
[email protected] | 28cf60b | 2014-06-19 21:14:37 | [diff] [blame] | 30 | #include "clang/AST/TypeLoc.h" |
| 31 | #include "clang/Basic/SourceManager.h" |
dcheng | 80484b1d | 2015-05-09 18:39:43 | [diff] [blame] | 32 | #include "clang/Basic/SourceLocation.h" |
[email protected] | 28cf60b | 2014-06-19 21:14:37 | [diff] [blame] | 33 | |
dskiba | 2bc8946 | 2016-04-06 15:51:06 | [diff] [blame] | 34 | #include "CheckIPCVisitor.h" |
Yuki Yamada | ead8ffe | 2021-10-21 06:09:31 | [diff] [blame^] | 35 | #include "CheckLayoutObjectMethodsVisitor.h" |
[email protected] | 28cf60b | 2014-06-19 21:14:37 | [diff] [blame] | 36 | #include "ChromeClassTester.h" |
| 37 | #include "Options.h" |
dcheng | 80484b1d | 2015-05-09 18:39:43 | [diff] [blame] | 38 | #include "SuppressibleDiagnosticBuilder.h" |
[email protected] | 28cf60b | 2014-06-19 21:14:37 | [diff] [blame] | 39 | |
| 40 | namespace chrome_checker { |
| 41 | |
| 42 | // Searches for constructs that we know we don't want in the Chromium code base. |
dcheng | 80f54dc | 2015-01-07 19:13:49 | [diff] [blame] | 43 | class FindBadConstructsConsumer |
| 44 | : public clang::RecursiveASTVisitor<FindBadConstructsConsumer>, |
| 45 | public ChromeClassTester { |
[email protected] | 28cf60b | 2014-06-19 21:14:37 | [diff] [blame] | 46 | public: |
| 47 | FindBadConstructsConsumer(clang::CompilerInstance& instance, |
| 48 | const Options& options); |
| 49 | |
dskiba | 2bc8946 | 2016-04-06 15:51:06 | [diff] [blame] | 50 | void Traverse(clang::ASTContext& context); |
| 51 | |
dcheng | 80f54dc | 2015-01-07 19:13:49 | [diff] [blame] | 52 | // RecursiveASTVisitor: |
dskiba | 2bc8946 | 2016-04-06 15:51:06 | [diff] [blame] | 53 | bool TraverseDecl(clang::Decl* decl); |
Daniel Cheng | d8358f64 | 2018-03-30 18:36:58 | [diff] [blame] | 54 | bool VisitEnumDecl(clang::EnumDecl* enum_decl); |
vmpstr | a48d78b | 2016-06-09 20:03:34 | [diff] [blame] | 55 | bool VisitTagDecl(clang::TagDecl* tag_decl); |
| 56 | bool VisitVarDecl(clang::VarDecl* var_decl); |
dskiba | 2bc8946 | 2016-04-06 15:51:06 | [diff] [blame] | 57 | bool VisitTemplateSpecializationType(clang::TemplateSpecializationType* spec); |
| 58 | bool VisitCallExpr(clang::CallExpr* call_expr); |
dcheng | 80f54dc | 2015-01-07 19:13:49 | [diff] [blame] | 59 | |
[email protected] | 28cf60b | 2014-06-19 21:14:37 | [diff] [blame] | 60 | // ChromeClassTester overrides: |
dcheng | 6aff6f1 | 2017-04-11 20:26:12 | [diff] [blame] | 61 | void CheckChromeClass(LocationType location_type, |
| 62 | clang::SourceLocation record_location, |
dcheng | 993e04f | 2014-09-28 19:27:54 | [diff] [blame] | 63 | clang::CXXRecordDecl* record) override; |
[email protected] | 28cf60b | 2014-06-19 21:14:37 | [diff] [blame] | 64 | |
| 65 | private: |
| 66 | // The type of problematic ref-counting pattern that was encountered. |
| 67 | enum RefcountIssue { None, ImplicitDestructor, PublicDestructor }; |
| 68 | |
| 69 | void CheckCtorDtorWeight(clang::SourceLocation record_location, |
| 70 | clang::CXXRecordDecl* record); |
| 71 | |
dcheng | 80484b1d | 2015-05-09 18:39:43 | [diff] [blame] | 72 | // Returns a diagnostic builder that only emits the diagnostic if the spelling |
| 73 | // location (the actual characters that make up the token) is not in an |
| 74 | // ignored file. This is useful for situations where the token might originate |
| 75 | // from a macro in a system header: warning isn't useful, since system headers |
| 76 | // generally can't be easily updated. |
| 77 | SuppressibleDiagnosticBuilder ReportIfSpellingLocNotIgnored( |
| 78 | clang::SourceLocation loc, |
dcheng | 80484b1d | 2015-05-09 18:39:43 | [diff] [blame] | 79 | unsigned diagnostic_id); |
| 80 | |
[email protected] | 28cf60b | 2014-06-19 21:14:37 | [diff] [blame] | 81 | void CheckVirtualMethods(clang::SourceLocation record_location, |
| 82 | clang::CXXRecordDecl* record, |
| 83 | bool warn_on_inline_bodies); |
dcheng | 993e04f | 2014-09-28 19:27:54 | [diff] [blame] | 84 | void CheckVirtualSpecifiers(const clang::CXXMethodDecl* method); |
| 85 | void CheckVirtualBodies(const clang::CXXMethodDecl* method); |
[email protected] | 28cf60b | 2014-06-19 21:14:37 | [diff] [blame] | 86 | |
| 87 | void CountType(const clang::Type* type, |
| 88 | int* trivial_member, |
| 89 | int* non_trivial_member, |
| 90 | int* templated_non_trivial_member); |
| 91 | |
| 92 | static RefcountIssue CheckRecordForRefcountIssue( |
| 93 | const clang::CXXRecordDecl* record, |
| 94 | clang::SourceLocation& loc); |
Nico Weber | 8805f84 | 2015-07-25 18:41:04 | [diff] [blame] | 95 | bool IsRefCounted(const clang::CXXBaseSpecifier* base, |
| 96 | clang::CXXBasePath& path); |
[email protected] | 28cf60b | 2014-06-19 21:14:37 | [diff] [blame] | 97 | static bool HasPublicDtorCallback(const clang::CXXBaseSpecifier* base, |
| 98 | clang::CXXBasePath& path, |
| 99 | void* user_data); |
| 100 | void PrintInheritanceChain(const clang::CXXBasePath& path); |
| 101 | unsigned DiagnosticForIssue(RefcountIssue issue); |
| 102 | void CheckRefCountedDtors(clang::SourceLocation record_location, |
| 103 | clang::CXXRecordDecl* record); |
| 104 | |
| 105 | void CheckWeakPtrFactoryMembers(clang::SourceLocation record_location, |
| 106 | clang::CXXRecordDecl* record); |
Daniel Cheng | d8358f64 | 2018-03-30 18:36:58 | [diff] [blame] | 107 | void CheckEnumMaxValue(clang::EnumDecl* decl); |
vmpstr | a48d78b | 2016-06-09 20:03:34 | [diff] [blame] | 108 | void CheckVarDecl(clang::VarDecl* decl); |
[email protected] | 28cf60b | 2014-06-19 21:14:37 | [diff] [blame] | 109 | |
dskiba | 2bc8946 | 2016-04-06 15:51:06 | [diff] [blame] | 110 | void ParseFunctionTemplates(clang::TranslationUnitDecl* decl); |
| 111 | |
[email protected] | 28cf60b | 2014-06-19 21:14:37 | [diff] [blame] | 112 | unsigned diag_method_requires_override_; |
dcheng | 993e04f | 2014-09-28 19:27:54 | [diff] [blame] | 113 | unsigned diag_redundant_virtual_specifier_; |
Daniel Cheng | 1d51449 | 2017-10-24 17:49:53 | [diff] [blame] | 114 | unsigned diag_will_be_redundant_virtual_specifier_; |
dcheng | 993e04f | 2014-09-28 19:27:54 | [diff] [blame] | 115 | unsigned diag_base_method_virtual_and_final_; |
Daniel Cheng | 2fb72ec | 2017-09-15 22:15:56 | [diff] [blame] | 116 | unsigned diag_virtual_with_inline_body_; |
| 117 | unsigned diag_no_explicit_ctor_; |
| 118 | unsigned diag_no_explicit_copy_ctor_; |
| 119 | unsigned diag_inline_complex_ctor_; |
[email protected] | 28cf60b | 2014-06-19 21:14:37 | [diff] [blame] | 120 | unsigned diag_no_explicit_dtor_; |
Daniel Cheng | 2fb72ec | 2017-09-15 22:15:56 | [diff] [blame] | 121 | unsigned diag_inline_complex_dtor_; |
| 122 | unsigned diag_refcounted_needs_explicit_dtor_; |
| 123 | unsigned diag_refcounted_with_public_dtor_; |
| 124 | unsigned diag_refcounted_with_protected_non_virtual_dtor_; |
[email protected] | 28cf60b | 2014-06-19 21:14:37 | [diff] [blame] | 125 | unsigned diag_weak_ptr_factory_order_; |
Daniel Cheng | d8358f64 | 2018-03-30 18:36:58 | [diff] [blame] | 126 | unsigned diag_bad_enum_max_value_; |
| 127 | unsigned diag_enum_max_value_unique_; |
vmpstr | a48d78b | 2016-06-09 20:03:34 | [diff] [blame] | 128 | unsigned diag_auto_deduced_to_a_pointer_type_; |
[email protected] | 28cf60b | 2014-06-19 21:14:37 | [diff] [blame] | 129 | unsigned diag_note_inheritance_; |
| 130 | unsigned diag_note_implicit_dtor_; |
| 131 | unsigned diag_note_public_dtor_; |
| 132 | unsigned diag_note_protected_non_virtual_dtor_; |
dskiba | 2bc8946 | 2016-04-06 15:51:06 | [diff] [blame] | 133 | |
| 134 | std::unique_ptr<CheckIPCVisitor> ipc_visitor_; |
Yuki Yamada | ead8ffe | 2021-10-21 06:09:31 | [diff] [blame^] | 135 | std::unique_ptr<CheckLayoutObjectMethodsVisitor> layout_visitor_; |
[email protected] | 28cf60b | 2014-06-19 21:14:37 | [diff] [blame] | 136 | }; |
| 137 | |
| 138 | } // namespace chrome_checker |
dcheng | 80484b1d | 2015-05-09 18:39:43 | [diff] [blame] | 139 | |
| 140 | #endif // TOOLS_CLANG_PLUGINS_FINDBADCONSTRUCTSCONSUMER_H_ |