r315250 - [Analyzer] Do not segfault on unexpected call_once implementation

George Karpenkov via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 9 16:20:46 PDT 2017


Author: george.karpenkov
Date: Mon Oct  9 16:20:46 2017
New Revision: 315250

URL: http://llvm.org/viewvc/llvm-project?rev=315250&view=rev
Log:
[Analyzer] Do not segfault on unexpected call_once implementation

Fixes https://bugs.llvm.org/show_bug.cgi?id=34869

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

Modified:
    cfe/trunk/lib/Analysis/BodyFarm.cpp
    cfe/trunk/test/Analysis/call_once.cpp

Modified: cfe/trunk/lib/Analysis/BodyFarm.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/BodyFarm.cpp?rev=315250&r1=315249&r2=315250&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/BodyFarm.cpp (original)
+++ cfe/trunk/lib/Analysis/BodyFarm.cpp Mon Oct  9 16:20:46 2017
@@ -327,6 +327,28 @@ static Stmt *create_call_once(ASTContext
   const ParmVarDecl *Flag = D->getParamDecl(0);
   const ParmVarDecl *Callback = D->getParamDecl(1);
   QualType CallbackType = Callback->getType().getNonReferenceType();
+  QualType FlagType = Flag->getType().getNonReferenceType();
+  CXXRecordDecl *FlagCXXDecl = FlagType->getAsCXXRecordDecl();
+  if (!FlagCXXDecl) {
+    DEBUG(llvm::dbgs() << "Flag field is not a CXX record: "
+                       << "unknown std::call_once implementation."
+                       << "Ignoring the call.\n");
+    return nullptr;
+  }
+
+  // Note: here we are assuming libc++ implementation of call_once,
+  // which has a struct with a field `__state_`.
+  // Body farming might not work for other `call_once` implementations.
+  NamedDecl *FoundDecl = M.findMemberField(FlagCXXDecl, "__state_");
+  ValueDecl *FieldDecl;
+  if (FoundDecl) {
+    FieldDecl = dyn_cast<ValueDecl>(FoundDecl);
+  } else {
+    DEBUG(llvm::dbgs() << "No field __state_ found on std::once_flag struct, "
+                       << "unable to synthesize call_once body, ignoring "
+                       << "the call.\n");
+    return nullptr;
+  }
 
   bool isLambdaCall = CallbackType->getAsCXXRecordDecl() &&
                       CallbackType->getAsCXXRecordDecl()->isLambda();
@@ -355,27 +377,11 @@ static Stmt *create_call_once(ASTContext
     CallbackCall = create_call_once_funcptr_call(C, M, Callback, CallArgs);
   }
 
-  QualType FlagType = Flag->getType().getNonReferenceType();
   DeclRefExpr *FlagDecl =
       M.makeDeclRefExpr(Flag,
                         /* RefersToEnclosingVariableOrCapture=*/true,
                         /* GetNonReferenceType=*/true);
 
-  CXXRecordDecl *FlagCXXDecl = FlagType->getAsCXXRecordDecl();
-
-  // Note: here we are assuming libc++ implementation of call_once,
-  // which has a struct with a field `__state_`.
-  // Body farming might not work for other `call_once` implementations.
-  NamedDecl *FoundDecl = M.findMemberField(FlagCXXDecl, "__state_");
-  ValueDecl *FieldDecl;
-  if (FoundDecl) {
-    FieldDecl = dyn_cast<ValueDecl>(FoundDecl);
-  } else {
-    DEBUG(llvm::dbgs() << "No field __state_ found on std::once_flag struct, "
-                       << "unable to synthesize call_once body, ignoring "
-                       << "the call.\n");
-    return nullptr;
-  }
 
   MemberExpr *Deref = M.makeMemberExpression(FlagDecl, FieldDecl);
   assert(Deref->isLValue());

Modified: cfe/trunk/test/Analysis/call_once.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/call_once.cpp?rev=315250&r1=315249&r2=315250&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/call_once.cpp (original)
+++ cfe/trunk/test/Analysis/call_once.cpp Mon Oct  9 16:20:46 2017
@@ -231,3 +231,12 @@ void test_non_std_call_once() {
   int x = call_once();
   clang_analyzer_eval(x == 5); // expected-warning{{TRUE}}
 }
+
+namespace std {
+template <typename d, typename e>
+void call_once(d, e);
+}
+void g();
+void test_no_segfault_on_different_impl() {
+  std::call_once(g, false); // no-warning
+}




More information about the cfe-commits mailing list