Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(285)

Side by Side Diff: tools/clang/plugins/FindBadConstructs.cpp

Issue 150943005: Add a check to the FindBadConstructs.cpp clang plugin for bad enum last values. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix comment. Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « tools/clang/plugins/ChromeClassTester.cpp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // This file defines a bunch of recurring problems in the Chromium C++ code. 5 // This file defines a bunch of recurring problems in the Chromium C++ code.
6 // 6 //
7 // Checks that are implemented: 7 // Checks that are implemented:
8 // - Constructors/Destructors should not be inlined if they are of a complex 8 // - Constructors/Destructors should not be inlined if they are of a complex
9 // class type. 9 // class type.
10 // - Missing "virtual" keywords on methods that should be virtual. 10 // - Missing "virtual" keywords on methods that should be virtual.
11 // - Non-annotated overriding virtual methods. 11 // - Non-annotated overriding virtual methods.
12 // - Virtual methods with nonempty implementations in their headers. 12 // - Virtual methods with nonempty implementations in their headers.
13 // - Classes that derive from base::RefCounted / base::RefCountedThreadSafe 13 // - Classes that derive from base::RefCounted / base::RefCountedThreadSafe
14 // should have protected or private destructors. 14 // should have protected or private destructors.
15 // - WeakPtrFactory members that refer to their outer class should be the last 15 // - WeakPtrFactory members that refer to their outer class should be the last
16 // member. 16 // member.
17 // - Enum types with a xxxx_LAST or xxxxLast const actually have that constant
18 // have the maximal value for that type.
17 19
18 #include "clang/AST/ASTConsumer.h" 20 #include "clang/AST/ASTConsumer.h"
19 #include "clang/AST/AST.h" 21 #include "clang/AST/AST.h"
20 #include "clang/AST/Attr.h" 22 #include "clang/AST/Attr.h"
21 #include "clang/AST/CXXInheritance.h" 23 #include "clang/AST/CXXInheritance.h"
22 #include "clang/AST/TypeLoc.h" 24 #include "clang/AST/TypeLoc.h"
23 #include "clang/Basic/SourceManager.h" 25 #include "clang/Basic/SourceManager.h"
24 #include "clang/Frontend/CompilerInstance.h" 26 #include "clang/Frontend/CompilerInstance.h"
25 #include "clang/Frontend/FrontendPluginRegistry.h" 27 #include "clang/Frontend/FrontendPluginRegistry.h"
26 #include "clang/Lex/Lexer.h" 28 #include "clang/Lex/Lexer.h"
(...skipping 14 matching lines...) Expand all
41 "destructors that are declared protected or private."; 43 "destructors that are declared protected or private.";
42 const char kPublicDtor[] = 44 const char kPublicDtor[] =
43 "[chromium-style] Classes that are ref-counted should have " 45 "[chromium-style] Classes that are ref-counted should have "
44 "destructors that are declared protected or private."; 46 "destructors that are declared protected or private.";
45 const char kProtectedNonVirtualDtor[] = 47 const char kProtectedNonVirtualDtor[] =
46 "[chromium-style] Classes that are ref-counted and have non-private " 48 "[chromium-style] Classes that are ref-counted and have non-private "
47 "destructors should declare their destructor virtual."; 49 "destructors should declare their destructor virtual.";
48 const char kWeakPtrFactoryOrder[] = 50 const char kWeakPtrFactoryOrder[] =
49 "[chromium-style] WeakPtrFactory members which refer to their outer class " 51 "[chromium-style] WeakPtrFactory members which refer to their outer class "
50 "must be the last member in the outer class definition."; 52 "must be the last member in the outer class definition.";
53 const char kBadLastEnumValue[] =
54 "[chromium-style] _LAST/Last constants of enum types must have the maximal "
55 "value for any constant of that type.";
51 const char kNoteInheritance[] = 56 const char kNoteInheritance[] =
52 "[chromium-style] %0 inherits from %1 here"; 57 "[chromium-style] %0 inherits from %1 here";
53 const char kNoteImplicitDtor[] = 58 const char kNoteImplicitDtor[] =
54 "[chromium-style] No explicit destructor for %0 defined"; 59 "[chromium-style] No explicit destructor for %0 defined";
55 const char kNotePublicDtor[] = 60 const char kNotePublicDtor[] =
56 "[chromium-style] Public destructor declared here"; 61 "[chromium-style] Public destructor declared here";
57 const char kNoteProtectedNonVirtualDtor[] = 62 const char kNoteProtectedNonVirtualDtor[] =
58 "[chromium-style] Protected non-virtual destructor declared here"; 63 "[chromium-style] Protected non-virtual destructor declared here";
59 64
60 bool TypeHasNonTrivialDtor(const Type* type) { 65 bool TypeHasNonTrivialDtor(const Type* type) {
(...skipping 11 matching lines...) Expand all
72 return UnwrapType(elaborated->getNamedType().getTypePtr()); 77 return UnwrapType(elaborated->getNamedType().getTypePtr());
73 if (const TypedefType* typedefed = dyn_cast<TypedefType>(type)) 78 if (const TypedefType* typedefed = dyn_cast<TypedefType>(type))
74 return UnwrapType(typedefed->desugar().getTypePtr()); 79 return UnwrapType(typedefed->desugar().getTypePtr());
75 return type; 80 return type;
76 } 81 }
77 82
78 struct FindBadConstructsOptions { 83 struct FindBadConstructsOptions {
79 FindBadConstructsOptions() : check_base_classes(false), 84 FindBadConstructsOptions() : check_base_classes(false),
80 check_virtuals_in_implementations(true), 85 check_virtuals_in_implementations(true),
81 check_url_directory(false), 86 check_url_directory(false),
82 check_weak_ptr_factory_order(false) { 87 check_weak_ptr_factory_order(false),
88 check_bad_enum_last_value(true) {
83 } 89 }
84 bool check_base_classes; 90 bool check_base_classes;
85 bool check_virtuals_in_implementations; 91 bool check_virtuals_in_implementations;
86 bool check_url_directory; 92 bool check_url_directory;
87 bool check_weak_ptr_factory_order; 93 bool check_weak_ptr_factory_order;
94 bool check_bad_enum_last_value;
88 }; 95 };
89 96
90 // Searches for constructs that we know we don't want in the Chromium code base. 97 // Searches for constructs that we know we don't want in the Chromium code base.
91 class FindBadConstructsConsumer : public ChromeClassTester { 98 class FindBadConstructsConsumer : public ChromeClassTester {
92 public: 99 public:
93 FindBadConstructsConsumer(CompilerInstance& instance, 100 FindBadConstructsConsumer(CompilerInstance& instance,
94 const FindBadConstructsOptions& options) 101 const FindBadConstructsOptions& options)
95 : ChromeClassTester(instance, options.check_url_directory), 102 : ChromeClassTester(instance, options.check_url_directory),
96 options_(options) { 103 options_(options) {
97 // Register warning/error messages. 104 // Register warning/error messages.
98 diag_method_requires_override_ = diagnostic().getCustomDiagID( 105 diag_method_requires_override_ = diagnostic().getCustomDiagID(
99 getErrorLevel(), kMethodRequiresOverride); 106 getErrorLevel(), kMethodRequiresOverride);
100 diag_method_requires_virtual_ = diagnostic().getCustomDiagID( 107 diag_method_requires_virtual_ = diagnostic().getCustomDiagID(
101 getErrorLevel(), kMethodRequiresVirtual); 108 getErrorLevel(), kMethodRequiresVirtual);
102 diag_no_explicit_dtor_ = diagnostic().getCustomDiagID( 109 diag_no_explicit_dtor_ = diagnostic().getCustomDiagID(
103 getErrorLevel(), kNoExplicitDtor); 110 getErrorLevel(), kNoExplicitDtor);
104 diag_public_dtor_ = diagnostic().getCustomDiagID( 111 diag_public_dtor_ = diagnostic().getCustomDiagID(
105 getErrorLevel(), kPublicDtor); 112 getErrorLevel(), kPublicDtor);
106 diag_protected_non_virtual_dtor_ = diagnostic().getCustomDiagID( 113 diag_protected_non_virtual_dtor_ = diagnostic().getCustomDiagID(
107 getErrorLevel(), kProtectedNonVirtualDtor); 114 getErrorLevel(), kProtectedNonVirtualDtor);
108 diag_weak_ptr_factory_order_ = diagnostic().getCustomDiagID( 115 diag_weak_ptr_factory_order_ = diagnostic().getCustomDiagID(
109 getErrorLevel(), kWeakPtrFactoryOrder); 116 getErrorLevel(), kWeakPtrFactoryOrder);
117 diag_bad_enum_last_value_ = diagnostic().getCustomDiagID(
118 getErrorLevel(), kBadLastEnumValue);
110 119
111 // Registers notes to make it easier to interpret warnings. 120 // Registers notes to make it easier to interpret warnings.
112 diag_note_inheritance_ = diagnostic().getCustomDiagID( 121 diag_note_inheritance_ = diagnostic().getCustomDiagID(
113 DiagnosticsEngine::Note, kNoteInheritance); 122 DiagnosticsEngine::Note, kNoteInheritance);
114 diag_note_implicit_dtor_ = diagnostic().getCustomDiagID( 123 diag_note_implicit_dtor_ = diagnostic().getCustomDiagID(
115 DiagnosticsEngine::Note, kNoteImplicitDtor); 124 DiagnosticsEngine::Note, kNoteImplicitDtor);
116 diag_note_public_dtor_ = diagnostic().getCustomDiagID( 125 diag_note_public_dtor_ = diagnostic().getCustomDiagID(
117 DiagnosticsEngine::Note, kNotePublicDtor); 126 DiagnosticsEngine::Note, kNotePublicDtor);
118 diag_note_protected_non_virtual_dtor_ = diagnostic().getCustomDiagID( 127 diag_note_protected_non_virtual_dtor_ = diagnostic().getCustomDiagID(
119 DiagnosticsEngine::Note, kNoteProtectedNonVirtualDtor); 128 DiagnosticsEngine::Note, kNoteProtectedNonVirtualDtor);
(...skipping 16 matching lines...) Expand all
136 // virtual and OVERRIDE. 145 // virtual and OVERRIDE.
137 CheckVirtualMethods(record_location, record, warn_on_inline_bodies); 146 CheckVirtualMethods(record_location, record, warn_on_inline_bodies);
138 } 147 }
139 148
140 CheckRefCountedDtors(record_location, record); 149 CheckRefCountedDtors(record_location, record);
141 150
142 if (options_.check_weak_ptr_factory_order) 151 if (options_.check_weak_ptr_factory_order)
143 CheckWeakPtrFactoryMembers(record_location, record); 152 CheckWeakPtrFactoryMembers(record_location, record);
144 } 153 }
145 154
155 virtual void CheckChromeEnum(SourceLocation enum_location,
156 EnumDecl* enum_decl) {
157 if (options_.check_bad_enum_last_value) {
darin (slow to review) 2014/02/12 05:59:47 nit: I recommend returning early if this option is
158 bool got_one = false;
159 llvm::APSInt max_so_far;
160 EnumDecl::enumerator_iterator iter;
161 for (iter = enum_decl->enumerator_begin();
162 iter != enum_decl->enumerator_end(); ++iter) {
163 if (!got_one) {
164 max_so_far = iter->getInitVal();
165 got_one = true;
166 } else if (iter->getInitVal() > max_so_far)
167 max_so_far = iter->getInitVal();
168 }
169 for (iter = enum_decl->enumerator_begin();
170 iter != enum_decl->enumerator_end(); ++iter) {
171 std::string name = iter->getNameAsString();
172 if (((name.size() > 4 &&
173 name.compare(name.size() - 4, 4, "Last") == 0) ||
174 (name.size() > 5 &&
175 name.compare(name.size() - 5, 5, "_LAST") == 0)) &&
176 iter->getInitVal() < max_so_far) {
177 diagnostic().Report(iter->getLocation(), diag_bad_enum_last_value_);
178 }
179 }
180 }
181 }
182
146 private: 183 private:
147 // The type of problematic ref-counting pattern that was encountered. 184 // The type of problematic ref-counting pattern that was encountered.
148 enum RefcountIssue { 185 enum RefcountIssue {
149 None, 186 None,
150 ImplicitDestructor, 187 ImplicitDestructor,
151 PublicDestructor 188 PublicDestructor
152 }; 189 };
153 190
154 FindBadConstructsOptions options_; 191 FindBadConstructsOptions options_;
155 192
156 unsigned diag_method_requires_override_; 193 unsigned diag_method_requires_override_;
157 unsigned diag_method_requires_virtual_; 194 unsigned diag_method_requires_virtual_;
158 unsigned diag_no_explicit_dtor_; 195 unsigned diag_no_explicit_dtor_;
159 unsigned diag_public_dtor_; 196 unsigned diag_public_dtor_;
160 unsigned diag_protected_non_virtual_dtor_; 197 unsigned diag_protected_non_virtual_dtor_;
161 unsigned diag_weak_ptr_factory_order_; 198 unsigned diag_weak_ptr_factory_order_;
199 unsigned diag_bad_enum_last_value_;
162 unsigned diag_note_inheritance_; 200 unsigned diag_note_inheritance_;
163 unsigned diag_note_implicit_dtor_; 201 unsigned diag_note_implicit_dtor_;
164 unsigned diag_note_public_dtor_; 202 unsigned diag_note_public_dtor_;
165 unsigned diag_note_protected_non_virtual_dtor_; 203 unsigned diag_note_protected_non_virtual_dtor_;
166 204
167 // Prints errors if the constructor/destructor weight is too heavy. 205 // Prints errors if the constructor/destructor weight is too heavy.
168 void CheckCtorDtorWeight(SourceLocation record_location, 206 void CheckCtorDtorWeight(SourceLocation record_location,
169 CXXRecordDecl* record) { 207 CXXRecordDecl* record) {
170 // We don't handle anonymous structs. If this record doesn't have a 208 // We don't handle anonymous structs. If this record doesn't have a
171 // name, it's of the form: 209 // name, it's of the form:
(...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after
705 options_.check_virtuals_in_implementations = false; 743 options_.check_virtuals_in_implementations = false;
706 } else if (args[i] == "check-base-classes") { 744 } else if (args[i] == "check-base-classes") {
707 // TODO(rsleevi): Remove this once http://crbug.com/123295 is fixed. 745 // TODO(rsleevi): Remove this once http://crbug.com/123295 is fixed.
708 options_.check_base_classes = true; 746 options_.check_base_classes = true;
709 } else if (args[i] == "check-url-directory") { 747 } else if (args[i] == "check-url-directory") {
710 // TODO(tfarina): Remove this once http://crbug.com/229660 is fixed. 748 // TODO(tfarina): Remove this once http://crbug.com/229660 is fixed.
711 options_.check_url_directory = true; 749 options_.check_url_directory = true;
712 } else if (args[i] == "check-weak-ptr-factory-order") { 750 } else if (args[i] == "check-weak-ptr-factory-order") {
713 // TODO(dmichael): Remove this once http://crbug.com/303818 is fixed. 751 // TODO(dmichael): Remove this once http://crbug.com/303818 is fixed.
714 options_.check_weak_ptr_factory_order = true; 752 options_.check_weak_ptr_factory_order = true;
753 } else if (args[i] == "check-bad-enum-last-value") {
754 options_.check_bad_enum_last_value = true;
715 } else { 755 } else {
716 parsed = false; 756 parsed = false;
717 llvm::errs() << "Unknown clang plugin argument: " << args[i] << "\n"; 757 llvm::errs() << "Unknown clang plugin argument: " << args[i] << "\n";
718 } 758 }
719 } 759 }
720 760
721 return parsed; 761 return parsed;
722 } 762 }
723 763
724 private: 764 private:
725 FindBadConstructsOptions options_; 765 FindBadConstructsOptions options_;
726 }; 766 };
727 767
728 } // namespace 768 } // namespace
729 769
730 static FrontendPluginRegistry::Add<FindBadConstructsAction> 770 static FrontendPluginRegistry::Add<FindBadConstructsAction>
731 X("find-bad-constructs", "Finds bad C++ constructs"); 771 X("find-bad-constructs", "Finds bad C++ constructs");
OLDNEW
« no previous file with comments | « tools/clang/plugins/ChromeClassTester.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698