Skip to content

Commit

Permalink
[Analyzer] Handle implicit function reference in bodyfarming std::cal…
Browse files Browse the repository at this point in the history
…l_once

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

llvm-svn: 316402
  • Loading branch information
George Karpenkov committed Oct 24, 2017
1 parent 619b326 commit 98e81cd
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 8 deletions.
28 changes: 20 additions & 8 deletions clang/lib/Analysis/BodyFarm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -253,13 +253,23 @@ static CallExpr *create_call_once_funcptr_call(ASTContext &C, ASTMaker M,
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,
Expand Down Expand Up @@ -366,9 +376,11 @@ static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) {
CallbackFunctionType = CallbackRecordDecl->getLambdaCallOperator()
->getType()
->getAs<FunctionProtoType>();
} else {
} else if (!CallbackType->getPointeeType().isNull()) {
CallbackFunctionType =
CallbackType->getPointeeType()->getAs<FunctionProtoType>();
} else {
CallbackFunctionType = CallbackType->getAs<FunctionProtoType>();
}

if (!CallbackFunctionType)
Expand Down
13 changes: 13 additions & 0 deletions clang/test/Analysis/call_once.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 &param) {
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}}
}

0 comments on commit 98e81cd

Please sign in to comment.