llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
29.09k stars 12k forks source link

`requires{ member_fn; }` within a member function is true, despite `member_fn;` being an error #51246

Open nyanpasu64 opened 3 years ago

nyanpasu64 commented 3 years ago
Bugzilla Link 51904
Version trunk
OS Linux
Attachments Test case for requires{} expressions
CC @zygoloid

Extended Description

If I define a class with a void member_fn() which contains requires{ member_fn; }, it evaluates to true on Clang but is an error on GCC, despite member_fn; being an error on both compilers.

If I define a template<typename T> Class : T instantiated with a T containing base_fn(), and Class contains a member function with requires{ T::base_fn; }, it evaluates to true on Clang but false on GCC, despite base_fn; being an error on both compilers.

Is this a Clang bug, or is my code ill-formed? I was using the value of requires{} as an input to if constexpr or static_assert, rather than as a concept or template bound; is this allowed?

I've attached a file testing whether requires{} in various positions is true, false, or an error to evaluate.

Quuxplusone commented 2 years ago

Good news: on your test cases, Clang's behavior almost entirely matches GCC's now. https://godbolt.org/z/c7Psxvcr8

The one remaining difference is when you use a requires-clause outside of any template, and the required expression is something ambiguous or overloaded, e.g.: https://godbolt.org/z/zW3r5eaah

void f();
void f(int);
static_assert(requires{ f; });  // Clang+MSVC accept; GCC hard-errors

struct S {
    void mf() {
        static_assert(requires{ mf; });  // Clang+MSVC accept; GCC hard-errors
        static_assert(requires{ S::mf; });  // Clang+MSVC accept; GCC hard-errors
    }
};

I'm inclined to think GCC is right, because every compiler agrees that an egregiously ill-formed expression like static_assert(!requires{ "x"*1; }); should produce a hard error, not a quiet false.