6

I'm using clang-tidy 10 on a project and it's behaving weirdly on Windows with the MSVC STL. A minimal example is the following:

#include <iostream>
#include <stdexcept>

int main()
{
    try {
        throw std::runtime_error {"Boom!"};
    } catch (...) {
        std::cerr << "Unexpected non-exception error!\n";
    }
}

If I tell it to include the check bugprone-exception-escape, it tells me an exception may be thrown in function 'main'. However, if I change the line streaming to std::cerr with the following then the check does not cause a complaint:

std::cerr << "Unexpected non-exception error!\n" << std::flush;

I assume the two consecutive stream operations in one statement is the cause of the different behaviour, because the following does raise the problem.

std::cerr << "Unexpected non-exception error!\n";
std::cerr << std::flush;

I noticed clang-tidy does not complain on any of these examples on Linux, at least if I pass -stdlib=libc++. Is there some weird subtlety I'm missing, or is this a bug in clang-tidy and/or MSVC's STL implementation?

1 Answers1

1

I can't say for certain, but this seems very likely to be a bug. There have already been two similar bug reports/issues raised: https://github.com/llvm/llvm-project/issues/54668 and https://github.com/llvm/llvm-project/issues/56411. The first one already has a patch created to fix it (at the time of writing it's still under review though).

My guess is that a piping a single string literal to cerr somehow result in a string move, triggering the bug reported in the first issue I linked. There may be some kind of optimization where it's trying to move the string directly into the buffer, and using the returned ostream to perform another operation somehow prevents that optimization.

Alternatively, it's another case of the underlying issue causing the problem with the string move. i.e. There's a throw in a function several calls deep, but one of those calls is declared noexcept, and so the diagnostic shouldn't propagate further up.

Daniel McIntosh
  • 522
  • 3
  • 17
  • The general idea sounds plausible, although I'd be very surprised if a string move somehow got involved since I see no good reason for a string to be constructed at all here. But iostreams is very complicated so I can buy there being a reason, plus the general issue with noexcept calls sounds very realistic as the source of the problem. – Raymond Wright Oct 01 '22 at 12:17