Author: george.karpenkov Date: Mon Oct 23 17:13:18 2017 New Revision: 316402
URL: http://llvm.org/viewvc/llvm-project?rev=316402&view=rev Log: [Analyzer] Handle implicit function reference in bodyfarming std::call_once Differential Revision: https://reviews.llvm.org/D39201 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=316402&r1=316401&r2=316402&view=diff ============================================================================== --- cfe/trunk/lib/Analysis/BodyFarm.cpp (original) +++ cfe/trunk/lib/Analysis/BodyFarm.cpp Mon Oct 23 17:13:18 2017 @@ -253,13 +253,23 @@ static CallExpr *create_call_once_funcpt const ParmVarDecl *Callback, ArrayRef<Expr *> CallArgs) { - return new (C) CallExpr( - /*ASTContext=*/C, - /*StmtClass=*/M.makeLvalueToRvalue(/*Expr=*/Callback), - /*args=*/CallArgs, - /*QualType=*/C.VoidTy, - /*ExprValueType=*/VK_RValue, - /*SourceLocation=*/SourceLocation()); + QualType Ty = Callback->getType(); + DeclRefExpr *Call = M.makeDeclRefExpr(Callback); + CastKind CK; + if (Ty->isRValueReferenceType()) { + CK = CK_LValueToRValue; + } else { + assert(Ty->isLValueReferenceType()); + CK = CK_FunctionToPointerDecay; + Ty = C.getPointerType(Ty.getNonReferenceType()); + } + + return new (C) + CallExpr(C, M.makeImplicitCast(Call, Ty.getNonReferenceType(), CK), + /*args=*/CallArgs, + /*QualType=*/C.VoidTy, + /*ExprValueType=*/VK_RValue, + /*SourceLocation=*/SourceLocation()); } static CallExpr *create_call_once_lambda_call(ASTContext &C, ASTMaker M, @@ -366,9 +376,11 @@ static Stmt *create_call_once(ASTContext CallbackFunctionType = CallbackRecordDecl->getLambdaCallOperator() ->getType() ->getAs<FunctionProtoType>(); - } else { + } else if (!CallbackType->getPointeeType().isNull()) { CallbackFunctionType = CallbackType->getPointeeType()->getAs<FunctionProtoType>(); + } else { + CallbackFunctionType = CallbackType->getAs<FunctionProtoType>(); } if (!CallbackFunctionType) Modified: cfe/trunk/test/Analysis/call_once.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/call_once.cpp?rev=316402&r1=316401&r2=316402&view=diff ============================================================================== --- cfe/trunk/test/Analysis/call_once.cpp (original) +++ cfe/trunk/test/Analysis/call_once.cpp Mon Oct 23 17:13:18 2017 @@ -290,3 +290,16 @@ void test_mutator_noref() { std::call_once(flag, &fail_mutator, a); clang_analyzer_eval(a == 42); // expected-warning{{FALSE}} } + +// Function is implicitly treated as a function pointer +// even when an ampersand is not explicitly set. +void callbackn(int ¶m) { + param = 42; +}; +void test_implicit_funcptr() { + int x = 0; + static std::once_flag flagn; + + std::call_once(flagn, callbackn, x); + clang_analyzer_eval(x == 42); // expected-warning{{TRUE}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits