r291581 - [analyzer] Treat pointers to static member functions as function pointers

Devin Coughlin via cfe-commits cfe-commits at lists.llvm.org
Tue Jan 10 10:49:27 PST 2017


Author: dcoughlin
Date: Tue Jan 10 12:49:27 2017
New Revision: 291581

URL: http://llvm.org/viewvc/llvm-project?rev=291581&view=rev
Log:
[analyzer] Treat pointers to static member functions as function pointers

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).

Differential Revision: https://reviews.llvm.org/D28033

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

Modified: cfe/trunk/lib/StaticAnalyzer/Core/SValBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/SValBuilder.cpp?rev=291581&r1=291580&r2=291581&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/SValBuilder.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/SValBuilder.cpp Tue Jan 10 12:49:27 2017
@@ -218,6 +218,18 @@ SValBuilder::getDerivedRegionValueSymbol
 }
 
 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);
 }
 

Modified: cfe/trunk/test/Analysis/pointer-to-member.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/pointer-to-member.cpp?rev=291581&r1=291580&r2=291581&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/pointer-to-member.cpp (original)
+++ cfe/trunk/test/Analysis/pointer-to-member.cpp Tue Jan 10 12:49:27 2017
@@ -77,7 +77,8 @@ bool testDereferencing() {
 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 @@ namespace testPointerToMemberFunction {
 
     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 @@ namespace testPointerToMemberData {
     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
 




More information about the cfe-commits mailing list