diff options
Diffstat (limited to 'clang-tools-extra/unittests/clang-tidy/ExprMutationAnalyzerTest.cpp')
-rw-r--r-- | clang-tools-extra/unittests/clang-tidy/ExprMutationAnalyzerTest.cpp | 110 |
1 files changed, 106 insertions, 4 deletions
diff --git a/clang-tools-extra/unittests/clang-tidy/ExprMutationAnalyzerTest.cpp b/clang-tools-extra/unittests/clang-tidy/ExprMutationAnalyzerTest.cpp index 042d4cbef6f..117bcfe4200 100644 --- a/clang-tools-extra/unittests/clang-tidy/ExprMutationAnalyzerTest.cpp +++ b/clang-tools-extra/unittests/clang-tidy/ExprMutationAnalyzerTest.cpp @@ -114,6 +114,26 @@ TEST(ExprMutationAnalyzerTest, NonConstMemberFunc) { EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x.mf()")); } +TEST(ExprMutationAnalyzerTest, AssumedNonConstMemberFunc) { + auto AST = tooling::buildASTFromCode( + "struct X { template <class T> void mf(); };" + "template <class T> void f() { X x; x.mf<T>(); }"); + auto Results = + match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x.mf<T>()")); + + AST = + tooling::buildASTFromCode("template <class T> void f() { T x; x.mf(); }"); + Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x.mf()")); + + AST = tooling::buildASTFromCode( + "template <class T> struct X;" + "template <class T> void f() { X<T> x; x.mf(); }"); + Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x.mf()")); +} + TEST(ExprMutationAnalyzerTest, ConstMemberFunc) { const auto AST = tooling::buildASTFromCode( "void f() { struct Foo { void mf() const; }; Foo x; x.mf(); }"); @@ -292,6 +312,51 @@ TEST(ExprMutationAnalyzerTest, Forward) { ElementsAre("std::forward<A &>(x)")); } +TEST(ExprMutationAnalyzerTest, CallUnresolved) { + auto AST = + tooling::buildASTFromCode("template <class T> void f() { T x; g(x); }"); + auto Results = + match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("g(x)")); + + AST = tooling::buildASTFromCode( + "template <int N> void f() { char x[N]; g(x); }"); + Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("g(x)")); + + AST = tooling::buildASTFromCode( + "template <class T> void f(T t) { int x; g(t, x); }"); + Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("g(t, x)")); + + AST = tooling::buildASTFromCode( + "template <class T> void f(T t) { int x; t.mf(x); }"); + Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("t.mf(x)")); + + AST = tooling::buildASTFromCode( + "template <class T> struct S;" + "template <class T> void f() { S<T> s; int x; s.mf(x); }"); + Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("s.mf(x)")); + + AST = tooling::buildASTFromCode( + "struct S { template <class T> void mf(); };" + "template <class T> void f(S s) { int x; s.mf<T>(x); }"); + Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("s.mf<T>(x)")); + + AST = tooling::buildASTFromCode("template <class F>" + "void g(F f) { int x; f(x); } "); + Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("f(x)")); + + AST = tooling::buildASTFromCode( + "template <class T> void f() { int x; (void)T(x); }"); + Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("T(x)")); +} + TEST(ExprMutationAnalyzerTest, ReturnAsValue) { const auto AST = tooling::buildASTFromCode("int f() { int x; return x; }"); const auto Results = @@ -347,6 +412,21 @@ TEST(ExprMutationAnalyzerTest, ArrayToPointerDecay) { EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x")); } +TEST(ExprMutationAnalyzerTest, TemplateWithArrayToPointerDecay) { + const auto AST = tooling::buildASTFromCode( + "template <typename T> struct S { static constexpr int v = 8; };" + "template <> struct S<int> { static constexpr int v = 4; };" + "void g(char*);" + "template <typename T> void f() { char x[S<T>::v]; g(x); }" + "template <> void f<int>() { char y[S<int>::v]; g(y); }"); + const auto ResultsX = + match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_THAT(mutatedBy(ResultsX, AST.get()), ElementsAre("g(x)")); + const auto ResultsY = + match(withEnclosingCompound(declRefTo("y")), AST->getASTContext()); + EXPECT_THAT(mutatedBy(ResultsY, AST.get()), ElementsAre("y")); +} + TEST(ExprMutationAnalyzerTest, FollowRefModified) { const auto AST = tooling::buildASTFromCode( "void f() { int x; int& r0 = x; int& r1 = r0; int& r2 = r1; " @@ -398,21 +478,43 @@ TEST(ExprMutationAnalyzerTest, ArrayElementNotModified) { } TEST(ExprMutationAnalyzerTest, NestedMemberModified) { - const auto AST = tooling::buildASTFromCode( + auto AST = tooling::buildASTFromCode( "void f() { struct A { int vi; }; struct B { A va; }; " "struct C { B vb; }; C x; x.vb.va.vi = 10; }"); - const auto Results = + auto Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x.vb.va.vi = 10")); + + AST = tooling::buildASTFromCode( + "template <class T> void f() { T x; x.y.z = 10; }"); + Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x.y.z = 10")); + + AST = tooling::buildASTFromCode( + "template <class T> struct S;" + "template <class T> void f() { S<T> x; x.y.z = 10; }"); + Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x.y.z = 10")); } TEST(ExprMutationAnalyzerTest, NestedMemberNotModified) { - const auto AST = tooling::buildASTFromCode( + auto AST = tooling::buildASTFromCode( "void f() { struct A { int vi; }; struct B { A va; }; " "struct C { B vb; }; C x; x.vb.va.vi; }"); - const auto Results = + auto Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); EXPECT_FALSE(isMutated(Results, AST.get())); + + AST = + tooling::buildASTFromCode("template <class T> void f() { T x; x.y.z; }"); + Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_FALSE(isMutated(Results, AST.get())); + + AST = tooling::buildASTFromCode( + "template <class T> struct S;" + "template <class T> void f() { S<T> x; x.y.z; }"); + Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_FALSE(isMutated(Results, AST.get())); } TEST(ExprMutationAnalyzerTest, CastToValue) { |