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

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

Issue 952893003: Update from https://crrev.com/317530 (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Fix gn for nacl Created 5 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
« no previous file with comments | « tools/clang/plugins/FindBadConstructsAction.cpp ('k') | tools/clang/plugins/Options.h » ('j') | 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 #include "FindBadConstructsConsumer.h" 5 #include "FindBadConstructsConsumer.h"
6 6
7 #include "clang/Frontend/CompilerInstance.h" 7 #include "clang/Frontend/CompilerInstance.h"
8 #include "clang/AST/Attr.h" 8 #include "clang/AST/Attr.h"
9 #include "clang/Lex/Lexer.h" 9 #include "clang/Lex/Lexer.h"
10 #include "llvm/Support/raw_ostream.h" 10 #include "llvm/Support/raw_ostream.h"
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 if (!record->hasUserDeclaredConstructor()) { 276 if (!record->hasUserDeclaredConstructor()) {
277 emitWarning(record_location, 277 emitWarning(record_location,
278 "Complex class/struct needs an explicit out-of-line " 278 "Complex class/struct needs an explicit out-of-line "
279 "constructor."); 279 "constructor.");
280 } else { 280 } else {
281 // Iterate across all the constructors in this file and yell if we 281 // Iterate across all the constructors in this file and yell if we
282 // find one that tries to be inline. 282 // find one that tries to be inline.
283 for (CXXRecordDecl::ctor_iterator it = record->ctor_begin(); 283 for (CXXRecordDecl::ctor_iterator it = record->ctor_begin();
284 it != record->ctor_end(); 284 it != record->ctor_end();
285 ++it) { 285 ++it) {
286 // The current check is buggy. An implicit copy constructor does not
287 // have an inline body, so this check never fires for classes with a
288 // user-declared out-of-line constructor.
286 if (it->hasInlineBody()) { 289 if (it->hasInlineBody()) {
287 if (it->isCopyConstructor() && 290 if (it->isCopyConstructor() &&
288 !record->hasUserDeclaredCopyConstructor()) { 291 !record->hasUserDeclaredCopyConstructor()) {
289 emitWarning(record_location, 292 emitWarning(record_location,
290 "Complex class/struct needs an explicit out-of-line " 293 "Complex class/struct needs an explicit out-of-line "
291 "copy constructor."); 294 "copy constructor.");
292 } else { 295 } else {
293 emitWarning(it->getInnerLocStart(), 296 emitWarning(it->getInnerLocStart(),
294 "Complex constructor has an inlined body."); 297 "Complex constructor has an inlined body.");
295 } 298 }
299 } else if (it->isInlined() && (!it->isCopyOrMoveConstructor() ||
300 it->isExplicitlyDefaulted())) {
301 // isInlined() is a more reliable check than hasInlineBody(), but
302 // unfortunately, it results in warnings for implicit copy/move
303 // constructors in the previously mentioned situation. To preserve
304 // compatibility with existing Chromium code, only warn if it's an
305 // explicitly defaulted copy or move constructor.
306 emitWarning(it->getInnerLocStart(),
307 "Complex constructor has an inlined body.");
296 } 308 }
297 } 309 }
298 } 310 }
299 } 311 }
300 312
301 // The destructor side is equivalent except that we don't check for 313 // The destructor side is equivalent except that we don't check for
302 // trivial members; 20 ints don't need a destructor. 314 // trivial members; 20 ints don't need a destructor.
303 if (dtor_score >= 10 && !record->hasTrivialDestructor()) { 315 if (dtor_score >= 10 && !record->hasTrivialDestructor()) {
304 if (!record->hasUserDeclaredDestructor()) { 316 if (!record->hasUserDeclaredDestructor()) {
305 emitWarning(record_location, 317 emitWarning(record_location,
306 "Complex class/struct needs an explicit out-of-line " 318 "Complex class/struct needs an explicit out-of-line "
307 "destructor."); 319 "destructor.");
308 } else if (CXXDestructorDecl* dtor = record->getDestructor()) { 320 } else if (CXXDestructorDecl* dtor = record->getDestructor()) {
309 if (dtor->hasInlineBody()) { 321 if (dtor->isInlined()) {
310 emitWarning(dtor->getInnerLocStart(), 322 emitWarning(dtor->getInnerLocStart(),
311 "Complex destructor has an inline body."); 323 "Complex destructor has an inline body.");
312 } 324 }
313 } 325 }
314 } 326 }
315 } 327 }
316 328
317 bool FindBadConstructsConsumer::InTestingNamespace(const Decl* record) { 329 bool FindBadConstructsConsumer::InTestingNamespace(const Decl* record) {
318 return GetNamespace(record).find("testing") != std::string::npos; 330 return GetNamespace(record).find("testing") != std::string::npos;
319 } 331 }
320 332
321 bool FindBadConstructsConsumer::IsMethodInBannedOrTestingNamespace( 333 bool FindBadConstructsConsumer::IsMethodInBannedOrTestingNamespace(
322 const CXXMethodDecl* method) { 334 const CXXMethodDecl* method) {
323 if (InBannedNamespace(method)) 335 if (InBannedNamespace(method))
324 return true; 336 return true;
325 for (CXXMethodDecl::method_iterator i = method->begin_overridden_methods(); 337 for (CXXMethodDecl::method_iterator i = method->begin_overridden_methods();
326 i != method->end_overridden_methods(); 338 i != method->end_overridden_methods();
327 ++i) { 339 ++i) {
328 const CXXMethodDecl* overridden = *i; 340 const CXXMethodDecl* overridden = *i;
329 if (IsMethodInBannedOrTestingNamespace(overridden) || 341 if (IsMethodInBannedOrTestingNamespace(overridden) ||
330 // Provide an exception for ::testing::Test. gtest itself uses some 342 // Provide an exception for ::testing::Test. gtest itself uses some
331 // magic to try to make sure SetUp()/TearDown() aren't capitalized 343 // magic to try to make sure SetUp()/TearDown() aren't capitalized
332 // incorrectly, but having the plugin enforce override is also nice. 344 // incorrectly, but having the plugin enforce override is also nice.
333 (InTestingNamespace(overridden) && 345 (InTestingNamespace(overridden) &&
334 (!options_.strict_virtual_specifiers || 346 !IsGtestTestFixture(overridden->getParent()))) {
335 !IsGtestTestFixture(overridden->getParent())))) {
336 return true; 347 return true;
337 } 348 }
338 } 349 }
339 350
340 return false; 351 return false;
341 } 352 }
342 353
343 // Checks that virtual methods are correctly annotated, and have no body in a 354 // Checks that virtual methods are correctly annotated, and have no body in a
344 // header file. 355 // header file.
345 void FindBadConstructsConsumer::CheckVirtualMethods( 356 void FindBadConstructsConsumer::CheckVirtualMethods(
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 // virtual method overrides a method from a base class, only the override 397 // virtual method overrides a method from a base class, only the override
387 // specifier should be used. If the method should not be overridden by derived 398 // specifier should be used. If the method should not be overridden by derived
388 // classes, only the final specifier should be used. 399 // classes, only the final specifier should be used.
389 void FindBadConstructsConsumer::CheckVirtualSpecifiers( 400 void FindBadConstructsConsumer::CheckVirtualSpecifiers(
390 const CXXMethodDecl* method) { 401 const CXXMethodDecl* method) {
391 bool is_override = method->size_overridden_methods() > 0; 402 bool is_override = method->size_overridden_methods() > 0;
392 bool has_virtual = method->isVirtualAsWritten(); 403 bool has_virtual = method->isVirtualAsWritten();
393 OverrideAttr* override_attr = method->getAttr<OverrideAttr>(); 404 OverrideAttr* override_attr = method->getAttr<OverrideAttr>();
394 FinalAttr* final_attr = method->getAttr<FinalAttr>(); 405 FinalAttr* final_attr = method->getAttr<FinalAttr>();
395 406
396 if (method->isPure() && !options_.strict_virtual_specifiers)
397 return;
398
399 if (IsMethodInBannedOrTestingNamespace(method)) 407 if (IsMethodInBannedOrTestingNamespace(method))
400 return; 408 return;
401 409
402 if (isa<CXXDestructorDecl>(method) && !options_.strict_virtual_specifiers)
403 return;
404
405 SourceManager& manager = instance().getSourceManager(); 410 SourceManager& manager = instance().getSourceManager();
406 411
407 // Complain if a method is annotated virtual && (override || final). 412 // Complain if a method is annotated virtual && (override || final).
408 if (has_virtual && (override_attr || final_attr) && 413 if (has_virtual && (override_attr || final_attr)) {
409 options_.strict_virtual_specifiers) {
410 diagnostic().Report(method->getLocStart(), 414 diagnostic().Report(method->getLocStart(),
411 diag_redundant_virtual_specifier_) 415 diag_redundant_virtual_specifier_)
412 << "'virtual'" 416 << "'virtual'"
413 << (override_attr ? static_cast<Attr*>(override_attr) : final_attr) 417 << (override_attr ? static_cast<Attr*>(override_attr) : final_attr)
414 << FixItRemovalForVirtual(manager, method); 418 << FixItRemovalForVirtual(manager, method);
415 } 419 }
416 420
417 // Complain if a method is an override and is not annotated with override or 421 // Complain if a method is an override and is not annotated with override or
418 // final. 422 // final.
419 if (is_override && !override_attr && !final_attr) { 423 if (is_override && !override_attr && !final_attr) {
420 SourceRange type_info_range = 424 SourceRange type_info_range =
421 method->getTypeSourceInfo()->getTypeLoc().getSourceRange(); 425 method->getTypeSourceInfo()->getTypeLoc().getSourceRange();
422 FullSourceLoc loc(type_info_range.getBegin(), manager); 426 FullSourceLoc loc(type_info_range.getBegin(), manager);
423 427
424 // Build the FixIt insertion point after the end of the method definition, 428 // Build the FixIt insertion point after the end of the method definition,
425 // including any const-qualifiers and attributes, and before the opening 429 // including any const-qualifiers and attributes, and before the opening
426 // of the l-curly-brace (if inline) or the semi-color (if a declaration). 430 // of the l-curly-brace (if inline) or the semi-color (if a declaration).
427 SourceLocation spelling_end = 431 SourceLocation spelling_end =
428 manager.getSpellingLoc(type_info_range.getEnd()); 432 manager.getSpellingLoc(type_info_range.getEnd());
429 if (spelling_end.isValid()) { 433 if (spelling_end.isValid()) {
430 SourceLocation token_end = 434 SourceLocation token_end =
431 Lexer::getLocForEndOfToken(spelling_end, 0, manager, LangOptions()); 435 Lexer::getLocForEndOfToken(spelling_end, 0, manager, LangOptions());
432 diagnostic().Report(token_end, diag_method_requires_override_) 436 diagnostic().Report(token_end, diag_method_requires_override_)
433 << FixItHint::CreateInsertion(token_end, " override"); 437 << FixItHint::CreateInsertion(token_end, " override");
434 } else { 438 } else {
435 diagnostic().Report(loc, diag_method_requires_override_); 439 diagnostic().Report(loc, diag_method_requires_override_);
436 } 440 }
437 } 441 }
438 442
439 if (final_attr && override_attr && options_.strict_virtual_specifiers) { 443 if (final_attr && override_attr) {
440 diagnostic().Report(override_attr->getLocation(), 444 diagnostic().Report(override_attr->getLocation(),
441 diag_redundant_virtual_specifier_) 445 diag_redundant_virtual_specifier_)
442 << override_attr << final_attr 446 << override_attr << final_attr
443 << FixItHint::CreateRemoval(override_attr->getRange()); 447 << FixItHint::CreateRemoval(override_attr->getRange());
444 } 448 }
445 449
446 if (final_attr && !is_override && options_.strict_virtual_specifiers) { 450 if (final_attr && !is_override) {
447 diagnostic().Report(method->getLocStart(), 451 diagnostic().Report(method->getLocStart(),
448 diag_base_method_virtual_and_final_) 452 diag_base_method_virtual_and_final_)
449 << FixItRemovalForVirtual(manager, method) 453 << FixItRemovalForVirtual(manager, method)
450 << FixItHint::CreateRemoval(final_attr->getRange()); 454 << FixItHint::CreateRemoval(final_attr->getRange());
451 } 455 }
452 } 456 }
453 457
454 void FindBadConstructsConsumer::CheckVirtualBodies( 458 void FindBadConstructsConsumer::CheckVirtualBodies(
455 const CXXMethodDecl* method) { 459 const CXXMethodDecl* method) {
456 // Virtual methods should not have inline definitions beyond "{}". This 460 // Virtual methods should not have inline definitions beyond "{}". This
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after
781 // one of those, it means there is at least one member after a factory. 785 // one of those, it means there is at least one member after a factory.
782 if (weak_ptr_factory_location.isValid() && 786 if (weak_ptr_factory_location.isValid() &&
783 !param_is_weak_ptr_factory_to_self) { 787 !param_is_weak_ptr_factory_to_self) {
784 diagnostic().Report(weak_ptr_factory_location, 788 diagnostic().Report(weak_ptr_factory_location,
785 diag_weak_ptr_factory_order_); 789 diag_weak_ptr_factory_order_);
786 } 790 }
787 } 791 }
788 } 792 }
789 793
790 } // namespace chrome_checker 794 } // namespace chrome_checker
OLDNEW
« no previous file with comments | « tools/clang/plugins/FindBadConstructsAction.cpp ('k') | tools/clang/plugins/Options.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698