Index: clang-tidy/utils/ExprMutationAnalyzer.cpp =================================================================== --- clang-tidy/utils/ExprMutationAnalyzer.cpp +++ clang-tidy/utils/ExprMutationAnalyzer.cpp @@ -48,7 +48,8 @@ } const auto nonConstReferenceType = [] { - return referenceType(pointee(unless(isConstQualified()))); + return hasUnqualifiedDesugaredType( + referenceType(pointee(unless(isConstQualified())))); }; } // namespace Index: unittests/clang-tidy/ExprMutationAnalyzerTest.cpp =================================================================== --- unittests/clang-tidy/ExprMutationAnalyzerTest.cpp +++ unittests/clang-tidy/ExprMutationAnalyzerTest.cpp @@ -168,6 +168,18 @@ match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("g(x)")); + AST = tooling::buildASTFromCode("typedef int& IntRef;" + "void g(IntRef); void f() { int x; g(x); }"); + Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("g(x)")); + + AST = tooling::buildASTFromCode( + "template struct identity { using type = T; };" + "template void g(typename identity::type);" + "void f() { int x; g(x); }"); + Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("g(x)")); + AST = tooling::buildASTFromCode( "void f() { struct A {}; A operator+(A&, int); A x; x + 1; }"); Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); @@ -348,13 +360,22 @@ } TEST(ExprMutationAnalyzerTest, FollowRefModified) { - const auto AST = tooling::buildASTFromCode( + auto AST = tooling::buildASTFromCode( "void f() { int x; int& r0 = x; int& r1 = r0; int& r2 = r1; " "int& r3 = r2; r3 = 10; }"); - const auto Results = + auto Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("r0", "r1", "r2", "r3", "r3 = 10")); + + AST = tooling::buildASTFromCode( + "typedef int& IntRefX;" + "using IntRefY = int&;" + "void f() { int x; IntRefX r0 = x; IntRefY r1 = r0;" + "decltype((x)) r2 = r1; r2 = 10; }"); + Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_THAT(mutatedBy(Results, AST.get()), + ElementsAre("r0", "r1", "r2", "r2 = 10")); } TEST(ExprMutationAnalyzerTest, FollowRefNotModified) { @@ -424,12 +445,19 @@ } TEST(ExprMutationAnalyzerTest, CastToRefModified) { - const auto AST = tooling::buildASTFromCode( + auto AST = tooling::buildASTFromCode( "void f() { int x; static_cast(x) = 10; }"); - const auto Results = + auto Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("static_cast(x) = 10")); + + AST = tooling::buildASTFromCode( + "typedef int& IntRef;" + "void f() { int x; static_cast(x) = 10; }"); + Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_THAT(mutatedBy(Results, AST.get()), + ElementsAre("static_cast(x) = 10")); } TEST(ExprMutationAnalyzerTest, CastToRefNotModified) { @@ -483,11 +511,17 @@ } TEST(ExprMutationAnalyzerTest, RangeForArrayByRefModified) { - const auto AST = tooling::buildASTFromCode( + auto AST = tooling::buildASTFromCode( "void f() { int x[2]; for (int& e : x) e = 10; }"); - const auto Results = + auto Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("e", "e = 10")); + + AST = tooling::buildASTFromCode( + "typedef int& IntRef;" + "void f() { int x[2]; for (IntRef e : x) e = 10; }"); + Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("e", "e = 10")); } TEST(ExprMutationAnalyzerTest, RangeForArrayByRefNotModified) {