forked from OSchip/llvm-project
[analyzer] Fix yet-another-crash in body-farming std::call_once
Crash occurs when parameters to the callback and to std::call_once mismatch, and C++ is supposed to auto-construct an argument. Filed by Alexander Kornienko in https://bugs.llvm.org/show_bug.cgi?id=36149 rdar://37034403 Differential Revision: https://reviews.llvm.org/D42777 llvm-svn: 324046
This commit is contained in:
parent
844ccca577
commit
59202324a5
clang
|
@ -406,6 +406,16 @@ static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) {
|
||||||
// reference.
|
// reference.
|
||||||
for (unsigned int ParamIdx = 2; ParamIdx < D->getNumParams(); ParamIdx++) {
|
for (unsigned int ParamIdx = 2; ParamIdx < D->getNumParams(); ParamIdx++) {
|
||||||
const ParmVarDecl *PDecl = D->getParamDecl(ParamIdx);
|
const ParmVarDecl *PDecl = D->getParamDecl(ParamIdx);
|
||||||
|
if (PDecl &&
|
||||||
|
CallbackFunctionType->getParamType(ParamIdx - 2)
|
||||||
|
.getNonReferenceType()
|
||||||
|
.getCanonicalType() !=
|
||||||
|
PDecl->getType().getNonReferenceType().getCanonicalType()) {
|
||||||
|
DEBUG(llvm::dbgs() << "Types of params of the callback do not match "
|
||||||
|
<< "params passed to std::call_once, "
|
||||||
|
<< "ignoring the call\n");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
Expr *ParamExpr = M.makeDeclRefExpr(PDecl);
|
Expr *ParamExpr = M.makeDeclRefExpr(PDecl);
|
||||||
if (!CallbackFunctionType->getParamType(ParamIdx - 2)->isReferenceType()) {
|
if (!CallbackFunctionType->getParamType(ParamIdx - 2)->isReferenceType()) {
|
||||||
QualType PTy = PDecl->getType().getNonReferenceType();
|
QualType PTy = PDecl->getType().getNonReferenceType();
|
||||||
|
@ -816,4 +826,3 @@ Stmt *BodyFarm::getBody(const ObjCMethodDecl *D) {
|
||||||
|
|
||||||
return Val.getValue();
|
return Val.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,9 +9,26 @@
|
||||||
|
|
||||||
void clang_analyzer_eval(bool);
|
void clang_analyzer_eval(bool);
|
||||||
|
|
||||||
// Faking std::std::call_once implementation.
|
// Faking std::call_once implementation.
|
||||||
namespace std {
|
namespace std {
|
||||||
|
|
||||||
|
// Fake std::function implementation.
|
||||||
|
template <typename>
|
||||||
|
class function;
|
||||||
|
class function_base {
|
||||||
|
public:
|
||||||
|
long field;
|
||||||
|
};
|
||||||
|
template <typename R, typename... P>
|
||||||
|
class function<R(P...)> : function_base {
|
||||||
|
public:
|
||||||
|
R operator()(P...) const {
|
||||||
|
|
||||||
|
// Read from a super-class necessary to reproduce a crash.
|
||||||
|
bool a = field;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#ifndef EMULATE_LIBSTDCPP
|
#ifndef EMULATE_LIBSTDCPP
|
||||||
typedef struct once_flag_s {
|
typedef struct once_flag_s {
|
||||||
unsigned long __state_ = 0;
|
unsigned long __state_ = 0;
|
||||||
|
@ -360,3 +377,29 @@ void test_implicit_funcptr() {
|
||||||
clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
|
clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int param_passed(int *x) {
|
||||||
|
return *x; // no-warning, as std::function is not working yet.
|
||||||
|
}
|
||||||
|
|
||||||
|
void callback_taking_func_ok(std::function<void(int*)> &innerCallback) {
|
||||||
|
innerCallback(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The provided callback expects an std::function, but instead a pointer
|
||||||
|
// to a C++ function is provided.
|
||||||
|
void callback_with_implicit_cast_ok() {
|
||||||
|
std::once_flag flag;
|
||||||
|
call_once(flag, callback_taking_func_ok, ¶m_passed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void callback_taking_func(std::function<void()> &innerCallback) {
|
||||||
|
innerCallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
// The provided callback expects an std::function, but instead a C function
|
||||||
|
// name is provided, and C++ implicitly auto-constructs a pointer from it.
|
||||||
|
void callback_with_implicit_cast() {
|
||||||
|
std::once_flag flag;
|
||||||
|
call_once(flag, callback_taking_func, callback_with_implicit_cast);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue