<div dir="ltr">Bugzilla is not accessible, so here's a reduced test case:<div><span style="font-family:monospace;font-size:13px">$ cat test-clang__BodyFarm__getBody.cc</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">namespace std {</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">template <typename d, typename e></span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">void call_once(d, e);</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">}</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">void g();</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">void f() {</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">  std::call_once(g, false);</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">}</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">$ clang-tidy -checks=-*,clang-analyzer* test-clang__BodyFarm__getBody.cc -- -std=c++11 -w</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">*** SIGSEGV; stack trace: ***</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">PC: @          0x2f96e3a  (unknown)  clang::DeclContext::lookup()</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">    @          0x532bb51       1152  FailureSignalHandler()</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">    @     0x7f42b341f9a0  (unknown)  (unknown)</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">    @          0x2ae74c5        576  (anonymous namespace)::ASTMaker::findMemberField()</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">    @          0x2ae59fc        704  create_call_once()</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">    @          0x2ae5040        784  clang::BodyFarm::getBody()</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">    @          0x2ac67af        144  clang::AnalysisDeclContext::getBody()</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">    @          0x1c499fa        128  clang::ento::AnyFunctionCall::getRuntimeDefinition()</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">    @          0x1cc6146        320  clang::ento::ExprEngine::defaultEvalCall()</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">    @          0x1c61033        464  clang::ento::CheckerManager::runCheckersForEvalCall()</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">    @          0x1cc4fc9        352  clang::ento::ExprEngine::evalCall()</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">    @          0x1cc4e8c        432  clang::ento::ExprEngine::VisitCallExpr()</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">    @          0x1c7da94       4000  clang::ento::ExprEngine::Visit()</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">    @          0x1c7a821        496  clang::ento::ExprEngine::ProcessStmt()</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">    @          0x1c7a4da        240  clang::ento::ExprEngine::processCFGElement()</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">    @          0x1ca8ed6        128  clang::ento::CoreEngine::HandlePostStmt()</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">    @          0x1ca87d6        496  clang::ento::CoreEngine::dispatchWorkItem()</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">    @          0x1ca8338        544  clang::ento::CoreEngine::ExecuteWorkList()</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">    @           0xf954d5         80  clang::ento::ExprEngine::ExecuteWorkList()</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">    @           0xf3c612       1056  (anonymous namespace)::AnalysisConsumer::ActionExprEngine()</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">    @           0xf3c3d1         80  (anonymous namespace)::AnalysisConsumer::RunPathSensitiveChecks()</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">    @           0xf3c095        288  (anonymous namespace)::AnalysisConsumer::HandleCode()</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">    @           0xf2f6e3        416  (anonymous namespace)::AnalysisConsumer::HandleDeclsCallGraph()</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">    @           0xf2d967        336  (anonymous namespace)::AnalysisConsumer::HandleTranslationUnit()</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">    @          0x1366eae         80  clang::MultiplexConsumer::HandleTranslationUnit()</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">    @          0x1dc6ae6        288  clang::ParseAST()</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">    @          0x135475a         80  clang::ASTFrontendAction::ExecuteAction()</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">    @          0x13541f0        112  clang::FrontendAction::Execute()</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">    @          0x1169822        496  clang::CompilerInstance::ExecuteAction()</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">    @          0x1032ba2        464  clang::tooling::FrontendActionFactory::runInvocation()</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">    @          0x1032a43        160  clang::tooling::ToolInvocation::runInvocation()</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">    @          0x1031306       1840  clang::tooling::ToolInvocation::run()</span><br style="font-family:monospace;font-size:13px"><span style="font-family:monospace;font-size:13px">    @          0x1033c30       1664  clang::tooling::ClangTool::run()</span><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Sat, Oct 7, 2017 at 12:56 PM, Alexander Kornienko <span dir="ltr"><<a href="mailto:alexfh@google.com" target="_blank">alexfh@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">This revision might be the cause of <a href="https://bugs.llvm.org/show_bug.cgi?id=34869" target="_blank">https://bugs.llvm.org/show_<wbr>bug.cgi?id=34869</a>. I'm still working on a reduced test case.</div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Sat, Sep 30, 2017 at 2:03 AM, George Karpenkov via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: george.karpenkov<br>
Date: Fri Sep 29 17:03:22 2017<br>
New Revision: 314571<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=314571&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject?rev=314571&view=rev</a><br>
Log:<br>
[Analyzer] Synthesize function body for std::call_once<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D37840" rel="noreferrer" target="_blank">https://reviews.llvm.org/D3784<wbr>0</a><br>
<br>
Added:<br>
    cfe/trunk/test/Analysis/call_o<wbr>nce.cpp<br>
Modified:<br>
    cfe/trunk/lib/Analysis/BodyFar<wbr>m.cpp<br>
<br>
Modified: cfe/trunk/lib/Analysis/BodyFar<wbr>m.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/BodyFarm.cpp?rev=314571&r1=314570&r2=314571&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/lib/Analysis/<wbr>BodyFarm.cpp?rev=314571&r1=<wbr>314570&r2=314571&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Analysis/BodyFar<wbr>m.cpp (original)<br>
+++ cfe/trunk/lib/Analysis/BodyFar<wbr>m.cpp Fri Sep 29 17:03:22 2017<br>
@@ -14,11 +14,18 @@<br>
<br>
 #include "BodyFarm.h"<br>
 #include "clang/AST/ASTContext.h"<br>
+#include "clang/AST/CXXInheritance.h"<br>
 #include "clang/AST/Decl.h"<br>
 #include "clang/AST/Expr.h"<br>
+#include "clang/AST/ExprCXX.h"<br>
 #include "clang/AST/ExprObjC.h"<br>
+#include "clang/AST/NestedNameSpecifier<wbr>.h"<br>
 #include "clang/Analysis/CodeInjector.h<wbr>"<br>
+#include "clang/Basic/OperatorKinds.h"<br>
 #include "llvm/ADT/StringSwitch.h"<br>
+#include "llvm/Support/Debug.h"<br>
+<br>
+#define DEBUG_TYPE "body-farm"<br>
<br>
 using namespace clang;<br>
<br>
@@ -55,7 +62,9 @@ public:<br>
   CompoundStmt *makeCompound(ArrayRef<Stmt*>)<wbr>;<br>
<br>
   /// Create a new DeclRefExpr for the referenced variable.<br>
-  DeclRefExpr *makeDeclRefExpr(const VarDecl *D);<br>
+  DeclRefExpr *makeDeclRefExpr(const VarDecl *D,<br>
+                               bool RefersToEnclosingVariableOrCap<wbr>ture = false,<br>
+                               bool GetNonReferenceType = false);<br>
<br>
   /// Create a new UnaryOperator representing a dereference.<br>
   UnaryOperator *makeDereference(const Expr *Arg, QualType Ty);<br>
@@ -66,9 +75,24 @@ public:<br>
   /// Create an implicit cast to a builtin boolean type.<br>
   ImplicitCastExpr *makeIntegralCastToBoolean(con<wbr>st Expr *Arg);<br>
<br>
-  // Create an implicit cast for lvalue-to-rvaluate conversions.<br>
+  /// Create an implicit cast for lvalue-to-rvaluate conversions.<br>
   ImplicitCastExpr *makeLvalueToRvalue(const Expr *Arg, QualType Ty);<br>
<br>
+  /// Create an implicit cast for lvalue-to-rvaluate conversions.<br>
+  ImplicitCastExpr *makeLvalueToRvalue(const Expr *Arg,<br>
+                                       bool GetNonReferenceType = false);<br>
+<br>
+  /// Make RValue out of variable declaration, creating a temporary<br>
+  /// DeclRefExpr in the process.<br>
+  ImplicitCastExpr *<br>
+  makeLvalueToRvalue(const VarDecl *Decl,<br>
+                     bool RefersToEnclosingVariableOrCap<wbr>ture = false,<br>
+                     bool GetNonReferenceType = false);<br>
+<br>
+  /// Create an implicit cast of the given type.<br>
+  ImplicitCastExpr *makeImplicitCast(const Expr *Arg, QualType Ty,<br>
+                                     CastKind CK = CK_LValueToRValue);<br>
+<br>
   /// Create an Objective-C bool literal.<br>
   ObjCBoolLiteralExpr *makeObjCBool(bool Val);<br>
<br>
@@ -78,6 +102,18 @@ public:<br>
   /// Create a Return statement.<br>
   ReturnStmt *makeReturn(const Expr *RetVal);<br>
<br>
+  /// Create an integer literal.<br>
+  IntegerLiteral *makeIntegerLiteral(uint64_t value);<br>
+<br>
+  /// Create a member expression.<br>
+  MemberExpr *makeMemberExpression(Expr *base, ValueDecl *MemberDecl,<br>
+                                   bool IsArrow = false,<br>
+                                   ExprValueKind ValueKind = VK_LValue);<br>
+<br>
+  /// Returns a *first* member field of a record declaration with a given name.<br>
+  /// \return an nullptr if no member with such a name exists.<br>
+  NamedDecl *findMemberField(const CXXRecordDecl *RD, StringRef Name);<br>
+<br>
 private:<br>
   ASTContext &C;<br>
 };<br>
@@ -106,16 +142,16 @@ CompoundStmt *ASTMaker::makeCompound(Arr<br>
   return new (C) CompoundStmt(C, Stmts, SourceLocation(), SourceLocation());<br>
 }<br>
<br>
-DeclRefExpr *ASTMaker::makeDeclRefExpr(con<wbr>st VarDecl *D) {<br>
-  DeclRefExpr *DR =<br>
-    DeclRefExpr::Create(/* Ctx = */ C,<br>
-                        /* QualifierLoc = */ NestedNameSpecifierLoc(),<br>
-                        /* TemplateKWLoc = */ SourceLocation(),<br>
-                        /* D = */ const_cast<VarDecl*>(D),<br>
-                        /* RefersToEnclosingVariableOrCap<wbr>ture = */ false,<br>
-                        /* NameLoc = */ SourceLocation(),<br>
-                        /* T = */ D->getType(),<br>
-                        /* VK = */ VK_LValue);<br>
+DeclRefExpr *ASTMaker::makeDeclRefExpr(con<wbr>st VarDecl *D,<br>
+                                       bool RefersToEnclosingVariableOrCap<wbr>ture,<br>
+                                       bool GetNonReferenceType) {<br>
+  auto Type = D->getType();<br>
+  if (GetNonReferenceType)<br>
+    Type = Type.getNonReferenceType();<br>
+<br>
+  DeclRefExpr *DR = DeclRefExpr::Create(<br>
+      C, NestedNameSpecifierLoc(), SourceLocation(), const_cast<VarDecl *>(D),<br>
+      RefersToEnclosingVariableOrCap<wbr>ture, SourceLocation(), Type, VK_LValue);<br>
   return DR;<br>
 }<br>
<br>
@@ -125,8 +161,38 @@ UnaryOperator *ASTMaker::makeDereference<br>
 }<br>
<br>
 ImplicitCastExpr *ASTMaker::makeLvalueToRvalue(<wbr>const Expr *Arg, QualType Ty) {<br>
-  return ImplicitCastExpr::Create(C, Ty, CK_LValueToRValue,<br>
-                                  const_cast<Expr*>(Arg), nullptr, VK_RValue);<br>
+  return makeImplicitCast(Arg, Ty, CK_LValueToRValue);<br>
+}<br>
+<br>
+ImplicitCastExpr *ASTMaker::makeLvalueToRvalue(<wbr>const Expr *Arg,<br>
+                                               bool GetNonReferenceType) {<br>
+<br>
+  QualType Type = Arg->getType();<br>
+  if (GetNonReferenceType)<br>
+    Type = Type.getNonReferenceType();<br>
+  return makeImplicitCast(Arg, Type, CK_LValueToRValue);<br>
+}<br>
+<br>
+ImplicitCastExpr *<br>
+ASTMaker::makeLvalueToRvalue(<wbr>const VarDecl *Arg,<br>
+                             bool RefersToEnclosingVariableOrCap<wbr>ture,<br>
+                             bool GetNonReferenceType) {<br>
+  auto Type = Arg->getType();<br>
+  if (GetNonReferenceType)<br>
+    Type = Type.getNonReferenceType();<br>
+  return makeLvalueToRvalue(makeDeclRef<wbr>Expr(Arg,<br>
+                                            RefersToEnclosingVariableOrCap<wbr>ture,<br>
+                                            GetNonReferenceType),<br>
+                            Type);<br>
+}<br>
+<br>
+ImplicitCastExpr *ASTMaker::makeImplicitCast(co<wbr>nst Expr *Arg, QualType Ty,<br>
+                                             CastKind CK) {<br>
+  return ImplicitCastExpr::Create(C, Ty,<br>
+                                  /* CastKind= */ CK,<br>
+                                  /* Expr= */ const_cast<Expr *>(Arg),<br>
+                                  /* CXXCastPath= */ nullptr,<br>
+                                  /* ExprValueKind= */ VK_RValue);<br>
 }<br>
<br>
 Expr *ASTMaker::makeIntegralCast(co<wbr>nst Expr *Arg, QualType Ty) {<br>
@@ -161,12 +227,196 @@ ReturnStmt *ASTMaker::makeReturn(const E<br>
                             nullptr);<br>
 }<br>
<br>
+IntegerLiteral *ASTMaker::makeIntegerLiteral(<wbr>uint64_t value) {<br>
+  return IntegerLiteral::Create(C,<br>
+                                llvm::APInt(<br>
+                                    /*numBits=*/C.getTypeSize(C.In<wbr>tTy), value),<br>
+                                /*QualType=*/C.IntTy, SourceLocation());<br>
+}<br>
+<br>
+MemberExpr *ASTMaker::makeMemberExpressio<wbr>n(Expr *base, ValueDecl *MemberDecl,<br>
+                                           bool IsArrow,<br>
+                                           ExprValueKind ValueKind) {<br>
+<br>
+  DeclAccessPair FoundDecl = DeclAccessPair::make(MemberDec<wbr>l, AS_public);<br>
+  return MemberExpr::Create(<br>
+      C, base, IsArrow, SourceLocation(), NestedNameSpecifierLoc(),<br>
+      SourceLocation(), MemberDecl, FoundDecl,<br>
+      DeclarationNameInfo(MemberDecl<wbr>->getDeclName(), SourceLocation()),<br>
+      /* TemplateArgumentListInfo= */ nullptr, MemberDecl->getType(), ValueKind,<br>
+      OK_Ordinary);<br>
+}<br>
+<br>
+NamedDecl *ASTMaker::findMemberField(con<wbr>st CXXRecordDecl *RD, StringRef Name) {<br>
+<br>
+  CXXBasePaths Paths(<br>
+      /* FindAmbiguities=*/false,<br>
+      /* RecordPaths=*/false,<br>
+      /* DetectVirtual= */ false);<br>
+  const IdentifierInfo &II = C.Idents.get(Name);<br>
+  DeclarationName DeclName = C.DeclarationNames.getIdentifi<wbr>er(&II);<br>
+<br>
+  DeclContextLookupResult Decls = RD->lookup(DeclName);<br>
+  for (NamedDecl *FoundDecl : Decls)<br>
+    if (!FoundDecl->getDeclContext()-<wbr>>isFunctionOrMethod())<br>
+      return FoundDecl;<br>
+<br>
+  return nullptr;<br>
+}<br>
+<br>
 //===------------------------<wbr>------------------------------<wbr>----------------===//<br>
 // Creation functions for faux ASTs.<br>
 //===------------------------<wbr>------------------------------<wbr>----------------===//<br>
<br>
 typedef Stmt *(*FunctionFarmer)(ASTContext &C, const FunctionDecl *D);<br>
<br>
+static CallExpr *<br>
+create_call_once_funcptr_call<wbr>(ASTContext &C, ASTMaker M,<br>
+                              const ParmVarDecl *Callback,<br>
+                              SmallVectorImpl<Expr *> &CallArgs) {<br>
+<br>
+  return new (C) CallExpr(<br>
+      /*ASTContext=*/C,<br>
+      /*StmtClass=*/M.makeLvalueToRv<wbr>alue(/*Expr=*/Callback),<br>
+      /*args=*/CallArgs,<br>
+      /*QualType=*/C.VoidTy,<br>
+      /*ExprValueType=*/VK_RValue,<br>
+      /*SourceLocation=*/SourceLocat<wbr>ion());<br>
+}<br>
+<br>
+static CallExpr *<br>
+create_call_once_lambda_call(<wbr>ASTContext &C, ASTMaker M,<br>
+                             const ParmVarDecl *Callback, QualType CallbackType,<br>
+                             SmallVectorImpl<Expr *> &CallArgs) {<br>
+<br>
+  CXXRecordDecl *CallbackDecl = CallbackType->getAsCXXRecordDe<wbr>cl();<br>
+<br>
+  assert(CallbackDecl != nullptr);<br>
+  assert(CallbackDecl->isLambda(<wbr>));<br>
+  FunctionDecl *callOperatorDecl = CallbackDecl->getLambdaCallOpe<wbr>rator();<br>
+  assert(callOperatorDecl != nullptr);<br>
+<br>
+  DeclRefExpr *callOperatorDeclRef =<br>
+      DeclRefExpr::Create(/* Ctx = */ C,<br>
+                          /* QualifierLoc = */ NestedNameSpecifierLoc(),<br>
+                          /* TemplateKWLoc = */ SourceLocation(),<br>
+                          const_cast<FunctionDecl *>(callOperatorDecl),<br>
+                          /* RefersToEnclosingVariableOrCap<wbr>ture= */ false,<br>
+                          /* NameLoc = */ SourceLocation(),<br>
+                          /* T = */ callOperatorDecl->getType(),<br>
+                          /* VK = */ VK_LValue);<br>
+<br>
+  CallArgs.insert(<br>
+      CallArgs.begin(),<br>
+      M.makeDeclRefExpr(Callback,<br>
+                        /* RefersToEnclosingVariableOrCap<wbr>ture= */ true,<br>
+                        /* GetNonReferenceType= */ true));<br>
+<br>
+  return new (C)<br>
+      CXXOperatorCallExpr(/*AstConte<wbr>xt=*/C, OO_Call, callOperatorDeclRef,<br>
+                          /*args=*/CallArgs,<br>
+                          /*QualType=*/C.VoidTy,<br>
+                          /*ExprValueType=*/VK_RValue,<br>
+                          /*SourceLocation=*/SourceLocat<wbr>ion(), FPOptions());<br>
+}<br>
+<br>
+/// Create a fake body for std::call_once.<br>
+/// Emulates the following function body:<br>
+///<br>
+/// \code<br>
+/// typedef struct once_flag_s {<br>
+///   unsigned long __state = 0;<br>
+/// } once_flag;<br>
+/// template<class Callable><br>
+/// void call_once(once_flag& o, Callable func) {<br>
+///   if (!o.__state) {<br>
+///     func();<br>
+///   }<br>
+///   o.__state = 1;<br>
+/// }<br>
+/// \endcode<br>
+static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) {<br>
+  DEBUG(llvm::dbgs() << "Generating body for call_once\n");<br>
+<br>
+  // We need at least two parameters.<br>
+  if (D->param_size() < 2)<br>
+    return nullptr;<br>
+<br>
+  ASTMaker M(C);<br>
+<br>
+  const ParmVarDecl *Flag = D->getParamDecl(0);<br>
+  const ParmVarDecl *Callback = D->getParamDecl(1);<br>
+  QualType CallbackType = Callback->getType().getNonRefe<wbr>renceType();<br>
+<br>
+  SmallVector<Expr *, 5> CallArgs;<br>
+<br>
+  // All arguments past first two ones are passed to the callback.<br>
+  for (unsigned int i = 2; i < D->getNumParams(); i++)<br>
+    CallArgs.push_back(M.makeLvalu<wbr>eToRvalue(D->getParamDecl(i)))<wbr>;<br>
+<br>
+  CallExpr *CallbackCall;<br>
+  if (CallbackType->getAsCXXRecordD<wbr>ecl() &&<br>
+      CallbackType->getAsCXXRecordDe<wbr>cl()->isLambda()) {<br>
+<br>
+    CallbackCall =<br>
+        create_call_once_lambda_call(C<wbr>, M, Callback, CallbackType, CallArgs);<br>
+  } else {<br>
+<br>
+    // Function pointer case.<br>
+    CallbackCall = create_call_once_funcptr_call(<wbr>C, M, Callback, CallArgs);<br>
+  }<br>
+<br>
+  QualType FlagType = Flag->getType().getNonReferenc<wbr>eType();<br>
+  DeclRefExpr *FlagDecl =<br>
+      M.makeDeclRefExpr(Flag,<br>
+                        /* RefersToEnclosingVariableOrCap<wbr>ture=*/true,<br>
+                        /* GetNonReferenceType=*/true);<br>
+<br>
+  CXXRecordDecl *FlagCXXDecl = FlagType->getAsCXXRecordDecl()<wbr>;<br>
+<br>
+  // Note: here we are assuming libc++ implementation of call_once,<br>
+  // which has a struct with a field `__state_`.<br>
+  // Body farming might not work for other `call_once` implementations.<br>
+  NamedDecl *FoundDecl = M.findMemberField(FlagCXXDecl, "__state_");<br>
+  ValueDecl *FieldDecl;<br>
+  if (FoundDecl) {<br>
+    FieldDecl = dyn_cast<ValueDecl>(FoundDecl)<wbr>;<br>
+  } else {<br>
+    DEBUG(llvm::dbgs() << "No field __state_ found on std::once_flag struct, "<br>
+                       << "unable to synthesize call_once body, ignoring "<br>
+                       << "the call.\n");<br>
+    return nullptr;<br>
+  }<br>
+<br>
+  MemberExpr *Deref = M.makeMemberExpression(FlagDec<wbr>l, FieldDecl);<br>
+  assert(Deref->isLValue());<br>
+  QualType DerefType = Deref->getType();<br>
+<br>
+  // Negation predicate.<br>
+  UnaryOperator *FlagCheck = new (C) UnaryOperator(<br>
+      /* input= */<br>
+      M.makeImplicitCast(M.makeLvalu<wbr>eToRvalue(Deref, DerefType), DerefType,<br>
+                         CK_IntegralToBoolean),<br>
+      /* opc= */ UO_LNot,<br>
+      /* QualType= */ C.IntTy,<br>
+      /* ExprValueKind= */ VK_RValue,<br>
+      /* ExprObjectKind= */ OK_Ordinary, SourceLocation());<br>
+<br>
+  // Create assignment.<br>
+  BinaryOperator *FlagAssignment = M.makeAssignment(<br>
+      Deref, M.makeIntegralCast(M.makeInteg<wbr>erLiteral(1), DerefType), DerefType);<br>
+<br>
+  IfStmt *Out = new (C)<br>
+      IfStmt(C, SourceLocation(),<br>
+             /* IsConstexpr= */ false,<br>
+             /* init= */ nullptr,<br>
+             /* var= */ nullptr,<br>
+             /* cond= */ FlagCheck,<br>
+             /* then= */ M.makeCompound({CallbackCall, FlagAssignment}));<br>
+<br>
+  return Out;<br>
+}<br>
+<br>
 /// Create a fake body for dispatch_once.<br>
 static Stmt *create_dispatch_once(ASTConte<wbr>xt &C, const FunctionDecl *D) {<br>
   // Check if we have at least two parameters.<br>
@@ -202,15 +452,17 @@ static Stmt *create_dispatch_once(ASTCon<br>
   ASTMaker M(C);<br>
<br>
   // (1) Create the call.<br>
-  DeclRefExpr *DR = M.makeDeclRefExpr(Block);<br>
-  ImplicitCastExpr *ICE = M.makeLvalueToRvalue(DR, Ty);<br>
-  CallExpr *CE = new (C) CallExpr(C, ICE, None, C.VoidTy, VK_RValue,<br>
-                                  SourceLocation());<br>
+  CallExpr *CE = new (C) CallExpr(<br>
+      /*ASTContext=*/C,<br>
+      /*StmtClass=*/M.makeLvalueToRv<wbr>alue(/*Expr=*/Block),<br>
+      /*args=*/None,<br>
+      /*QualType=*/C.VoidTy,<br>
+      /*ExprValueType=*/VK_RValue,<br>
+      /*SourceLocation=*/SourceLocat<wbr>ion());<br>
<br>
   // (2) Create the assignment to the predicate.<br>
-  IntegerLiteral *IL =<br>
-    IntegerLiteral::Create(C, llvm::APInt(C.getTypeSize(C.In<wbr>tTy), (uint64_t) 1),<br>
-                           C.IntTy, SourceLocation());<br>
+  IntegerLiteral *IL = M.makeIntegerLiteral(1);<br>
+<br>
   BinaryOperator *B =<br>
     M.makeAssignment(<br>
        M.makeDereference(<br>
@@ -234,13 +486,20 @@ static Stmt *create_dispatch_once(ASTCon<br>
         PredicateTy),<br>
     PredicateTy);<br>
<br>
-  UnaryOperator *UO = new (C) UnaryOperator(LValToRval, UO_LNot, C.IntTy,<br>
-                                           VK_RValue, OK_Ordinary,<br>
-                                           SourceLocation());<br>
+  UnaryOperator *UO = new (C) UnaryOperator(<br>
+      /* input= */ LValToRval,<br>
+      /* opc= */ UO_LNot,<br>
+      /* QualType= */ C.IntTy,<br>
+      /* ExprValueKind= */ VK_RValue,<br>
+      /* ExprObjectKind= */ OK_Ordinary, SourceLocation());<br>
<br>
   // (5) Create the 'if' statement.<br>
-  IfStmt *If = new (C) IfStmt(C, SourceLocation(), false, nullptr, nullptr,<br>
-                              UO, CS);<br>
+  IfStmt *If = new (C) IfStmt(C, SourceLocation(),<br>
+                              /* IsConstexpr= */ false,<br>
+                              /* init= */ nullptr,<br>
+                              /* var= */ nullptr,<br>
+                              /* cond= */ UO,<br>
+                              /* then= */ CS);<br>
   return If;<br>
 }<br>
<br>
@@ -370,8 +629,9 @@ Stmt *BodyFarm::getBody(const FunctionDe<br>
   if (Name.startswith("OSAtomicComp<wbr>areAndSwap") ||<br>
       Name.startswith("objc_atomicC<wbr>ompareAndSwap")) {<br>
     FF = create_OSAtomicCompareAndSwap;<br>
-  }<br>
-  else {<br>
+  } else if (Name == "call_once" && D->getDeclContext()->isStdName<wbr>space()) {<br>
+    FF = create_call_once;<br>
+  } else {<br>
     FF = llvm::StringSwitch<FunctionFar<wbr>mer>(Name)<br>
           .Case("dispatch_sync", create_dispatch_sync)<br>
           .Case("dispatch_once", create_dispatch_once)<br>
<br>
Added: cfe/trunk/test/Analysis/call_o<wbr>nce.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/call_once.cpp?rev=314571&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/test/Analysis/<wbr>call_once.cpp?rev=314571&view=<wbr>auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/Analysis/call_o<wbr>nce.cpp (added)<br>
+++ cfe/trunk/test/Analysis/call_o<wbr>nce.cpp Fri Sep 29 17:03:22 2017<br>
@@ -0,0 +1,233 @@<br>
+// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.E<wbr>xprInspection -w -verify %s<br>
+<br>
+void clang_analyzer_eval(bool);<br>
+<br>
+// Faking std::std::call_once implementation.<br>
+namespace std {<br>
+typedef struct once_flag_s {<br>
+  unsigned long __state_ = 0;<br>
+} once_flag;<br>
+<br>
+template <class Callable, class... Args><br>
+void call_once(once_flag &o, Callable func, Args... args);<br>
+} // namespace std<br>
+<br>
+// Check with Lambdas.<br>
+void test_called_warning() {<br>
+  std::once_flag g_initialize;<br>
+  int z;<br>
+<br>
+  std::call_once(g_initialize, [&] {<br>
+    int *x = nullptr;<br>
+    int y = *x; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}<br>
+    z = 200;<br>
+  });<br>
+}<br>
+<br>
+void test_called_on_path_inside_no_<wbr>warning() {<br>
+  std::once_flag g_initialize;<br>
+<br>
+  int *x = nullptr;<br>
+  int y = 100;<br>
+  int z;<br>
+<br>
+  std::call_once(g_initialize, [&] {<br>
+    z = 200;<br>
+    x = &z;<br>
+  });<br>
+<br>
+  *x = 100; // no-warning<br>
+  clang_analyzer_eval(z == 100); // expected-warning{{TRUE}}<br>
+}<br>
+<br>
+void test_called_on_path_no_warning<wbr>() {<br>
+  std::once_flag g_initialize;<br>
+<br>
+  int *x = nullptr;<br>
+  int y = 100;<br>
+<br>
+  std::call_once(g_initialize, [&] {<br>
+    x = &y;<br>
+  });<br>
+<br>
+  *x = 100; // no-warning<br>
+}<br>
+<br>
+void test_called_on_path_warning() {<br>
+  std::once_flag g_initialize;<br>
+<br>
+  int y = 100;<br>
+  int *x = &y;<br>
+<br>
+  std::call_once(g_initialize, [&] {<br>
+    x = nullptr;<br>
+  });<br>
+<br>
+  *x = 100; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}<br>
+}<br>
+<br>
+void test_called_once_warning() {<br>
+  std::once_flag g_initialize;<br>
+<br>
+  int *x = nullptr;<br>
+  int y = 100;<br>
+<br>
+  std::call_once(g_initialize, [&] {<br>
+    x = nullptr;<br>
+  });<br>
+<br>
+  std::call_once(g_initialize, [&] {<br>
+    x = &y;<br>
+  });<br>
+<br>
+  *x = 100; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}<br>
+}<br>
+<br>
+void test_called_once_no_warning() {<br>
+  std::once_flag g_initialize;<br>
+<br>
+  int *x = nullptr;<br>
+  int y = 100;<br>
+<br>
+  std::call_once(g_initialize, [&] {<br>
+    x = &y;<br>
+  });<br>
+<br>
+  std::call_once(g_initialize, [&] {<br>
+    x = nullptr;<br>
+  });<br>
+<br>
+  *x = 100; // no-warning<br>
+}<br>
+<br>
+static int global = 0;<br>
+void funcPointer() {<br>
+  global = 1;<br>
+}<br>
+<br>
+void test_func_pointers() {<br>
+  static std::once_flag flag;<br>
+  std::call_once(flag, &funcPointer);<br>
+  clang_analyzer_eval(global == 1); // expected-warning{{TRUE}}<br>
+}<br>
+<br>
+template <class _Fp><br>
+class function; // undefined<br>
+template <class _Rp, class... _ArgTypes><br>
+struct function<_Rp(_ArgTypes...)> {<br>
+  _Rp operator()(_ArgTypes...) const;<br>
+  template <class _Fp><br>
+  function(_Fp);<br>
+};<br>
+<br>
+// Note: currently we do not support calls to std::function,<br>
+// but the analyzer should not crash either.<br>
+void test_function_objects_warning(<wbr>) {<br>
+  int x = 0;<br>
+  int *y = &x;<br>
+<br>
+  std::once_flag flag;<br>
+<br>
+  function<void()> func = [&]() {<br>
+    y = nullptr;<br>
+  };<br>
+<br>
+  std::call_once(flag, func);<br>
+<br>
+  func();<br>
+  int z = *y;<br>
+}<br>
+<br>
+void test_param_passing_lambda() {<br>
+  std::once_flag flag;<br>
+  int x = 120;<br>
+  int y = 0;<br>
+<br>
+  std::call_once(flag, [&](int p) {<br>
+    y = p;<br>
+  },<br>
+                 x);<br>
+<br>
+  clang_analyzer_eval(y == 120); // expected-warning{{TRUE}}<br>
+}<br>
+<br>
+void test_param_passing_lambda_fals<wbr>e() {<br>
+  std::once_flag flag;<br>
+  int x = 120;<br>
+<br>
+  std::call_once(flag, [&](int p) {<br>
+    x = 0;<br>
+  },<br>
+                 x);<br>
+<br>
+  clang_analyzer_eval(x == 120); // expected-warning{{FALSE}}<br>
+}<br>
+<br>
+void test_param_passing_stored_lamb<wbr>da() {<br>
+  std::once_flag flag;<br>
+  int x = 120;<br>
+  int y = 0;<br>
+<br>
+  auto lambda = [&](int p) {<br>
+    y = p;<br>
+  };<br>
+<br>
+  std::call_once(flag, lambda, x);<br>
+  clang_analyzer_eval(y == 120); // expected-warning{{TRUE}}<br>
+}<br>
+<br>
+void test_multiparam_passing_lambda<wbr>() {<br>
+  std::once_flag flag;<br>
+  int x = 120;<br>
+<br>
+  std::call_once(flag, [&](int a, int b, int c) {<br>
+    x = a + b + c;<br>
+  },<br>
+                 1, 2, 3);<br>
+<br>
+  clang_analyzer_eval(x == 120); // expected-warning{{FALSE}}<br>
+  clang_analyzer_eval(x == 6); // expected-warning{{TRUE}}<br>
+}<br>
+<br>
+static int global2 = 0;<br>
+void test_param_passing_lambda_glob<wbr>al() {<br>
+  std::once_flag flag;<br>
+  global2 = 0;<br>
+  std::call_once(flag, [&](int a, int b, int c) {<br>
+    global2 = a + b + c;<br>
+  },<br>
+                 1, 2, 3);<br>
+  clang_analyzer_eval(global2 == 6); // expected-warning{{TRUE}}<br>
+}<br>
+<br>
+static int global3 = 0;<br>
+void funcptr(int a, int b, int c) {<br>
+  global3 = a + b + c;<br>
+}<br>
+<br>
+void test_param_passing_funcptr() {<br>
+  std::once_flag flag;<br>
+  global3 = 0;<br>
+<br>
+  std::call_once(flag, &funcptr, 1, 2, 3);<br>
+<br>
+  clang_analyzer_eval(global3 == 6); // expected-warning{{TRUE}}<br>
+}<br>
+<br>
+void test_blocks() {<br>
+  global3 = 0;<br>
+  std::once_flag flag;<br>
+  std::call_once(flag, ^{<br>
+    global3 = 120;<br>
+  });<br>
+  clang_analyzer_eval(global3 == 120); // expected-warning{{TRUE}}<br>
+}<br>
+<br>
+int call_once() {<br>
+  return 5;<br>
+}<br>
+<br>
+void test_non_std_call_once() {<br>
+  int x = call_once();<br>
+  clang_analyzer_eval(x == 5); // expected-warning{{TRUE}}<br>
+}<br>
<br>
<br>
______________________________<wbr>_________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>
</div></div></blockquote></div><br></div>