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

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

Issue 1108173002: Roll //build, //native_client, and a few more targets of opportunity. Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Test fix Created 5 years, 8 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 | « tools/clang/plugins/ChromeClassTester.cpp ('k') | tools/clang/plugins/tests/overridden_methods.txt » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/clang/plugins/FindBadConstructsConsumer.cpp
diff --git a/tools/clang/plugins/FindBadConstructsConsumer.cpp b/tools/clang/plugins/FindBadConstructsConsumer.cpp
index 770e2551d6e7c92f12032f850251ba5b8af738d1..20919a41afd7afb98a90211160b36d23cccacac7 100644
--- a/tools/clang/plugins/FindBadConstructsConsumer.cpp
+++ b/tools/clang/plugins/FindBadConstructsConsumer.cpp
@@ -70,14 +70,15 @@ bool IsGtestTestFixture(const CXXRecordDecl* decl) {
return decl->getQualifiedNameAsString() == "testing::Test";
}
+// Generates a fixit hint to remove the 'virtual' keyword.
+// Unfortunately, there doesn't seem to be a good way to determine the source
+// location of the 'virtual' keyword. It's available in Declarator, but that
+// isn't accessible from the AST. So instead, make an educated guess that the
+// first token is probably the virtual keyword. Strictly speaking, this doesn't
+// have to be true, but it probably will be.
+// TODO(dcheng): Add a warning to force virtual to always appear first ;-)
FixItHint FixItRemovalForVirtual(const SourceManager& manager,
const CXXMethodDecl* method) {
- // Unfortunately, there doesn't seem to be a good way to determine the
- // location of the 'virtual' keyword. It's available in Declarator, but that
- // isn't accessible from the AST. So instead, make an educated guess that the
- // first token is probably the virtual keyword. Strictly speaking, this
- // doesn't have to be true, but it probably will be.
- // TODO(dcheng): Add a warning to force virtual to always appear first ;-)
SourceRange range(method->getLocStart());
// Get the spelling loc just in case it was expanded from a macro.
SourceRange spelling_range(manager.getSpellingLoc(range.getBegin()));
@@ -413,32 +414,68 @@ void FindBadConstructsConsumer::CheckVirtualSpecifiers(
// Complain if a method is annotated virtual && (override || final).
if (has_virtual && (override_attr || final_attr)) {
- diagnostic().Report(method->getLocStart(),
- diag_redundant_virtual_specifier_)
- << "'virtual'"
- << (override_attr ? static_cast<Attr*>(override_attr) : final_attr)
- << FixItRemovalForVirtual(manager, method);
+ // ... but only if virtual does not originate in a macro from a banned file.
+ // Note this is just an educated guess: the assumption here is that any
+ // macro for declaring methods will probably be at the start of the method's
+ // source range.
+ if (!InBannedDirectory(manager.getSpellingLoc(method->getLocStart()))) {
+ diagnostic().Report(method->getLocStart(),
+ diag_redundant_virtual_specifier_)
+ << "'virtual'"
+ << (override_attr ? static_cast<Attr*>(override_attr) : final_attr)
+ << FixItRemovalForVirtual(manager, method);
+ }
}
// Complain if a method is an override and is not annotated with override or
// final.
if (is_override && !override_attr && !final_attr) {
- SourceRange type_info_range =
- method->getTypeSourceInfo()->getTypeLoc().getSourceRange();
- FullSourceLoc loc(type_info_range.getBegin(), manager);
-
- // Build the FixIt insertion point after the end of the method definition,
- // including any const-qualifiers and attributes, and before the opening
- // of the l-curly-brace (if inline) or the semi-color (if a declaration).
- SourceLocation spelling_end =
- manager.getSpellingLoc(type_info_range.getEnd());
- if (spelling_end.isValid()) {
- SourceLocation token_end =
- Lexer::getLocForEndOfToken(spelling_end, 0, manager, LangOptions());
- diagnostic().Report(token_end, diag_method_requires_override_)
- << FixItHint::CreateInsertion(token_end, " override");
+ SourceRange range = method->getSourceRange();
+ SourceLocation loc;
+ if (method->hasInlineBody()) {
+ loc = method->getBody()->getSourceRange().getBegin();
+ } else {
+ // TODO(dcheng): We should probably use ASTContext's LangOptions here.
+ LangOptions lang_options;
+ loc = Lexer::getLocForEndOfToken(
+ manager.getSpellingLoc(range.getEnd()), 0,
+ manager, lang_options);
+ // The original code used the ending source loc of TypeSourceInfo's
+ // TypeLoc. Unfortunately, this breaks down in the presence of attributes.
+ // Attributes often appear at the end of a TypeLoc, e.g.
+ // virtual ULONG __stdcall AddRef()
+ // has a TypeSourceInfo that looks something like:
+ // ULONG AddRef() __attribute(stdcall)
+ // so a fix-it insertion would be generated to insert 'override' after
+ // __stdcall in the code as written.
+ // While using the spelling loc of the CXXMethodDecl fixes attribute
+ // handling, it breaks handling of "= 0" and similar constructs.. To work
+ // around this, scan backwards in the source text for a '=' or ')' token
+ // and adjust the location as needed...
+ for (SourceLocation l = loc.getLocWithOffset(-1);
+ l != manager.getLocForStartOfFile(manager.getFileID(loc));
+ l = l.getLocWithOffset(-1)) {
+ l = Lexer::GetBeginningOfToken(l, manager, lang_options);
+ Token token;
+ // getRawToken() returns *true* on failure. In that case, just give up
+ // and don't bother generating a possibly incorrect fix-it.
+ if (Lexer::getRawToken(l, token, manager, lang_options, true)) {
+ loc = SourceLocation();
+ break;
+ }
+ if (token.is(tok::r_paren)) {
+ break;
+ } else if (token.is(tok::equal)) {
+ loc = l;
+ break;
+ }
+ }
+ }
+ if (loc.isValid()) {
+ diagnostic().Report(loc, diag_method_requires_override_)
+ << FixItHint::CreateInsertion(loc, " override");
} else {
- diagnostic().Report(loc, diag_method_requires_override_);
+ diagnostic().Report(range.getBegin(), diag_method_requires_override_);
}
}
@@ -559,8 +596,14 @@ FindBadConstructsConsumer::CheckRecordForRefcountIssue(
// Adds either a warning or error, based on the current handling of
// -Werror.
DiagnosticsEngine::Level FindBadConstructsConsumer::getErrorLevel() {
+#if defined(LLVM_ON_WIN32)
+ // TODO(dcheng): Re-enable -Werror for these diagnostics on Windows once all
+ // the pre-existing warnings are cleaned up. https://crbug.com/467287
+ return DiagnosticsEngine::Warning;
+#else
return diagnostic().getWarningsAsErrors() ? DiagnosticsEngine::Error
: DiagnosticsEngine::Warning;
+#endif
}
// Returns true if |base| specifies one of the Chromium reference counted
« no previous file with comments | « tools/clang/plugins/ChromeClassTester.cpp ('k') | tools/clang/plugins/tests/overridden_methods.txt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698