Avi Drissman | dfd88085 | 2022-09-15 20:11:09 | [diff] [blame] | 1 | // Copyright 2012 The Chromium Authors |
[email protected] | 28cf60b | 2014-06-19 21:14:37 | [diff] [blame] | 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 | |
Xianzhu Wang | 86b1146 | 2022-09-24 22:00:12 | [diff] [blame] | 34 | #include "BlinkDataMemberTypeChecker.h" |
dskiba | 2bc8946 | 2016-04-06 15:51:06 | [diff] [blame] | 35 | #include "CheckIPCVisitor.h" |
Yuki Yamada | ead8ffe | 2021-10-21 06:09:31 | [diff] [blame] | 36 | #include "CheckLayoutObjectMethodsVisitor.h" |
[email protected] | 28cf60b | 2014-06-19 21:14:37 | [diff] [blame] | 37 | #include "ChromeClassTester.h" |
| 38 | #include "Options.h" |
Stefan Zager | e9734a5c | 2023-01-20 22:44:46 | [diff] [blame] | 39 | #include "StackAllocatedChecker.h" |
dcheng | 80484b1d | 2015-05-09 18:39:43 | [diff] [blame] | 40 | #include "SuppressibleDiagnosticBuilder.h" |
[email protected] | 28cf60b | 2014-06-19 21:14:37 | [diff] [blame] | 41 | |
| 42 | namespace chrome_checker { |
| 43 | |
| 44 | // 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] | 45 | class FindBadConstructsConsumer |
| 46 | : public clang::RecursiveASTVisitor<FindBadConstructsConsumer>, |
| 47 | public ChromeClassTester { |
[email protected] | 28cf60b | 2014-06-19 21:14:37 | [diff] [blame] | 48 | public: |
| 49 | FindBadConstructsConsumer(clang::CompilerInstance& instance, |
| 50 | const Options& options); |
| 51 | |
dskiba | 2bc8946 | 2016-04-06 15:51:06 | [diff] [blame] | 52 | void Traverse(clang::ASTContext& context); |
| 53 | |
dcheng | 80f54dc | 2015-01-07 19:13:49 | [diff] [blame] | 54 | // RecursiveASTVisitor: |
dskiba | 2bc8946 | 2016-04-06 15:51:06 | [diff] [blame] | 55 | bool TraverseDecl(clang::Decl* decl); |
danakj | fffdbb93 | 2024-06-07 17:11:41 | [diff] [blame] | 56 | bool VisitCXXConstructExpr(clang::CXXConstructExpr* expr); |
Stefan Zager | e9734a5c | 2023-01-20 22:44:46 | [diff] [blame] | 57 | bool VisitCXXRecordDecl(clang::CXXRecordDecl* cxx_record_decl); |
Daniel Cheng | d8358f64 | 2018-03-30 18:36:58 | [diff] [blame] | 58 | bool VisitEnumDecl(clang::EnumDecl* enum_decl); |
vmpstr | a48d78b | 2016-06-09 20:03:34 | [diff] [blame] | 59 | bool VisitTagDecl(clang::TagDecl* tag_decl); |
| 60 | bool VisitVarDecl(clang::VarDecl* var_decl); |
dskiba | 2bc8946 | 2016-04-06 15:51:06 | [diff] [blame] | 61 | bool VisitTemplateSpecializationType(clang::TemplateSpecializationType* spec); |
| 62 | bool VisitCallExpr(clang::CallExpr* call_expr); |
dcheng | 80f54dc | 2015-01-07 19:13:49 | [diff] [blame] | 63 | |
[email protected] | 28cf60b | 2014-06-19 21:14:37 | [diff] [blame] | 64 | // ChromeClassTester overrides: |
dcheng | 6aff6f1 | 2017-04-11 20:26:12 | [diff] [blame] | 65 | void CheckChromeClass(LocationType location_type, |
| 66 | clang::SourceLocation record_location, |
dcheng | 993e04f | 2014-09-28 19:27:54 | [diff] [blame] | 67 | clang::CXXRecordDecl* record) override; |
[email protected] | 28cf60b | 2014-06-19 21:14:37 | [diff] [blame] | 68 | |
| 69 | private: |
| 70 | // The type of problematic ref-counting pattern that was encountered. |
| 71 | enum RefcountIssue { None, ImplicitDestructor, PublicDestructor }; |
| 72 | |
| 73 | void CheckCtorDtorWeight(clang::SourceLocation record_location, |
| 74 | clang::CXXRecordDecl* record); |
| 75 | |
dcheng | 80484b1d | 2015-05-09 18:39:43 | [diff] [blame] | 76 | // Returns a diagnostic builder that only emits the diagnostic if the spelling |
| 77 | // location (the actual characters that make up the token) is not in an |
| 78 | // ignored file. This is useful for situations where the token might originate |
| 79 | // from a macro in a system header: warning isn't useful, since system headers |
| 80 | // generally can't be easily updated. |
| 81 | SuppressibleDiagnosticBuilder ReportIfSpellingLocNotIgnored( |
| 82 | clang::SourceLocation loc, |
| 83 | unsigned diagnostic_id); |
| 84 | |
[email protected] | 28cf60b | 2014-06-19 21:14:37 | [diff] [blame] | 85 | void CheckVirtualMethods(clang::SourceLocation record_location, |
| 86 | clang::CXXRecordDecl* record, |
| 87 | bool warn_on_inline_bodies); |
dcheng | 993e04f | 2014-09-28 19:27:54 | [diff] [blame] | 88 | void CheckVirtualSpecifiers(const clang::CXXMethodDecl* method); |
| 89 | void CheckVirtualBodies(const clang::CXXMethodDecl* method); |
[email protected] | 28cf60b | 2014-06-19 21:14:37 | [diff] [blame] | 90 | |
Will Cassella | 64da6c5 | 2022-01-06 18:13:57 | [diff] [blame] | 91 | enum class TypeClassification { |
| 92 | kTrivial, |
| 93 | kNonTrivial, |
| 94 | kTrivialTemplate, |
| 95 | kNonTrivialTemplate, |
| 96 | kNonTrivialExternTemplate |
| 97 | }; |
| 98 | TypeClassification ClassifyType(const clang::Type* type); |
| 99 | |
[email protected] | 28cf60b | 2014-06-19 21:14:37 | [diff] [blame] | 100 | static RefcountIssue CheckRecordForRefcountIssue( |
| 101 | const clang::CXXRecordDecl* record, |
| 102 | clang::SourceLocation& loc); |
Nico Weber | 8805f84 | 2015-07-25 18:41:04 | [diff] [blame] | 103 | bool IsRefCounted(const clang::CXXBaseSpecifier* base, |
| 104 | clang::CXXBasePath& path); |
[email protected] | 28cf60b | 2014-06-19 21:14:37 | [diff] [blame] | 105 | static bool HasPublicDtorCallback(const clang::CXXBaseSpecifier* base, |
| 106 | clang::CXXBasePath& path, |
| 107 | void* user_data); |
| 108 | void PrintInheritanceChain(const clang::CXXBasePath& path); |
| 109 | unsigned DiagnosticForIssue(RefcountIssue issue); |
| 110 | void CheckRefCountedDtors(clang::SourceLocation record_location, |
| 111 | clang::CXXRecordDecl* record); |
| 112 | |
| 113 | void CheckWeakPtrFactoryMembers(clang::SourceLocation record_location, |
| 114 | clang::CXXRecordDecl* record); |
Daniel Cheng | d8358f64 | 2018-03-30 18:36:58 | [diff] [blame] | 115 | void CheckEnumMaxValue(clang::EnumDecl* decl); |
danakj | 3296e9e1 | 2024-02-05 21:33:59 | [diff] [blame] | 116 | void CheckDeducedAutoPointer(clang::VarDecl* decl); |
danakj | fffdbb93 | 2024-06-07 17:11:41 | [diff] [blame] | 117 | void CheckConstructingSpanFromStringLiteral( |
| 118 | clang::CXXConstructorDecl* ctor_decl, |
| 119 | llvm::ArrayRef<const clang::Expr*> args, |
| 120 | clang::SourceLocation loc); |
[email protected] | 28cf60b | 2014-06-19 21:14:37 | [diff] [blame] | 121 | |
dskiba | 2bc8946 | 2016-04-06 15:51:06 | [diff] [blame] | 122 | void ParseFunctionTemplates(clang::TranslationUnitDecl* decl); |
| 123 | |
[email protected] | 28cf60b | 2014-06-19 21:14:37 | [diff] [blame] | 124 | unsigned diag_method_requires_override_; |
dcheng | 993e04f | 2014-09-28 19:27:54 | [diff] [blame] | 125 | unsigned diag_redundant_virtual_specifier_; |
Daniel Cheng | 1d51449 | 2017-10-24 17:49:53 | [diff] [blame] | 126 | unsigned diag_will_be_redundant_virtual_specifier_; |
dcheng | 993e04f | 2014-09-28 19:27:54 | [diff] [blame] | 127 | unsigned diag_base_method_virtual_and_final_; |
Daniel Cheng | 2fb72ec | 2017-09-15 22:15:56 | [diff] [blame] | 128 | unsigned diag_virtual_with_inline_body_; |
| 129 | unsigned diag_no_explicit_ctor_; |
| 130 | unsigned diag_no_explicit_copy_ctor_; |
| 131 | unsigned diag_inline_complex_ctor_; |
[email protected] | 28cf60b | 2014-06-19 21:14:37 | [diff] [blame] | 132 | unsigned diag_no_explicit_dtor_; |
Daniel Cheng | 2fb72ec | 2017-09-15 22:15:56 | [diff] [blame] | 133 | unsigned diag_inline_complex_dtor_; |
| 134 | unsigned diag_refcounted_needs_explicit_dtor_; |
| 135 | unsigned diag_refcounted_with_public_dtor_; |
| 136 | unsigned diag_refcounted_with_protected_non_virtual_dtor_; |
[email protected] | 28cf60b | 2014-06-19 21:14:37 | [diff] [blame] | 137 | unsigned diag_weak_ptr_factory_order_; |
Daniel Cheng | d8358f64 | 2018-03-30 18:36:58 | [diff] [blame] | 138 | unsigned diag_bad_enum_max_value_; |
| 139 | unsigned diag_enum_max_value_unique_; |
vmpstr | a48d78b | 2016-06-09 20:03:34 | [diff] [blame] | 140 | unsigned diag_auto_deduced_to_a_pointer_type_; |
[email protected] | 28cf60b | 2014-06-19 21:14:37 | [diff] [blame] | 141 | unsigned diag_note_inheritance_; |
| 142 | unsigned diag_note_implicit_dtor_; |
| 143 | unsigned diag_note_public_dtor_; |
| 144 | unsigned diag_note_protected_non_virtual_dtor_; |
danakj | fffdbb93 | 2024-06-07 17:11:41 | [diff] [blame] | 145 | unsigned diag_span_from_string_literal_; |
| 146 | unsigned diag_note_span_from_string_literal1_; |
dskiba | 2bc8946 | 2016-04-06 15:51:06 | [diff] [blame] | 147 | |
Xianzhu Wang | 86b1146 | 2022-09-24 22:00:12 | [diff] [blame] | 148 | std::unique_ptr<BlinkDataMemberTypeChecker> blink_data_member_type_checker_; |
dskiba | 2bc8946 | 2016-04-06 15:51:06 | [diff] [blame] | 149 | std::unique_ptr<CheckIPCVisitor> ipc_visitor_; |
Yuki Yamada | ead8ffe | 2021-10-21 06:09:31 | [diff] [blame] | 150 | std::unique_ptr<CheckLayoutObjectMethodsVisitor> layout_visitor_; |
Stefan Zager | e9734a5c | 2023-01-20 22:44:46 | [diff] [blame] | 151 | std::unique_ptr<StackAllocatedChecker> stack_allocated_checker_; |
[email protected] | 28cf60b | 2014-06-19 21:14:37 | [diff] [blame] | 152 | }; |
| 153 | |
| 154 | } // namespace chrome_checker |
dcheng | 80484b1d | 2015-05-09 18:39:43 | [diff] [blame] | 155 | |
| 156 | #endif // TOOLS_CLANG_PLUGINS_FINDBADCONSTRUCTSCONSUMER_H_ |