| OLD | NEW |
| 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 "clang/Sema/Sema.h" | 10 #include "clang/Sema/Sema.h" |
| (...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 453 return true; | 453 return true; |
| 454 } | 454 } |
| 455 } | 455 } |
| 456 | 456 |
| 457 return false; | 457 return false; |
| 458 } | 458 } |
| 459 | 459 |
| 460 SuppressibleDiagnosticBuilder | 460 SuppressibleDiagnosticBuilder |
| 461 FindBadConstructsConsumer::ReportIfSpellingLocNotIgnored( | 461 FindBadConstructsConsumer::ReportIfSpellingLocNotIgnored( |
| 462 SourceLocation loc, | 462 SourceLocation loc, |
| 463 const Decl* record, |
| 463 unsigned diagnostic_id) { | 464 unsigned diagnostic_id) { |
| 464 LocationType type = | 465 LocationType type = ClassifyLocation( |
| 465 ClassifyLocation(instance().getSourceManager().getSpellingLoc(loc)); | 466 instance().getSourceManager().getSpellingLoc(loc), record); |
| 466 bool ignored = | 467 bool ignored = |
| 467 type == LocationType::kThirdParty || type == LocationType::kBlink; | 468 type == LocationType::kThirdParty || type == LocationType::kBlink; |
| 468 return SuppressibleDiagnosticBuilder(&diagnostic(), loc, diagnostic_id, | 469 return SuppressibleDiagnosticBuilder(&diagnostic(), loc, diagnostic_id, |
| 469 ignored); | 470 ignored); |
| 470 } | 471 } |
| 471 | 472 |
| 472 // Checks that virtual methods are correctly annotated, and have no body in a | 473 // Checks that virtual methods are correctly annotated, and have no body in a |
| 473 // header file. | 474 // header file. |
| 474 void FindBadConstructsConsumer::CheckVirtualMethods( | 475 void FindBadConstructsConsumer::CheckVirtualMethods( |
| 475 SourceLocation record_location, | 476 SourceLocation record_location, |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 527 | 528 |
| 528 SourceManager& manager = instance().getSourceManager(); | 529 SourceManager& manager = instance().getSourceManager(); |
| 529 const LangOptions& lang_opts = instance().getLangOpts(); | 530 const LangOptions& lang_opts = instance().getLangOpts(); |
| 530 | 531 |
| 531 // Complain if a method is annotated virtual && (override || final). | 532 // Complain if a method is annotated virtual && (override || final). |
| 532 if (has_virtual && (override_attr || final_attr)) { | 533 if (has_virtual && (override_attr || final_attr)) { |
| 533 // ... but only if virtual does not originate in a macro from a banned file. | 534 // ... but only if virtual does not originate in a macro from a banned file. |
| 534 // Note this is just an educated guess: the assumption here is that any | 535 // Note this is just an educated guess: the assumption here is that any |
| 535 // macro for declaring methods will probably be at the start of the method's | 536 // macro for declaring methods will probably be at the start of the method's |
| 536 // source range. | 537 // source range. |
| 537 ReportIfSpellingLocNotIgnored(method->getLocStart(), | 538 ReportIfSpellingLocNotIgnored(method->getLocStart(), method, |
| 538 diag_redundant_virtual_specifier_) | 539 diag_redundant_virtual_specifier_) |
| 539 << "'virtual'" | 540 << "'virtual'" |
| 540 << (override_attr ? static_cast<Attr*>(override_attr) : final_attr) | 541 << (override_attr ? static_cast<Attr*>(override_attr) : final_attr) |
| 541 << FixItRemovalForVirtual(manager, lang_opts, method); | 542 << FixItRemovalForVirtual(manager, lang_opts, method); |
| 542 } | 543 } |
| 543 | 544 |
| 544 // Complain if a method is an override and is not annotated with override or | 545 // Complain if a method is an override and is not annotated with override or |
| 545 // final. | 546 // final. |
| 546 if (is_override && !override_attr && !final_attr) { | 547 if (is_override && !override_attr && !final_attr) { |
| 547 SourceRange range = method->getSourceRange(); | 548 SourceRange range = method->getSourceRange(); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 578 break; | 579 break; |
| 579 } else if (token.is(tok::equal)) { | 580 } else if (token.is(tok::equal)) { |
| 580 loc = l; | 581 loc = l; |
| 581 break; | 582 break; |
| 582 } | 583 } |
| 583 } | 584 } |
| 584 } | 585 } |
| 585 // Again, only emit the warning if it doesn't originate from a macro in | 586 // Again, only emit the warning if it doesn't originate from a macro in |
| 586 // a system header. | 587 // a system header. |
| 587 if (loc.isValid()) { | 588 if (loc.isValid()) { |
| 588 ReportIfSpellingLocNotIgnored(loc, diag_method_requires_override_) | 589 ReportIfSpellingLocNotIgnored(loc, method, diag_method_requires_override_) |
| 589 << FixItHint::CreateInsertion(loc, " override"); | 590 << FixItHint::CreateInsertion(loc, " override"); |
| 590 } else { | 591 } else { |
| 591 ReportIfSpellingLocNotIgnored(range.getBegin(), | 592 ReportIfSpellingLocNotIgnored(range.getBegin(), method, |
| 592 diag_method_requires_override_); | 593 diag_method_requires_override_); |
| 593 } | 594 } |
| 594 } | 595 } |
| 595 | 596 |
| 596 if (final_attr && override_attr) { | 597 if (final_attr && override_attr) { |
| 597 ReportIfSpellingLocNotIgnored(override_attr->getLocation(), | 598 ReportIfSpellingLocNotIgnored(override_attr->getLocation(), method, |
| 598 diag_redundant_virtual_specifier_) | 599 diag_redundant_virtual_specifier_) |
| 599 << override_attr << final_attr | 600 << override_attr << final_attr |
| 600 << FixItHint::CreateRemoval(override_attr->getRange()); | 601 << FixItHint::CreateRemoval(override_attr->getRange()); |
| 601 } | 602 } |
| 602 | 603 |
| 603 if (final_attr && !is_override) { | 604 if (final_attr && !is_override) { |
| 604 ReportIfSpellingLocNotIgnored(method->getLocStart(), | 605 ReportIfSpellingLocNotIgnored(method->getLocStart(), method, |
| 605 diag_base_method_virtual_and_final_) | 606 diag_base_method_virtual_and_final_) |
| 606 << FixItRemovalForVirtual(manager, lang_opts, method) | 607 << FixItRemovalForVirtual(manager, lang_opts, method) |
| 607 << FixItHint::CreateRemoval(final_attr->getRange()); | 608 << FixItHint::CreateRemoval(final_attr->getRange()); |
| 608 } | 609 } |
| 609 } | 610 } |
| 610 | 611 |
| 611 void FindBadConstructsConsumer::CheckVirtualBodies( | 612 void FindBadConstructsConsumer::CheckVirtualBodies( |
| 612 const CXXMethodDecl* method) { | 613 const CXXMethodDecl* method) { |
| 613 // Virtual methods should not have inline definitions beyond "{}". This | 614 // Virtual methods should not have inline definitions beyond "{}". This |
| 614 // only matters for header files. | 615 // only matters for header files. |
| 615 if (method->hasBody() && method->hasInlineBody()) { | 616 if (method->hasBody() && method->hasInlineBody()) { |
| 616 if (CompoundStmt* cs = dyn_cast<CompoundStmt>(method->getBody())) { | 617 if (CompoundStmt* cs = dyn_cast<CompoundStmt>(method->getBody())) { |
| 617 if (cs->size()) { | 618 if (cs->size()) { |
| 618 SourceLocation loc = cs->getLBracLoc(); | 619 SourceLocation loc = cs->getLBracLoc(); |
| 619 // CR_BEGIN_MSG_MAP_EX and BEGIN_SAFE_MSG_MAP_EX try to be compatible | 620 // CR_BEGIN_MSG_MAP_EX and BEGIN_SAFE_MSG_MAP_EX try to be compatible |
| 620 // to BEGIN_MSG_MAP(_EX). So even though they are in chrome code, | 621 // to BEGIN_MSG_MAP(_EX). So even though they are in chrome code, |
| 621 // we can't easily fix them, so explicitly whitelist them here. | 622 // we can't easily fix them, so explicitly whitelist them here. |
| 622 bool emit = true; | 623 bool emit = true; |
| 623 if (loc.isMacroID()) { | 624 if (loc.isMacroID()) { |
| 624 SourceManager& manager = instance().getSourceManager(); | 625 SourceManager& manager = instance().getSourceManager(); |
| 625 LocationType type = ClassifyLocation(manager.getSpellingLoc(loc)); | 626 LocationType type = |
| 627 ClassifyLocation(manager.getSpellingLoc(loc), method); |
| 626 if (type == LocationType::kThirdParty || type == LocationType::kBlink) | 628 if (type == LocationType::kThirdParty || type == LocationType::kBlink) |
| 627 emit = false; | 629 emit = false; |
| 628 else { | 630 else { |
| 629 StringRef name = Lexer::getImmediateMacroName( | 631 StringRef name = Lexer::getImmediateMacroName( |
| 630 loc, manager, instance().getLangOpts()); | 632 loc, manager, instance().getLangOpts()); |
| 631 if (name == "CR_BEGIN_MSG_MAP_EX" || | 633 if (name == "CR_BEGIN_MSG_MAP_EX" || |
| 632 name == "BEGIN_SAFE_MSG_MAP_EX") | 634 name == "BEGIN_SAFE_MSG_MAP_EX") |
| 633 emit = false; | 635 emit = false; |
| 634 } | 636 } |
| 635 } | 637 } |
| (...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1006 non_reference_type->getAs<clang::AutoType>(); | 1008 non_reference_type->getAs<clang::AutoType>(); |
| 1007 if (auto_type) { | 1009 if (auto_type) { |
| 1008 if (auto_type->isDeduced()) { | 1010 if (auto_type->isDeduced()) { |
| 1009 QualType deduced_type = auto_type->getDeducedType(); | 1011 QualType deduced_type = auto_type->getDeducedType(); |
| 1010 if (!deduced_type.isNull() && deduced_type->isPointerType() && | 1012 if (!deduced_type.isNull() && deduced_type->isPointerType() && |
| 1011 !deduced_type->isFunctionPointerType()) { | 1013 !deduced_type->isFunctionPointerType()) { |
| 1012 // Check if we should even be considering this type (note that there | 1014 // Check if we should even be considering this type (note that there |
| 1013 // should be fewer auto types than banned namespace/directory types, | 1015 // should be fewer auto types than banned namespace/directory types, |
| 1014 // so check this last. | 1016 // so check this last. |
| 1015 LocationType location_type = | 1017 LocationType location_type = |
| 1016 ClassifyLocation(var_decl->getLocStart()); | 1018 ClassifyLocation(var_decl->getLocStart(), var_decl); |
| 1017 if (!InBannedNamespace(var_decl) && | 1019 if (!InBannedNamespace(var_decl) && |
| 1018 location_type != LocationType::kThirdParty) { | 1020 location_type != LocationType::kThirdParty) { |
| 1019 // The range starts from |var_decl|'s loc start, which is the | 1021 // The range starts from |var_decl|'s loc start, which is the |
| 1020 // beginning of the full expression defining this |var_decl|. It | 1022 // beginning of the full expression defining this |var_decl|. It |
| 1021 // ends, however, where this |var_decl|'s type loc ends, since | 1023 // ends, however, where this |var_decl|'s type loc ends, since |
| 1022 // that's the end of the type of |var_decl|. | 1024 // that's the end of the type of |var_decl|. |
| 1023 // Note that the beginning source location of type loc omits cv | 1025 // Note that the beginning source location of type loc omits cv |
| 1024 // qualifiers, which is why it's not a good candidate to use for the | 1026 // qualifiers, which is why it's not a good candidate to use for the |
| 1025 // start of the range. | 1027 // start of the range. |
| 1026 clang::SourceRange range( | 1028 clang::SourceRange range( |
| 1027 var_decl->getLocStart(), | 1029 var_decl->getLocStart(), |
| 1028 var_decl->getTypeSourceInfo()->getTypeLoc().getLocEnd()); | 1030 var_decl->getTypeSourceInfo()->getTypeLoc().getLocEnd()); |
| 1029 ReportIfSpellingLocNotIgnored(range.getBegin(), | 1031 ReportIfSpellingLocNotIgnored(range.getBegin(), var_decl, |
| 1030 diag_auto_deduced_to_a_pointer_type_) | 1032 diag_auto_deduced_to_a_pointer_type_) |
| 1031 << FixItHint::CreateReplacement( | 1033 << FixItHint::CreateReplacement( |
| 1032 range, | 1034 range, |
| 1033 GetAutoReplacementTypeAsString( | 1035 GetAutoReplacementTypeAsString( |
| 1034 var_decl->getType(), var_decl->getStorageClass())); | 1036 var_decl->getType(), var_decl->getStorageClass())); |
| 1035 } | 1037 } |
| 1036 } | 1038 } |
| 1037 } | 1039 } |
| 1038 } else if (non_reference_type->isPointerType()) { | 1040 } else if (non_reference_type->isPointerType()) { |
| 1039 non_reference_type = non_reference_type->getPointeeType(); | 1041 non_reference_type = non_reference_type->getPointeeType(); |
| 1040 continue; | 1042 continue; |
| 1041 } | 1043 } |
| 1042 break; | 1044 break; |
| 1043 } | 1045 } |
| 1044 } | 1046 } |
| 1045 | 1047 |
| 1046 } // namespace chrome_checker | 1048 } // namespace chrome_checker |
| OLD | NEW |