]> granicus.if.org Git - clang/commitdiff
[analyzer] Fix nullptr access when processing instantiated function in ExprMutationAn...
authorShuai Wang <shuaiwang@google.com>
Wed, 19 Sep 2018 18:00:55 +0000 (18:00 +0000)
committerShuai Wang <shuaiwang@google.com>
Wed, 19 Sep 2018 18:00:55 +0000 (18:00 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@342562 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/ExprMutationAnalyzer.cpp
unittests/Analysis/ExprMutationAnalyzerTest.cpp

index db8c259a52a96f2ea9609f016cf63f7600bd35b0..8414cb5c726aa4c3033ceda3c3b33a214514c7f1 100644 (file)
@@ -379,7 +379,7 @@ const Stmt *ExprMutationAnalyzer::findFunctionArgMutation(const Expr *Exp) {
   for (const auto &Nodes : Matches) {
     const auto *Exp = Nodes.getNodeAs<Expr>(NodeID<Expr>::value);
     const auto *Func = Nodes.getNodeAs<FunctionDecl>("func");
-    if (!Func->getBody())
+    if (!Func->getBody() || !Func->getPrimaryTemplate())
       return Exp;
 
     const auto *Parm = Nodes.getNodeAs<ParmVarDecl>("parm");
index 30950e0dd60dfb80815dfbcc05d694575475171b..8823ac803e341d6892873ab40b527a552994541c 100644 (file)
@@ -215,6 +215,12 @@ TEST(ExprMutationAnalyzerTest, ByValueArgument) {
                          "void f() { A x, y; y = x; }");
   Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
   EXPECT_FALSE(isMutated(Results, AST.get()));
+
+  AST = buildASTFromCode(
+      "template <int> struct A { A(); A(const A&); static void mf(A) {} };"
+      "void f() { A<0> x; A<0>::mf(x); }");
+  Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
 }
 
 TEST(ExprMutationAnalyzerTest, ByConstValueArgument) {
@@ -241,6 +247,12 @@ TEST(ExprMutationAnalyzerTest, ByConstValueArgument) {
       "void f() { struct A { A(const int); }; int x; A y(x); }");
   Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
   EXPECT_FALSE(isMutated(Results, AST.get()));
+
+  AST = buildASTFromCode("template <int> struct A { A(); A(const A&);"
+                         "static void mf(const A&) {} };"
+                         "void f() { A<0> x; A<0>::mf(x); }");
+  Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
 }
 
 TEST(ExprMutationAnalyzerTest, ByNonConstRefArgument) {
@@ -288,6 +300,12 @@ TEST(ExprMutationAnalyzerTest, ByNonConstRefArgument) {
   AST = buildASTFromCode("void f() { struct A { A(); A(A&); }; A x; A y(x); }");
   Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
   EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x"));
+
+  AST = buildASTFromCode(
+      "template <int> struct A { A(); A(const A&); static void mf(A&) {} };"
+      "void f() { A<0> x; A<0>::mf(x); }");
+  Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("A<0>::mf(x)"));
 }
 
 TEST(ExprMutationAnalyzerTest, ByConstRefArgument) {
@@ -686,6 +704,12 @@ TEST(ExprMutationAnalyzerTest, FollowFuncArgModified) {
   Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
   EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x"));
 
+  AST = buildASTFromCode("template <class U> struct S {"
+                         "template <class T> S(T&& t) : m(++t) { } U m; };"
+                         "void f() { int x; S<int> s(x); }");
+  Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_THAT(mutatedBy(Results, AST.get()), ElementsAre("x"));
+
   AST = buildASTFromCode(StdRemoveReference + StdForward +
                          "template <class... Args> void u(Args&...);"
                          "template <class... Args> void h(Args&&... args)"
@@ -737,6 +761,12 @@ TEST(ExprMutationAnalyzerTest, FollowFuncArgNotModified) {
   Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
   EXPECT_FALSE(isMutated(Results, AST.get()));
 
+  AST = buildASTFromCode("template <class U> struct S {"
+                         "template <class T> S(T&& t) : m(t) { } U m; };"
+                         "void f() { int x; S<int> s(x); }");
+  Results = match(withEnclosingCompound(declRefTo("x")), AST->getASTContext());
+  EXPECT_FALSE(isMutated(Results, AST.get()));
+
   AST = buildASTFromCode(StdRemoveReference + StdForward +
                          "template <class... Args> void u(Args...);"
                          "template <class... Args> void h(Args&&... args)"