[PATCH] D28033: [analyzer] Treat pointers to static member functions as function pointers

2017-01-10 Thread Devin Coughlin via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL291581: [analyzer] Treat pointers to static member functions 
as function pointers (authored by dcoughlin).

Changed prior to commit:
  https://reviews.llvm.org/D28033?vs=83828=83830#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D28033

Files:
  cfe/trunk/lib/StaticAnalyzer/Core/SValBuilder.cpp
  cfe/trunk/test/Analysis/pointer-to-member.cpp


Index: cfe/trunk/test/Analysis/pointer-to-member.cpp
===
--- cfe/trunk/test/Analysis/pointer-to-member.cpp
+++ cfe/trunk/test/Analysis/pointer-to-member.cpp
@@ -77,7 +77,8 @@
 namespace testPointerToMemberFunction {
   struct A {
 virtual int foo() { return 1; }
-int bar() { return 2;  }
+int bar() { return 2; }
+int static staticMemberFunction(int p) { return p + 1; };
   };
 
   struct B : public A {
@@ -111,11 +112,19 @@
 
 clang_analyzer_eval((APtr->*AFP)() == 3); // expected-warning{{TRUE}}
   }
+
+  void testPointerToStaticMemberCall() {
+int (*fPtr)(int) = ::staticMemberFunction;
+if (fPtr != 0) { // no-crash
+  clang_analyzer_eval(fPtr(2) == 3); // expected-warning{{TRUE}}
+}
+  }
 } // end of testPointerToMemberFunction namespace
 
 namespace testPointerToMemberData {
   struct A {
 int i;
+static int j;
   };
 
   void testPointerToMemberData() {
@@ -126,6 +135,13 @@
 a.*AMdPointer += 1;
 
 clang_analyzer_eval(a.i == 43); // expected-warning{{TRUE}}
+
+int *ptrToStaticField = ::j;
+if (ptrToStaticField != 0) {
+  *ptrToStaticField = 7;
+  clang_analyzer_eval(*ptrToStaticField == 7); // expected-warning{{TRUE}}
+  clang_analyzer_eval(A::j == 7); // expected-warning{{TRUE}}
+}
   }
 } // end of testPointerToMemberData namespace
 
Index: cfe/trunk/lib/StaticAnalyzer/Core/SValBuilder.cpp
===
--- cfe/trunk/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ cfe/trunk/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -218,6 +218,18 @@
 }
 
 DefinedSVal SValBuilder::getMemberPointer(const DeclaratorDecl* DD) {
+  assert(!DD || isa(DD) || isa(DD));
+
+  if (auto *MD = dyn_cast_or_null(DD)) {
+// Sema treats pointers to static member functions as have function pointer
+// type, so return a function pointer for the method.
+// We don't need to play a similar trick for static member fields
+// because these are represented as plain VarDecls and not FieldDecls
+// in the AST.
+if (MD->isStatic())
+  return getFunctionPointer(MD);
+  }
+
   return nonloc::PointerToMember(DD);
 }
 


Index: cfe/trunk/test/Analysis/pointer-to-member.cpp
===
--- cfe/trunk/test/Analysis/pointer-to-member.cpp
+++ cfe/trunk/test/Analysis/pointer-to-member.cpp
@@ -77,7 +77,8 @@
 namespace testPointerToMemberFunction {
   struct A {
 virtual int foo() { return 1; }
-int bar() { return 2;  }
+int bar() { return 2; }
+int static staticMemberFunction(int p) { return p + 1; };
   };
 
   struct B : public A {
@@ -111,11 +112,19 @@
 
 clang_analyzer_eval((APtr->*AFP)() == 3); // expected-warning{{TRUE}}
   }
+
+  void testPointerToStaticMemberCall() {
+int (*fPtr)(int) = ::staticMemberFunction;
+if (fPtr != 0) { // no-crash
+  clang_analyzer_eval(fPtr(2) == 3); // expected-warning{{TRUE}}
+}
+  }
 } // end of testPointerToMemberFunction namespace
 
 namespace testPointerToMemberData {
   struct A {
 int i;
+static int j;
   };
 
   void testPointerToMemberData() {
@@ -126,6 +135,13 @@
 a.*AMdPointer += 1;
 
 clang_analyzer_eval(a.i == 43); // expected-warning{{TRUE}}
+
+int *ptrToStaticField = ::j;
+if (ptrToStaticField != 0) {
+  *ptrToStaticField = 7;
+  clang_analyzer_eval(*ptrToStaticField == 7); // expected-warning{{TRUE}}
+  clang_analyzer_eval(A::j == 7); // expected-warning{{TRUE}}
+}
   }
 } // end of testPointerToMemberData namespace
 
Index: cfe/trunk/lib/StaticAnalyzer/Core/SValBuilder.cpp
===
--- cfe/trunk/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ cfe/trunk/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -218,6 +218,18 @@
 }
 
 DefinedSVal SValBuilder::getMemberPointer(const DeclaratorDecl* DD) {
+  assert(!DD || isa(DD) || isa(DD));
+
+  if (auto *MD = dyn_cast_or_null(DD)) {
+// Sema treats pointers to static member functions as have function pointer
+// type, so return a function pointer for the method.
+// We don't need to play a similar trick for static member fields
+// because these are represented as plain VarDecls and not FieldDecls
+// in the AST.
+if (MD->isStatic())
+  return getFunctionPointer(MD);
+  }
+
   return nonloc::PointerToMember(DD);
 }
 
___
cfe-commits mailing list

[PATCH] D28033: [analyzer] Treat pointers to static member functions as function pointers

2017-01-10 Thread Devin Coughlin via Phabricator via cfe-commits
dcoughlin updated this revision to Diff 83828.
dcoughlin added a comment.

Updating spacing, as @kromanenkov requested.


https://reviews.llvm.org/D28033

Files:
  lib/StaticAnalyzer/Core/SValBuilder.cpp
  test/Analysis/pointer-to-member.cpp


Index: test/Analysis/pointer-to-member.cpp
===
--- test/Analysis/pointer-to-member.cpp
+++ test/Analysis/pointer-to-member.cpp
@@ -77,7 +77,8 @@
 namespace testPointerToMemberFunction {
   struct A {
 virtual int foo() { return 1; }
-int bar() { return 2;  }
+int bar() { return 2; }
+int static staticMemberFunction(int p) { return p + 1; };
   };
 
   struct B : public A {
@@ -111,11 +112,19 @@
 
 clang_analyzer_eval((APtr->*AFP)() == 3); // expected-warning{{TRUE}}
   }
+
+  void testPointerToStaticMemberCall() {
+int (*fPtr)(int) = ::staticMemberFunction;
+if (fPtr != 0) { // no-crash
+  clang_analyzer_eval(fPtr(2) == 3); // expected-warning{{TRUE}}
+}
+  }
 } // end of testPointerToMemberFunction namespace
 
 namespace testPointerToMemberData {
   struct A {
 int i;
+static int j;
   };
 
   void testPointerToMemberData() {
@@ -126,6 +135,13 @@
 a.*AMdPointer += 1;
 
 clang_analyzer_eval(a.i == 43); // expected-warning{{TRUE}}
+
+int *ptrToStaticField = ::j;
+if (ptrToStaticField != 0) {
+  *ptrToStaticField = 7;
+  clang_analyzer_eval(*ptrToStaticField == 7); // expected-warning{{TRUE}}
+  clang_analyzer_eval(A::j == 7); // expected-warning{{TRUE}}
+}
   }
 } // end of testPointerToMemberData namespace
 
Index: lib/StaticAnalyzer/Core/SValBuilder.cpp
===
--- lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -218,6 +218,18 @@
 }
 
 DefinedSVal SValBuilder::getMemberPointer(const DeclaratorDecl* DD) {
+  assert(!DD || isa(DD) || isa(DD));
+
+  if (auto *MD = dyn_cast_or_null(DD)) {
+// Sema treats pointers to static member functions as have function pointer
+// type, so return a function pointer for the method.
+// We don't need to play a similar trick for static member fields
+// because these are represented as plain VarDecls and not FieldDecls
+// in the AST.
+if (MD->isStatic())
+  return getFunctionPointer(MD);
+  }
+
   return nonloc::PointerToMember(DD);
 }
 


Index: test/Analysis/pointer-to-member.cpp
===
--- test/Analysis/pointer-to-member.cpp
+++ test/Analysis/pointer-to-member.cpp
@@ -77,7 +77,8 @@
 namespace testPointerToMemberFunction {
   struct A {
 virtual int foo() { return 1; }
-int bar() { return 2;  }
+int bar() { return 2; }
+int static staticMemberFunction(int p) { return p + 1; };
   };
 
   struct B : public A {
@@ -111,11 +112,19 @@
 
 clang_analyzer_eval((APtr->*AFP)() == 3); // expected-warning{{TRUE}}
   }
+
+  void testPointerToStaticMemberCall() {
+int (*fPtr)(int) = ::staticMemberFunction;
+if (fPtr != 0) { // no-crash
+  clang_analyzer_eval(fPtr(2) == 3); // expected-warning{{TRUE}}
+}
+  }
 } // end of testPointerToMemberFunction namespace
 
 namespace testPointerToMemberData {
   struct A {
 int i;
+static int j;
   };
 
   void testPointerToMemberData() {
@@ -126,6 +135,13 @@
 a.*AMdPointer += 1;
 
 clang_analyzer_eval(a.i == 43); // expected-warning{{TRUE}}
+
+int *ptrToStaticField = ::j;
+if (ptrToStaticField != 0) {
+  *ptrToStaticField = 7;
+  clang_analyzer_eval(*ptrToStaticField == 7); // expected-warning{{TRUE}}
+  clang_analyzer_eval(A::j == 7); // expected-warning{{TRUE}}
+}
   }
 } // end of testPointerToMemberData namespace
 
Index: lib/StaticAnalyzer/Core/SValBuilder.cpp
===
--- lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -218,6 +218,18 @@
 }
 
 DefinedSVal SValBuilder::getMemberPointer(const DeclaratorDecl* DD) {
+  assert(!DD || isa(DD) || isa(DD));
+
+  if (auto *MD = dyn_cast_or_null(DD)) {
+// Sema treats pointers to static member functions as have function pointer
+// type, so return a function pointer for the method.
+// We don't need to play a similar trick for static member fields
+// because these are represented as plain VarDecls and not FieldDecls
+// in the AST.
+if (MD->isStatic())
+  return getFunctionPointer(MD);
+  }
+
   return nonloc::PointerToMember(DD);
 }
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D28033: [analyzer] Treat pointers to static member functions as function pointers

2017-01-10 Thread Kirill Romanenkov via Phabricator via cfe-commits
kromanenkov accepted this revision.
kromanenkov added a comment.
This revision is now accepted and ready to land.

Looks good to me, apart from a very small cavil introduced in not even your 
code. Thanks for not leaving pointers to static member functions out of account!




Comment at: test/Analysis/pointer-to-member.cpp:80
 virtual int foo() { return 1; }
 int bar() { return 2;  }
+int static staticMemberFunction(int p) { return p + 1; };

This line is not affected by your patch but would you please delete the extra 
space before the second brace?


https://reviews.llvm.org/D28033



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D28033: [analyzer] Treat pointers to static member functions as function pointers

2016-12-21 Thread Devin Coughlin via Phabricator via cfe-commits
dcoughlin created this revision.
dcoughlin added a reviewer: kromanenkov.
dcoughlin added subscribers: cfe-commits, NoQ, zaks.anna.

Sema treats pointers to static member functions as having function pointer
type, so treat treat them as function pointer values in the analyzer as well.
This prevents an assertion failure in SValBuilder::evalBinOp caused by code
that expects function pointers to be Locs (in contrast, PointerToMember values
are nonlocs).

Kirill: does this look alright to you?


https://reviews.llvm.org/D28033

Files:
  lib/StaticAnalyzer/Core/SValBuilder.cpp
  test/Analysis/pointer-to-member.cpp


Index: test/Analysis/pointer-to-member.cpp
===
--- test/Analysis/pointer-to-member.cpp
+++ test/Analysis/pointer-to-member.cpp
@@ -78,6 +78,7 @@
   struct A {
 virtual int foo() { return 1; }
 int bar() { return 2;  }
+int static staticMemberFunction(int p) { return p + 1; };
   };
 
   struct B : public A {
@@ -111,11 +112,19 @@
 
 clang_analyzer_eval((APtr->*AFP)() == 3); // expected-warning{{TRUE}}
   }
+
+  void testPointerToStaticMemberCall() {
+int (*fPtr)(int) = ::staticMemberFunction;
+if (fPtr != 0) { // no-crash
+  clang_analyzer_eval(fPtr(2) == 3); // expected-warning{{TRUE}}
+}
+  }
 } // end of testPointerToMemberFunction namespace
 
 namespace testPointerToMemberData {
   struct A {
 int i;
+static int j;
   };
 
   void testPointerToMemberData() {
@@ -126,6 +135,13 @@
 a.*AMdPointer += 1;
 
 clang_analyzer_eval(a.i == 43); // expected-warning{{TRUE}}
+
+int *ptrToStaticField = ::j;
+if (ptrToStaticField != 0) {
+  *ptrToStaticField = 7;
+  clang_analyzer_eval(*ptrToStaticField == 7); // expected-warning{{TRUE}}
+  clang_analyzer_eval(A::j == 7); // expected-warning{{TRUE}}
+}
   }
 } // end of testPointerToMemberData namespace
 
Index: lib/StaticAnalyzer/Core/SValBuilder.cpp
===
--- lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -218,6 +218,18 @@
 }
 
 DefinedSVal SValBuilder::getMemberPointer(const DeclaratorDecl* DD) {
+  assert(!DD || isa(DD) || isa(DD));
+
+  if (auto *MD = dyn_cast_or_null(DD)) {
+// Sema treats pointers to static member functions as have function pointer
+// type, so return a function pointer for the method.
+// We don't need to play a similar trick for static member fields
+// because these are represented as plain VarDecls and not FieldDecls
+// in the AST.
+if (MD->isStatic())
+  return getFunctionPointer(MD);
+  }
+
   return nonloc::PointerToMember(DD);
 }
 


Index: test/Analysis/pointer-to-member.cpp
===
--- test/Analysis/pointer-to-member.cpp
+++ test/Analysis/pointer-to-member.cpp
@@ -78,6 +78,7 @@
   struct A {
 virtual int foo() { return 1; }
 int bar() { return 2;  }
+int static staticMemberFunction(int p) { return p + 1; };
   };
 
   struct B : public A {
@@ -111,11 +112,19 @@
 
 clang_analyzer_eval((APtr->*AFP)() == 3); // expected-warning{{TRUE}}
   }
+
+  void testPointerToStaticMemberCall() {
+int (*fPtr)(int) = ::staticMemberFunction;
+if (fPtr != 0) { // no-crash
+  clang_analyzer_eval(fPtr(2) == 3); // expected-warning{{TRUE}}
+}
+  }
 } // end of testPointerToMemberFunction namespace
 
 namespace testPointerToMemberData {
   struct A {
 int i;
+static int j;
   };
 
   void testPointerToMemberData() {
@@ -126,6 +135,13 @@
 a.*AMdPointer += 1;
 
 clang_analyzer_eval(a.i == 43); // expected-warning{{TRUE}}
+
+int *ptrToStaticField = ::j;
+if (ptrToStaticField != 0) {
+  *ptrToStaticField = 7;
+  clang_analyzer_eval(*ptrToStaticField == 7); // expected-warning{{TRUE}}
+  clang_analyzer_eval(A::j == 7); // expected-warning{{TRUE}}
+}
   }
 } // end of testPointerToMemberData namespace
 
Index: lib/StaticAnalyzer/Core/SValBuilder.cpp
===
--- lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -218,6 +218,18 @@
 }
 
 DefinedSVal SValBuilder::getMemberPointer(const DeclaratorDecl* DD) {
+  assert(!DD || isa(DD) || isa(DD));
+
+  if (auto *MD = dyn_cast_or_null(DD)) {
+// Sema treats pointers to static member functions as have function pointer
+// type, so return a function pointer for the method.
+// We don't need to play a similar trick for static member fields
+// because these are represented as plain VarDecls and not FieldDecls
+// in the AST.
+if (MD->isStatic())
+  return getFunctionPointer(MD);
+  }
+
   return nonloc::PointerToMember(DD);
 }
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits