Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The code below, is it ill-formed NDR or is it well formed?

Clang accepts the following code, but gcc rejects it.

void h() { }

constexpr int f() {
    return 1;
    h();
}

int main() {
    constexpr int i = f();
}

Here is the error message:

g++ -std=c++17 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
main.cpp: In function 'constexpr int f()':
main.cpp:5:6: error: call to non-'constexpr' function 'void h()'
     h();
     ~^~
main.cpp: In function 'int main()':
main.cpp:9:24: error: 'constexpr int f()' called in a constant expression
     constexpr int i = f();
                       ~^~
main.cpp:9:19: warning: unused variable 'i' [-Wunused-variable]
     constexpr int i = f();

This could well be the case where both compilers are correct, once we consider [dcl.constexpr]/5, given that f() is not a constant expression, as it doesn't satisfy [expr.const]/(4.2), as it calls a non-constexpr function h. That is, the code is ill-formed, but no diagnostic is required.

One other possibility is that the code is well formed, as [expr.const]/(4.2) doesn't apply in this case because the call to h in f is not evaluated. If this is the case, gcc is wrong and clang is correct.

like image 752
Alexander Avatar asked Apr 18 '19 18:04

Alexander


1 Answers

Clang is correct. A call to f() is a constant expression since the call to h() is never evaluated, so [dcl.constexpr]/5 doesn't apply. The call to h() in the body of f() is not ill-formed because the constraints on constexpr functions don't say anything about not being allowed to call non-constexpr functions. Indeed, a function like the following is well-formed because a call to it can be a constant expression when x is odd:

constexpr int g(int x) {
    if (x%2 == 0) h();
    return 0;
}
like image 200
Brian Bi Avatar answered Oct 20 '22 11:10

Brian Bi