diff --git a/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp b/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp index f359702b3f5080..01a6ca74898b94 100644 --- a/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp @@ -522,13 +522,11 @@ void LoopConvertCheck::doConversion( const ValueDecl *MaybeContainer, const UsageResult &Usages, const DeclStmt *AliasDecl, bool AliasUseRequired, bool AliasFromForInit, const ForStmt *Loop, RangeDescriptor Descriptor) { - auto Diag = diag(Loop->getForLoc(), "use range-based for loop instead"); - std::string VarName; bool VarNameFromAlias = (Usages.size() == 1) && AliasDecl; bool AliasVarIsRef = false; bool CanCopy = true; - + std::vector FixIts; if (VarNameFromAlias) { const auto *AliasVar = cast(AliasDecl->getSingleDecl()); VarName = AliasVar->getName().str(); @@ -560,8 +558,8 @@ void LoopConvertCheck::doConversion( getAliasRange(Context->getSourceManager(), ReplaceRange); } - Diag << FixItHint::CreateReplacement( - CharSourceRange::getTokenRange(ReplaceRange), ReplacementText); + FixIts.push_back(FixItHint::CreateReplacement( + CharSourceRange::getTokenRange(ReplaceRange), ReplacementText)); // No further replacements are made to the loop, since the iterator or index // was used exactly once - in the initialization of AliasVar. } else { @@ -606,8 +604,8 @@ void LoopConvertCheck::doConversion( Usage.Kind == Usage::UK_CaptureByCopy ? "&" + VarName : VarName; } TUInfo->getReplacedVars().insert(std::make_pair(Loop, IndexVar)); - Diag << FixItHint::CreateReplacement( - CharSourceRange::getTokenRange(Range), ReplaceText); + FixIts.push_back(FixItHint::CreateReplacement( + CharSourceRange::getTokenRange(Range), ReplaceText)); } } @@ -645,8 +643,9 @@ void LoopConvertCheck::doConversion( std::string Range = ("(" + TypeString + " " + VarName + " : " + MaybeDereference + Descriptor.ContainerString + ")") .str(); - Diag << FixItHint::CreateReplacement( - CharSourceRange::getTokenRange(ParenRange), Range); + FixIts.push_back(FixItHint::CreateReplacement( + CharSourceRange::getTokenRange(ParenRange), Range)); + diag(Loop->getForLoc(), "use range-based for loop instead") << FixIts; TUInfo->getGeneratedDecls().insert(make_pair(Loop, VarName)); } diff --git a/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp b/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp index ef73519ef1385e..1fdd54888149f4 100644 --- a/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp +++ b/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp @@ -266,6 +266,33 @@ TEST(DiagnosticsTest, ClangTidy) { )); } +TEST(DiagnosticTest, NoMultipleDiagnosticInFlight) { + Annotations Main(R"cpp( + template struct Foo { + T *begin(); + T *end(); + }; + struct LabelInfo { + int a; + bool b; + }; + + void f() { + Foo label_info_map; + [[for]] (auto it = label_info_map.begin(); it != label_info_map.end(); ++it) { + auto S = *it; + } + } + )cpp"); + TestTU TU = TestTU::withCode(Main.code()); + TU.ClangTidyChecks = "modernize-loop-convert"; + EXPECT_THAT( + TU.build().getDiagnostics(), + UnorderedElementsAre(::testing::AllOf( + Diag(Main.range(), "use range-based for loop instead"), + DiagSource(Diag::ClangTidy), DiagName("modernize-loop-convert")))); +} + TEST(DiagnosticTest, ClangTidySuppressionComment) { Annotations Main(R"cpp( int main() {