Summary:
:
There are throw wrapper functions like `std::__throw_bad_alloc()` defined in both libstdc++ (https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/functexcept.h) and libc++ (e.g. 907c1196a7/include/new (L145)
). Folly actually exports some of them as well (diffusion/FBS/browse/master/fbcode/folly/portability/BitsFunctexcept.h). The function body of those wrappers merely throws the corresponding exception. My understanding is that the primary purpose of the wrappers is to throw the exception if everything goes well and to fall back to something reasonable when exception is disabled (e.g. when `-fno-exceptions` is passed to the compiler).
The problem is that infer doesn't really understand what those functions do, and I've seen some false positives get reported as a result of it. So to remove those FPs we need to either model them or handle them specially. Modeling those wrappers by either whitelisting them or overriding the include files turns out to be difficult, as those wrappers are only declared but not defined in the STL headers. Their implementations are not available to Infer so whitelisting them does nothing, and if I provide custom implementations in the headers then normal compilation process will be disrupted because the linker would complain about duplicated implementation.
What I did here is to replace functions whose name matches one of the throw wrapper's name with a `BuiltinDecls.exit`. I have to admit that this is a bit hacky: initially I was trying to do something more general: replacing functions with `noreturn` attribute with `BuitinDecls.exit`. That did not work because, CMIIW, the current frontend only exports function attributes for functions with actual bodies, not declaration-only functions. I'd love to be informed if there are better ways to handle those wrappers.
Reviewed By: jeremydubreil
Differential Revision: D5266030
fbshipit-source-id: 4580227
master
parent
62cfd554c7
commit
f7927cadda
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2017 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
#include <functional>
|
||||
#include <future>
|
||||
#include <ios>
|
||||
#include <new>
|
||||
#include <stdexcept>
|
||||
#include <typeinfo>
|
||||
|
||||
namespace std {
|
||||
|
||||
void __throw_bad_alloc() { throw bad_alloc(); }
|
||||
void __throw_bad_cast() { throw bad_cast(); }
|
||||
void __throw_bad_exception() { throw bad_exception(); }
|
||||
void __throw_bad_function_call() { throw bad_function_call(); }
|
||||
void __throw_bad_typeid() { throw bad_typeid(); }
|
||||
void __throw_domain_error(const char* s) { throw domain_error(s); }
|
||||
void __throw_invalid_argument(const char* s) { throw invalid_argument(s); }
|
||||
void __throw_ios_failure(const char* s) { throw ios_base::failure(s); }
|
||||
void __throw_length_error(const char* s) { throw length_error(s); }
|
||||
void __throw_logic_error(const char* s) { throw logic_error(s); }
|
||||
void __throw_out_of_range(const char* s) { throw out_of_range(s); }
|
||||
void __throw_overflow_error(const char* s) { throw overflow_error(s); }
|
||||
void __throw_range_error(const char* s) { throw range_error(s); }
|
||||
void __throw_runtime_error(const char* s) { throw runtime_error(s); }
|
||||
void __throw_system_error(int c) {
|
||||
throw system_error(error_code(c, generic_category()));
|
||||
}
|
||||
void __throw_underflow_error(const char* s) { throw underflow_error(s); }
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2017 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
// std::__throw_bad_alloc() is not a standarized function. It could be defined
|
||||
// in many places, so we need to consider all possibilities.
|
||||
#include <new>
|
||||
#include <stdexcept>
|
||||
|
||||
static int* get_null() { return nullptr; }
|
||||
|
||||
static void do_nothing() {}
|
||||
|
||||
int throw_if_null_ok() {
|
||||
int* p = get_null();
|
||||
if (p == nullptr)
|
||||
std::__throw_bad_alloc();
|
||||
return *p;
|
||||
}
|
||||
|
||||
int nothrow_if_null_bad() {
|
||||
int* p = get_null();
|
||||
if (p == nullptr)
|
||||
do_nothing();
|
||||
return *p;
|
||||
}
|
Loading…
Reference in new issue