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

Unified Diff: tools/clang/plugins/FindBadConstructs.cpp

Issue 26303002: Make Clang plugin check WeakPtrFactory member order (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Clean up for review Created 7 years, 2 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | tools/clang/plugins/tests/weak_ptr_factory.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/clang/plugins/FindBadConstructs.cpp
diff --git a/tools/clang/plugins/FindBadConstructs.cpp b/tools/clang/plugins/FindBadConstructs.cpp
index 9697c5f21104825a31c066099ca7ccea13d2ae9d..bdc497f64de99a0cad815473c6998195a88c52c0 100644
--- a/tools/clang/plugins/FindBadConstructs.cpp
+++ b/tools/clang/plugins/FindBadConstructs.cpp
@@ -12,6 +12,8 @@
// - Virtual methods with nonempty implementations in their headers.
// - Classes that derive from base::RefCounted / base::RefCountedThreadSafe
// should have protected or private destructors.
+// - WeakPtrFactory members that refer to their outer class should be the last
+// member.
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/AST.h"
@@ -43,6 +45,9 @@ const char kPublicDtor[] =
const char kProtectedNonVirtualDtor[] =
"[chromium-style] Classes that are ref-counted and have non-private "
"destructors should declare their destructor virtual.";
+const char kWeakPtrFactoryOrder[] =
+ "[chromium-style] WeakPtrFactory members which refer to their outer class "
+ "must be the last member in the outer class definition.";
const char kNoteInheritance[] =
"[chromium-style] %0 inherits from %1 here";
const char kNoteImplicitDtor[] =
@@ -70,16 +75,25 @@ const Type* UnwrapType(const Type* type) {
return type;
}
+struct FindBadConstructsOptions {
+ FindBadConstructsOptions() : check_base_classes(false),
+ check_virtuals_in_implementations(true),
+ check_url_directory(false),
+ check_weak_ptr_factory_order(false) {
+ }
+ bool check_base_classes;
+ bool check_virtuals_in_implementations;
+ bool check_url_directory;
+ bool check_weak_ptr_factory_order;
+};
+
// Searches for constructs that we know we don't want in the Chromium code base.
class FindBadConstructsConsumer : public ChromeClassTester {
public:
FindBadConstructsConsumer(CompilerInstance& instance,
- bool check_base_classes,
- bool check_virtuals_in_implementations,
- bool check_url_directory)
- : ChromeClassTester(instance, check_url_directory),
- check_base_classes_(check_base_classes),
- check_virtuals_in_implementations_(check_virtuals_in_implementations) {
+ const FindBadConstructsOptions& options)
+ : ChromeClassTester(instance, options.check_url_directory),
+ options_(options) {
// Register warning/error messages.
diag_method_requires_override_ = diagnostic().getCustomDiagID(
getErrorLevel(), kMethodRequiresOverride);
@@ -91,6 +105,8 @@ class FindBadConstructsConsumer : public ChromeClassTester {
getErrorLevel(), kPublicDtor);
diag_protected_non_virtual_dtor_ = diagnostic().getCustomDiagID(
getErrorLevel(), kProtectedNonVirtualDtor);
+ diag_weak_ptr_factory_order_ = diagnostic().getCustomDiagID(
+ getErrorLevel(), kWeakPtrFactoryOrder);
// Registers notes to make it easier to interpret warnings.
diag_note_inheritance_ = diagnostic().getCustomDiagID(
@@ -113,7 +129,7 @@ class FindBadConstructsConsumer : public ChromeClassTester {
CheckCtorDtorWeight(record_location, record);
}
- if (!implementation_file || check_virtuals_in_implementations_) {
+ if (!implementation_file || options_.check_virtuals_in_implementations) {
bool warn_on_inline_bodies = !implementation_file;
// Check that all virtual methods are marked accordingly with both
@@ -122,6 +138,9 @@ class FindBadConstructsConsumer : public ChromeClassTester {
}
CheckRefCountedDtors(record_location, record);
+
+ if (options_.check_weak_ptr_factory_order)
+ CheckWeakPtrFactoryMembers(record_location, record);
}
private:
@@ -132,14 +151,14 @@ class FindBadConstructsConsumer : public ChromeClassTester {
PublicDestructor
};
- bool check_base_classes_;
- bool check_virtuals_in_implementations_;
+ FindBadConstructsOptions options_;
unsigned diag_method_requires_override_;
unsigned diag_method_requires_virtual_;
unsigned diag_no_explicit_dtor_;
unsigned diag_public_dtor_;
unsigned diag_protected_non_virtual_dtor_;
+ unsigned diag_weak_ptr_factory_order_;
unsigned diag_note_inheritance_;
unsigned diag_note_implicit_dtor_;
unsigned diag_note_public_dtor_;
@@ -514,6 +533,8 @@ class FindBadConstructsConsumer : public ChromeClassTester {
assert(false && "Do not call DiagnosticForIssue with issue None");
return 0;
}
+ assert(false);
+ return 0;
}
// Check |record| to determine if it has any problematic refcounting
@@ -580,7 +601,7 @@ class FindBadConstructsConsumer : public ChromeClassTester {
// new RefCountedInterface);
// // Calls SomeInterface::~SomeInterface(), which is unsafe.
// delete static_cast<SomeInterface*>(some_class.get());
- if (!check_base_classes_)
+ if (!options_.check_base_classes)
return;
// Find all public destructors. This will record the class hierarchy
@@ -614,23 +635,64 @@ class FindBadConstructsConsumer : public ChromeClassTester {
}
}
}
+
+ // Check for any problems with WeakPtrFactory class members. This currently
+ // only checks that any WeakPtrFactory<T> member of T appears as the last
+ // data member in T. We could consider checking for bad uses of
+ // WeakPtrFactory to refer to other data members, but that would require
+ // looking at the initializer list in constructors to see what the factory
+ // points to.
+ // Note, if we later add other unrelated checks of data members, we should
+ // consider collapsing them in to one loop to avoid iterating over the data
+ // members more than once.
+ void CheckWeakPtrFactoryMembers(SourceLocation record_location,
+ CXXRecordDecl* record) {
+ // Skip anonymous structs.
+ if (record->getIdentifier() == NULL)
+ return;
+
+ // Iterate through members of the class.
+ RecordDecl::field_iterator iter(record->field_begin()),
+ the_end(record->field_end());
+ SourceLocation weak_ptr_factory_location; // Invalid initially.
+ for (; iter != the_end; ++iter) {
+ // If we enter the loop but have already seen a matching WeakPtrFactory,
+ // it means there is at least one member after the factory.
+ if (weak_ptr_factory_location.isValid()) {
+ diagnostic().Report(weak_ptr_factory_location,
+ diag_weak_ptr_factory_order_);
+ }
+ const TemplateSpecializationType* template_spec_type =
+ iter->getType().getTypePtr()->getAs<TemplateSpecializationType>();
+ if (template_spec_type) {
+ const TemplateDecl* template_decl =
+ template_spec_type->getTemplateName().getAsTemplateDecl();
+ if (template_decl && template_spec_type->getNumArgs() >= 1) {
+ if (template_decl->getNameAsString().compare("WeakPtrFactory") == 0 &&
+ GetNamespace(template_decl) == "base") {
+ const TemplateArgument& arg = template_spec_type->getArg(0);
+ if (arg.getAsType().getTypePtr()->getAsCXXRecordDecl() ==
+ record->getTypeForDecl()->getAsCXXRecordDecl()) {
+ weak_ptr_factory_location = iter->getLocation();
+ }
+ }
+ }
+ }
+ }
+ }
};
+
class FindBadConstructsAction : public PluginASTAction {
public:
- FindBadConstructsAction()
- : check_base_classes_(false),
- check_virtuals_in_implementations_(true),
- check_url_directory_(false) {
+ FindBadConstructsAction() {
}
protected:
// Overridden from PluginASTAction:
virtual ASTConsumer* CreateASTConsumer(CompilerInstance& instance,
llvm::StringRef ref) {
- return new FindBadConstructsConsumer(
- instance, check_base_classes_, check_virtuals_in_implementations_,
- check_url_directory_);
+ return new FindBadConstructsConsumer(instance, options_);
}
virtual bool ParseArgs(const CompilerInstance& instance,
@@ -640,13 +702,16 @@ class FindBadConstructsAction : public PluginASTAction {
for (size_t i = 0; i < args.size() && parsed; ++i) {
if (args[i] == "skip-virtuals-in-implementations") {
// TODO(rsleevi): Remove this once http://crbug.com/115047 is fixed.
- check_virtuals_in_implementations_ = false;
+ options_.check_virtuals_in_implementations = false;
} else if (args[i] == "check-base-classes") {
// TODO(rsleevi): Remove this once http://crbug.com/123295 is fixed.
- check_base_classes_ = true;
+ options_.check_base_classes = true;
} else if (args[i] == "check-url-directory") {
// TODO(tfarina): Remove this once http://crbug.com/229660 is fixed.
- check_url_directory_ = true;
+ options_.check_url_directory = true;
+ } else if (args[i] == "check-weak-ptr-factory-order") {
+ // TODO(dmichael): Remove this once http://crbug.com/303818 is fixed.
+ options_.check_weak_ptr_factory_order = true;
} else {
parsed = false;
llvm::errs() << "Unknown clang plugin argument: " << args[i] << "\n";
@@ -657,9 +722,7 @@ class FindBadConstructsAction : public PluginASTAction {
}
private:
- bool check_base_classes_;
- bool check_virtuals_in_implementations_;
- bool check_url_directory_;
+ FindBadConstructsOptions options_;
};
} // namespace
« no previous file with comments | « no previous file | tools/clang/plugins/tests/weak_ptr_factory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698