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

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

Issue 213403010: Re-enable the clang check for enum constants. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix copyright line. Created 6 years, 9 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
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 10 matching lines...) Expand all
71 if (const ElaboratedType* elaborated = dyn_cast<ElaboratedType>(type)) 76 if (const ElaboratedType* elaborated = dyn_cast<ElaboratedType>(type))
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_weak_ptr_factory_order(false) { 86 check_weak_ptr_factory_order(false),
87 check_enum_last_value(true) {
82 } 88 }
83 bool check_base_classes; 89 bool check_base_classes;
84 bool check_virtuals_in_implementations; 90 bool check_virtuals_in_implementations;
85 bool check_weak_ptr_factory_order; 91 bool check_weak_ptr_factory_order;
92 bool check_enum_last_value;
86 }; 93 };
87 94
88 // Searches for constructs that we know we don't want in the Chromium code base. 95 // Searches for constructs that we know we don't want in the Chromium code base.
89 class FindBadConstructsConsumer : public ChromeClassTester { 96 class FindBadConstructsConsumer : public ChromeClassTester {
90 public: 97 public:
91 FindBadConstructsConsumer(CompilerInstance& instance, 98 FindBadConstructsConsumer(CompilerInstance& instance,
92 const FindBadConstructsOptions& options) 99 const FindBadConstructsOptions& options)
93 : ChromeClassTester(instance), 100 : ChromeClassTester(instance),
94 options_(options) { 101 options_(options) {
95 // Register warning/error messages. 102 // Register warning/error messages.
96 diag_method_requires_override_ = diagnostic().getCustomDiagID( 103 diag_method_requires_override_ = diagnostic().getCustomDiagID(
97 getErrorLevel(), kMethodRequiresOverride); 104 getErrorLevel(), kMethodRequiresOverride);
98 diag_method_requires_virtual_ = diagnostic().getCustomDiagID( 105 diag_method_requires_virtual_ = diagnostic().getCustomDiagID(
99 getErrorLevel(), kMethodRequiresVirtual); 106 getErrorLevel(), kMethodRequiresVirtual);
100 diag_no_explicit_dtor_ = diagnostic().getCustomDiagID( 107 diag_no_explicit_dtor_ = diagnostic().getCustomDiagID(
101 getErrorLevel(), kNoExplicitDtor); 108 getErrorLevel(), kNoExplicitDtor);
102 diag_public_dtor_ = diagnostic().getCustomDiagID( 109 diag_public_dtor_ = diagnostic().getCustomDiagID(
103 getErrorLevel(), kPublicDtor); 110 getErrorLevel(), kPublicDtor);
104 diag_protected_non_virtual_dtor_ = diagnostic().getCustomDiagID( 111 diag_protected_non_virtual_dtor_ = diagnostic().getCustomDiagID(
105 getErrorLevel(), kProtectedNonVirtualDtor); 112 getErrorLevel(), kProtectedNonVirtualDtor);
106 diag_weak_ptr_factory_order_ = diagnostic().getCustomDiagID( 113 diag_weak_ptr_factory_order_ = diagnostic().getCustomDiagID(
107 getErrorLevel(), kWeakPtrFactoryOrder); 114 getErrorLevel(), kWeakPtrFactoryOrder);
115 diag_bad_enum_last_value_ = diagnostic().getCustomDiagID(
116 getErrorLevel(), kBadLastEnumValue);
108 117
109 // Registers notes to make it easier to interpret warnings. 118 // Registers notes to make it easier to interpret warnings.
110 diag_note_inheritance_ = diagnostic().getCustomDiagID( 119 diag_note_inheritance_ = diagnostic().getCustomDiagID(
111 DiagnosticsEngine::Note, kNoteInheritance); 120 DiagnosticsEngine::Note, kNoteInheritance);
112 diag_note_implicit_dtor_ = diagnostic().getCustomDiagID( 121 diag_note_implicit_dtor_ = diagnostic().getCustomDiagID(
113 DiagnosticsEngine::Note, kNoteImplicitDtor); 122 DiagnosticsEngine::Note, kNoteImplicitDtor);
114 diag_note_public_dtor_ = diagnostic().getCustomDiagID( 123 diag_note_public_dtor_ = diagnostic().getCustomDiagID(
115 DiagnosticsEngine::Note, kNotePublicDtor); 124 DiagnosticsEngine::Note, kNotePublicDtor);
116 diag_note_protected_non_virtual_dtor_ = diagnostic().getCustomDiagID( 125 diag_note_protected_non_virtual_dtor_ = diagnostic().getCustomDiagID(
117 DiagnosticsEngine::Note, kNoteProtectedNonVirtualDtor); 126 DiagnosticsEngine::Note, kNoteProtectedNonVirtualDtor);
(...skipping 16 matching lines...) Expand all
134 // virtual and OVERRIDE. 143 // virtual and OVERRIDE.
135 CheckVirtualMethods(record_location, record, warn_on_inline_bodies); 144 CheckVirtualMethods(record_location, record, warn_on_inline_bodies);
136 } 145 }
137 146
138 CheckRefCountedDtors(record_location, record); 147 CheckRefCountedDtors(record_location, record);
139 148
140 if (options_.check_weak_ptr_factory_order) 149 if (options_.check_weak_ptr_factory_order)
141 CheckWeakPtrFactoryMembers(record_location, record); 150 CheckWeakPtrFactoryMembers(record_location, record);
142 } 151 }
143 152
153 virtual void CheckChromeEnum(SourceLocation enum_location,
154 EnumDecl* enum_decl) {
155 if (!options_.check_enum_last_value)
156 return;
157
158 bool got_one = false;
159 bool is_signed = false;
160 llvm::APSInt max_so_far;
161 EnumDecl::enumerator_iterator iter;
162 for (iter = enum_decl->enumerator_begin();
163 iter != enum_decl->enumerator_end(); ++iter) {
164 llvm::APSInt current_value = iter->getInitVal();
165 if (!got_one) {
166 max_so_far = current_value;
167 is_signed = current_value.isSigned();
168 got_one = true;
169 } else {
170 if (is_signed != current_value.isSigned()) {
171 // This only happens in some cases when compiling C (not C++) files,
172 // so it is OK to bail out here.
173 return;
174 }
175 if (current_value > max_so_far)
176 max_so_far = current_value;
177 }
178 }
179 for (iter = enum_decl->enumerator_begin();
180 iter != enum_decl->enumerator_end(); ++iter) {
181 std::string name = iter->getNameAsString();
182 if (((name.size() > 4 &&
183 name.compare(name.size() - 4, 4, "Last") == 0) ||
184 (name.size() > 5 &&
185 name.compare(name.size() - 5, 5, "_LAST") == 0)) &&
186 iter->getInitVal() < max_so_far) {
187 diagnostic().Report(iter->getLocation(), diag_bad_enum_last_value_);
188 }
189 }
190 }
191
144 private: 192 private:
145 // The type of problematic ref-counting pattern that was encountered. 193 // The type of problematic ref-counting pattern that was encountered.
146 enum RefcountIssue { 194 enum RefcountIssue {
147 None, 195 None,
148 ImplicitDestructor, 196 ImplicitDestructor,
149 PublicDestructor 197 PublicDestructor
150 }; 198 };
151 199
152 FindBadConstructsOptions options_; 200 FindBadConstructsOptions options_;
153 201
154 unsigned diag_method_requires_override_; 202 unsigned diag_method_requires_override_;
155 unsigned diag_method_requires_virtual_; 203 unsigned diag_method_requires_virtual_;
156 unsigned diag_no_explicit_dtor_; 204 unsigned diag_no_explicit_dtor_;
157 unsigned diag_public_dtor_; 205 unsigned diag_public_dtor_;
158 unsigned diag_protected_non_virtual_dtor_; 206 unsigned diag_protected_non_virtual_dtor_;
159 unsigned diag_weak_ptr_factory_order_; 207 unsigned diag_weak_ptr_factory_order_;
208 unsigned diag_bad_enum_last_value_;
160 unsigned diag_note_inheritance_; 209 unsigned diag_note_inheritance_;
161 unsigned diag_note_implicit_dtor_; 210 unsigned diag_note_implicit_dtor_;
162 unsigned diag_note_public_dtor_; 211 unsigned diag_note_public_dtor_;
163 unsigned diag_note_protected_non_virtual_dtor_; 212 unsigned diag_note_protected_non_virtual_dtor_;
164 213
165 // Prints errors if the constructor/destructor weight is too heavy. 214 // Prints errors if the constructor/destructor weight is too heavy.
166 void CheckCtorDtorWeight(SourceLocation record_location, 215 void CheckCtorDtorWeight(SourceLocation record_location,
167 CXXRecordDecl* record) { 216 CXXRecordDecl* record) {
168 // We don't handle anonymous structs. If this record doesn't have a 217 // We don't handle anonymous structs. If this record doesn't have a
169 // name, it's of the form: 218 // name, it's of the form:
(...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after
700 for (size_t i = 0; i < args.size() && parsed; ++i) { 749 for (size_t i = 0; i < args.size() && parsed; ++i) {
701 if (args[i] == "skip-virtuals-in-implementations") { 750 if (args[i] == "skip-virtuals-in-implementations") {
702 // TODO(rsleevi): Remove this once http://crbug.com/115047 is fixed. 751 // TODO(rsleevi): Remove this once http://crbug.com/115047 is fixed.
703 options_.check_virtuals_in_implementations = false; 752 options_.check_virtuals_in_implementations = false;
704 } else if (args[i] == "check-base-classes") { 753 } else if (args[i] == "check-base-classes") {
705 // TODO(rsleevi): Remove this once http://crbug.com/123295 is fixed. 754 // TODO(rsleevi): Remove this once http://crbug.com/123295 is fixed.
706 options_.check_base_classes = true; 755 options_.check_base_classes = true;
707 } else if (args[i] == "check-weak-ptr-factory-order") { 756 } else if (args[i] == "check-weak-ptr-factory-order") {
708 // TODO(dmichael): Remove this once http://crbug.com/303818 is fixed. 757 // TODO(dmichael): Remove this once http://crbug.com/303818 is fixed.
709 options_.check_weak_ptr_factory_order = true; 758 options_.check_weak_ptr_factory_order = true;
759 } else if (args[i] == "skip-enum-last-value") {
Nico 2014/03/27 22:53:46 Usually, new warnings default to off, and are turn
760 // TODO(tsepez): Remove this once http://crbug.com/356815 and
761 // http://crbug.com/356816 are fixed.
762 options_.check_enum_last_value = false;
710 } else { 763 } else {
711 parsed = false; 764 parsed = false;
712 llvm::errs() << "Unknown clang plugin argument: " << args[i] << "\n"; 765 llvm::errs() << "Unknown clang plugin argument: " << args[i] << "\n";
713 } 766 }
714 } 767 }
715 768
716 return parsed; 769 return parsed;
717 } 770 }
718 771
719 private: 772 private:
720 FindBadConstructsOptions options_; 773 FindBadConstructsOptions options_;
721 }; 774 };
722 775
723 } // namespace 776 } // namespace
724 777
725 static FrontendPluginRegistry::Add<FindBadConstructsAction> 778 static FrontendPluginRegistry::Add<FindBadConstructsAction>
726 X("find-bad-constructs", "Finds bad C++ constructs"); 779 X("find-bad-constructs", "Finds bad C++ constructs");
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698