constexpr int* ptr =&i compiles in msvc but not with clang and gcc
Asked Answered
W

2

3

I am learning about constexpr variables using the books listed here. In particular I read in C++ Primer that:

Variables declared constexpr are implicitly const and must be initialized with constant expressions.

Now, to further clear my concept and check if I understood the things correctly, I wrote the following simple program that compiles with msvc but not with gcc and clang: Demo

int main(void)
{
   int i = 0;
   constexpr int *ptr= &i; //compiles with msvc but not with clang and gcc 
}

So, my question is which compiler is right here(if any)?

Whitherward answered 15/10, 2022 at 15:12 Comment(3)
Looks like ill-formed.Hoppe
AFAIK only a pointer to a variable with static storage can be a constant expression. Nitty gritty details are here : en.cppreference.com/w/cpp/language/constant_expressionPsychomancy
The quoted definition makes it seem pretty clear that MSVC is wrong.Zela
H
2

The program is ill-formed and msvc is wrong in not giving a diagnostic(this has been fixed in latest version of msvc). This is because i is not an statically allocated object and so its address is not constant. Basically, since we can initialize a constexpr pointer only from either the nullptr literal or literal 0 or from an address of an object that has fixed address and in your example, i is not an object that has a fixed address so that &i is not a constant expression.

This can be seen from expr.const#11 which states:

A constant expression is either a glvalue core constant expression that refers to an entity that is a permitted result of a constant expression (as defined below), or a prvalue core constant expression whose value satisfies the following constraints:

  • if the value is of pointer type, it contains the address of an object with static storage duration, the address past the end of such an object ([expr.add]), the address of a non-immediate function, or a null pointer value,

An entity is a permitted result of a constant expression if it is an object with static storage duration that either is not a temporary object or is a temporary object whose value satisfies the above constraints, or if it is a non-immediate function.

(emphasis mine)

This means that there are two ways to solve the problem. First is that you can add static infront of i to make it a local static. The second is to move the definition of i to global scope outside the main function. In both cases(shown below), i will then have static storage duration so that &i will now be a constant expression according to the above quoted statement.


Method 1

int main()
{
//-vvvvvv------------->static added here so that i now has static storage duration
   static int i = 0;
   constexpr int *ptr= &i; //works now
   
}

Method 2

int i = 0;  //make i global so that i now has static storage duration  
int main()
{

   constexpr int *ptr= &i; //works now   
}

Here is the msvc bug report:

MSVC compiles invalid constexpr int*ptr= &i where i is a local nonstatic object

Hoppe answered 15/10, 2022 at 15:25 Comment(5)
Before reporting a new msvc bug, it should be confirmed by compiling with the flag /permissive-.Ergener
Yes, it's not a compiler bug but extension, and the bug report will likely be closed.Ergener
@273K The program doesn't give diagnostic with /permissive-. Demo. So, it seems to be a bug.Hoppe
@273K Even with the flag you suggested, we don't get any diagnostic. So this looks like a bug as said in this answer.Whitherward
It's an interesting case because main is not the usual function. It can't be called by another function and a side effect is that the address of local objects never differ. Still, a technical bug.Posturize
S
1

As of August 9 2023, this has been fixed and is no longer an issue. Update your compilers.

See: https://developercommunity.visualstudio.com/t/MSVC-compiles-invalid-constexpr-intptr/10173848 which points to https://developercommunity.visualstudio.com/t/Address-of-local-variable-should-not-be-/1142306

Selfgratification answered 11/1, 2024 at 17:6 Comment(3)
I don't think this answer adds anything to the already existing answer. The existing answer has a link to the bug reports and explains that this is a bug in msvc. Whether or not msvc has fixed this and which version fixed it, wasn't the question.Hoppe
@Hoppe It has a link to a bug report that is closed as a duplicate as well as it is not immediately clear to anyone who is reading the question or answers by themselves that it is no longer a problem.Selfgratification
Yes, but editing the already existing answer to replace the bug report with the original target and also adding it has been fixed now would have been more appropriate. The question is language-lawyered and clearly asks "which compiler is right here(if any)?". Also users can follow the bug report in the existing answer that points to the duplicate bug.Hoppe

© 2022 - 2025 — McMap. All rights reserved.