Index: tools/clang/plugins/FindBadConstructs.cpp |
diff --git a/tools/clang/plugins/FindBadConstructs.cpp b/tools/clang/plugins/FindBadConstructs.cpp |
index 193fc8458ae0668cf4bec48ea6e0a655bb3d7ddd..fee2aaddae1d97d2f24b1217f0703c49a6b1d679 100644 |
--- a/tools/clang/plugins/FindBadConstructs.cpp |
+++ b/tools/clang/plugins/FindBadConstructs.cpp |
@@ -49,9 +49,11 @@ const Type* UnwrapType(const Type* type) { |
class FindBadConstructsConsumer : public ChromeClassTester { |
public: |
FindBadConstructsConsumer(CompilerInstance& instance, |
- bool check_refcounted_dtors) |
+ bool check_refcounted_dtors, |
+ bool check_virtuals_in_implementations) |
: ChromeClassTester(instance), |
- check_refcounted_dtors_(check_refcounted_dtors) { |
+ check_refcounted_dtors_(check_refcounted_dtors), |
+ check_virtuals_in_implementations_(check_virtuals_in_implementations) { |
} |
virtual void CheckChromeClass(SourceLocation record_location, |
@@ -62,10 +64,14 @@ class FindBadConstructsConsumer : public ChromeClassTester { |
// Only check for "heavy" constructors/destructors in header files; |
// within implementation files, there is no performance cost. |
CheckCtorDtorWeight(record_location, record); |
+ } |
+ |
+ if (!implementation_file || check_virtuals_in_implementations_) { |
+ bool warn_on_inline_bodies = !implementation_file; |
// Check that all virtual methods are marked accordingly with both |
// virtual and OVERRIDE. |
- CheckVirtualMethods(record_location, record); |
+ CheckVirtualMethods(record_location, record, warn_on_inline_bodies); |
} |
if (check_refcounted_dtors_) |
@@ -74,6 +80,7 @@ class FindBadConstructsConsumer : public ChromeClassTester { |
private: |
bool check_refcounted_dtors_; |
+ bool check_virtuals_in_implementations_; |
// Returns true if |base| specifies one of the Chromium reference counted |
// classes (base::RefCounted / base::RefCountedThreadSafe). |user_data| is |
@@ -225,7 +232,8 @@ class FindBadConstructsConsumer : public ChromeClassTester { |
} |
} |
- void CheckVirtualMethod(const CXXMethodDecl* method) { |
+ void CheckVirtualMethod(const CXXMethodDecl* method, |
+ bool warn_on_inline_bodies) { |
if (!method->isVirtual()) |
return; |
@@ -236,8 +244,10 @@ class FindBadConstructsConsumer : public ChromeClassTester { |
emitWarning(loc, "Overriding method must have \"virtual\" keyword."); |
} |
- // Virtual methods should not have inline definitions beyond "{}". |
- if (method->hasBody() && method->hasInlineBody()) { |
+ // Virtual methods should not have inline definitions beyond "{}". This |
+ // only matters for header files. |
+ if (warn_on_inline_bodies && method->hasBody() && |
+ method->hasInlineBody()) { |
if (CompoundStmt* cs = dyn_cast<CompoundStmt>(method->getBody())) { |
if (cs->size()) { |
emitWarning( |
@@ -281,15 +291,15 @@ class FindBadConstructsConsumer : public ChromeClassTester { |
emitWarning(loc, "Overriding method must be marked with OVERRIDE."); |
} |
- // Makes sure there is a "virtual" keyword on virtual methods and that there |
- // are no inline function bodies on them (but "{}" is allowed). |
+ // Makes sure there is a "virtual" keyword on virtual methods. |
// |
// Gmock objects trigger these for each MOCK_BLAH() macro used. So we have a |
// trick to get around that. If a class has member variables whose types are |
// in the "testing" namespace (which is how gmock works behind the scenes), |
// there's a really high chance we won't care about these errors |
void CheckVirtualMethods(SourceLocation record_location, |
- CXXRecordDecl* record) { |
+ CXXRecordDecl* record, |
+ bool warn_on_inline_bodies) { |
for (CXXRecordDecl::field_iterator it = record->field_begin(); |
it != record->field_end(); ++it) { |
CXXRecordDecl* record_type = |
@@ -310,7 +320,7 @@ class FindBadConstructsConsumer : public ChromeClassTester { |
!record->hasUserDeclaredDestructor()) { |
// Ignore non-user-declared destructors. |
} else { |
- CheckVirtualMethod(*it); |
+ CheckVirtualMethod(*it, warn_on_inline_bodies); |
CheckOverriddenMethod(*it); |
} |
} |
@@ -376,11 +386,15 @@ class FindBadConstructsConsumer : public ChromeClassTester { |
class FindBadConstructsAction : public PluginASTAction { |
public: |
- FindBadConstructsAction() : check_refcounted_dtors_(true) {} |
+ FindBadConstructsAction() |
+ : check_refcounted_dtors_(true), |
+ check_virtuals_in_implementations_(true) { |
+ } |
protected: |
ASTConsumer* CreateASTConsumer(CompilerInstance &CI, llvm::StringRef ref) { |
- return new FindBadConstructsConsumer(CI, check_refcounted_dtors_); |
+ return new FindBadConstructsConsumer( |
+ CI, check_refcounted_dtors_, check_virtuals_in_implementations_); |
} |
bool ParseArgs(const CompilerInstance &CI, |
@@ -390,6 +404,8 @@ class FindBadConstructsAction : public PluginASTAction { |
for (size_t i = 0; i < args.size() && parsed; ++i) { |
if (args[i] == "skip-refcounted-dtors") { |
check_refcounted_dtors_ = false; |
+ } else if (args[i] == "skip-virtuals-in-implementations") { |
+ check_virtuals_in_implementations_ = false; |
} else { |
parsed = false; |
llvm::errs() << "Unknown argument: " << args[i] << "\n"; |
@@ -401,6 +417,7 @@ class FindBadConstructsAction : public PluginASTAction { |
private: |
bool check_refcounted_dtors_; |
+ bool check_virtuals_in_implementations_; |
}; |
} // namespace |