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

Devin Coughlin via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Jan 10 10:46:13 PST 2017


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) = &A::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 = &A::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<CXXMethodDecl>(DD) || isa<FieldDecl>(DD));
+
+  if (auto *MD = dyn_cast_or_null<CXXMethodDecl>(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);
 }
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D28033.83828.patch
Type: text/x-patch
Size: 2215 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170110/61c71f49/attachment-0001.bin>


More information about the cfe-commits mailing list