I claim that this program ought to be well-formed: it declares a constexpr member function of S<int>. However, both GCC and Clang reject this program.
template<class T>
struct S {
    constexpr int foo() {
        if constexpr (std::is_same_v<T, int>) {
            return 0;
        } else {
            try {} catch (...) {}
            return 1;
        }
    }
};
int main()
{
    S<int> s;
    return s.foo();  // expect "return 0"
}
GCC says:
error: 'try' in 'constexpr' function
Clang says:
error: statement not allowed in constexpr function
Neither of them seem to notice that the "try" statement is located in a discarded branch of the if constexpr statement.
If I factor the try/catch out into a non-constexpr member function void trycatch(), then both Clang and GCC are happy with the code again, even though its behavior ought to be equivalent to the unhappy version.
template<class T>
struct S {
    void trycatch() {
        try {} catch (...) {}
    }
    constexpr int foo() {
        if constexpr (std::is_same_v<T, int>) {
            return 0;
        } else {
            trycatch();  // This is fine.
            return 1;
        }
    }
};
Is this
- a bug in both GCC and Clang?
 - a defect in the Standard, which GCC and Clang are faithfully implementing?
 - a Quality of Implementation issue due to the "conditional constexprness" of 
foo()? 
(Irrelevant background: I'm implementing constexpr any::emplace<T>() for an allocator-aware version of any whose allocator might be constexpr-per-P0639 (i.e. it might lack a deallocate member function) or might not. In the former case we don't want or need the try; in the latter case we need the try in order to call deallocate if the constructor of T throws.)