Skip to content
This repository has been archived by the owner on Apr 23, 2020. It is now read-only.

Commit

Permalink
[analyzer] Do not crash on callback for call_once passed by value
Browse files Browse the repository at this point in the history
https://bugs.llvm.org/show_bug.cgi?id=37312
rdar://40270582

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

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@332422 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
George Karpenkov committed May 16, 2018
1 parent dd41a58 commit 925ba27
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 10 deletions.
23 changes: 13 additions & 10 deletions lib/Analysis/BodyFarm.cpp
Expand Up @@ -254,21 +254,24 @@ static CallExpr *create_call_once_funcptr_call(ASTContext &C, ASTMaker M,

QualType Ty = Callback->getType();
DeclRefExpr *Call = M.makeDeclRefExpr(Callback);
CastKind CK;
Expr *SubExpr;
if (Ty->isRValueReferenceType()) {
CK = CK_LValueToRValue;
} else {
assert(Ty->isLValueReferenceType());
CK = CK_FunctionToPointerDecay;
SubExpr = M.makeImplicitCast(
Call, Ty.getNonReferenceType(), CK_LValueToRValue);
} else if (Ty->isLValueReferenceType() &&
Call->getType()->isFunctionType()) {
Ty = C.getPointerType(Ty.getNonReferenceType());
SubExpr = M.makeImplicitCast(Call, Ty, CK_FunctionToPointerDecay);
} else if (Ty->isLValueReferenceType()
&& Call->getType()->isPointerType()
&& Call->getType()->getPointeeType()->isFunctionType()){
SubExpr = Call;
} else {
llvm_unreachable("Unexpected state");
}

return new (C)
CallExpr(C, M.makeImplicitCast(Call, Ty.getNonReferenceType(), CK),
/*args=*/CallArgs,
/*QualType=*/C.VoidTy,
/*ExprValueType=*/VK_RValue,
/*SourceLocation=*/SourceLocation());
CallExpr(C, SubExpr, CallArgs, C.VoidTy, VK_RValue, SourceLocation());
}

static CallExpr *create_call_once_lambda_call(ASTContext &C, ASTMaker M,
Expand Down
9 changes: 9 additions & 0 deletions test/Analysis/call_once.cpp
Expand Up @@ -403,3 +403,12 @@ void callback_with_implicit_cast() {
std::once_flag flag;
call_once(flag, callback_taking_func, callback_with_implicit_cast);
}

std::once_flag another_once_flag;
typedef void (*my_callback_t)(int *);
my_callback_t callback;
int global_int;

void rdar40270582() {
call_once(another_once_flag, callback, &global_int);
}

0 comments on commit 925ba27

Please sign in to comment.