[analyzer] Suppress reports reported in std::list

The motivation is to suppresses false use-after-free reports that occur when calling
std::list::pop_front() or std::list::pop_back() twice. The analyzer does not
reason about the internal invariants of the list implementation, so just do not report
any of warnings in std::list.

Fixes radar://14317928.

llvm-svn: 185609
This commit is contained in:
Anna Zaks 2013-07-04 02:38:10 +00:00
parent 5673b6567a
commit a42fb525e4
3 changed files with 46 additions and 8 deletions

View File

@ -1521,18 +1521,33 @@ LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC,
BugReport &BR) {
// Here we suppress false positives coming from system headers. This list is
// based on known issues.
// Skip reports within the 'std' namespace. Although these can sometimes be
// the user's fault, we currently don't report them very well, and
// Note that this will not help for any other data structure libraries, like
// TR1, Boost, or llvm/ADT.
ExprEngine &Eng = BRC.getBugReporter().getEngine();
AnalyzerOptions &Options = Eng.getAnalysisManager().options;
if (Options.shouldSuppressFromCXXStandardLibrary()) {
const LocationContext *LCtx = N->getLocationContext();
if (isInStdNamespace(LCtx->getDecl())) {
const Decl *D = N->getLocationContext()->getDecl();
if (isInStdNamespace(D)) {
// Skip reports within the 'std' namespace. Although these can sometimes be
// the user's fault, we currently don't report them very well, and
// Note that this will not help for any other data structure libraries, like
// TR1, Boost, or llvm/ADT.
if (Options.shouldSuppressFromCXXStandardLibrary()) {
BR.markInvalid(getTag(), 0);
return 0;
} else {
// If the the complete 'std' suppression is not enabled, suppress reports
// from the 'std' namespace that are known to produce false positives.
// The analyzer issues a false use-after-free when std::list::pop_front
// or std::list::pop_back are called multiple times because we cannot
// reason about the internal invariants of the datastructure.
const DeclContext *DC =
D->getDeclContext()->getEnclosingNamespaceContext();
const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC);
if (ND && ND->getName() == "list") {
BR.markInvalid(getTag(), 0);
return 0;
}
}
}

View File

@ -86,6 +86,23 @@ namespace std {
struct forward_iterator_tag : public input_iterator_tag { };
struct bidirectional_iterator_tag : public forward_iterator_tag { };
struct random_access_iterator_tag : public bidirectional_iterator_tag { };
template <class _Tp>
class allocator {};
template <class _Tp, class _Alloc>
class __list_imp
{};
template <class _Tp, class _Alloc = allocator<_Tp> >
class list
: private __list_imp<_Tp, _Alloc>
{
public:
void pop_front();
bool empty() const;
};
}
void* operator new(std::size_t, const std::nothrow_t&) throw();

View File

@ -27,3 +27,9 @@ void testException(std::exception e) {
// expected-warning@-4 {{UNKNOWN}}
#endif
}
void testList_pop_front(std::list<int> list) {
while(!list.empty())
list.pop_front(); // no-warning
}