Skip to content

Commit

Permalink
[clangd] Fix modernize-loop-convert "multiple diag in flight" crash.
Browse files Browse the repository at this point in the history
Summary:
this maybe not ideal, but it is trivial and does fix the crash.

Fixes clangd/clangd#156.

Reviewers: sammccall

Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D78715

(cherry picked from commit a466e4b)
  • Loading branch information
hokein committed Jun 10, 2020
1 parent 85a2d23 commit cd477e7
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 9 deletions.
17 changes: 8 additions & 9 deletions clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
Expand Up @@ -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<FixItHint> FixIts;
if (VarNameFromAlias) {
const auto *AliasVar = cast<VarDecl>(AliasDecl->getSingleDecl());
VarName = AliasVar->getName().str();
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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));
}
}

Expand Down Expand Up @@ -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));
}

Expand Down
27 changes: 27 additions & 0 deletions clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
Expand Up @@ -266,6 +266,33 @@ TEST(DiagnosticsTest, ClangTidy) {
));
}

TEST(DiagnosticTest, NoMultipleDiagnosticInFlight) {
Annotations Main(R"cpp(
template <typename T> struct Foo {
T *begin();
T *end();
};
struct LabelInfo {
int a;
bool b;
};
void f() {
Foo<LabelInfo> 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() {
Expand Down

0 comments on commit cd477e7

Please sign in to comment.