A constexpr function is defined as (c++14)
A constexpr function must satisfy the following requirements:
- it must not be virtual
- its return type must be LiteralType each of its parameters must be LiteralType
- there exists at least one set of argument values such that an invocation of the function could be an evaluated subexpression of a core constant expression (for constructors, use in a constant initializer is sufficient) (since C++14). No diagnostic is required for a violation of this bullet.
the function body must be either deleted or defaulted or contain any statements except:
- an asm declaration
- a goto statement
- a statement with a label other than case and default
- a try-block
- a definition of a variable of non-literal type
- a definition of a variable of static or thread storage duration
- a definition of a variable for which no initialization is performed.
Now following func1 meets the requirement and compiles
constexpr int * func1 (int a)
{
int b = 4;
return &b;
}
int main()
{
constexpr int * a = func1(3);
int arr[*a];
std::cout << a << std::endl;
}
Now my question is how come func1 is constexpr. How does it know address of local variable at compile time?
I am using gcc 6.4.0
How does it know address of local variable at compile time?
It doesn't.
The third bullet in your quote is never satisfied:
There exists at least one set of argument values such that an invocation of the function could be an evaluated subexpression of a core constant expression (for constructors, use in a constant initializer is sufficient) (since C++14). No diagnostic is required for a violation of this bullet.
The compiler just doesn't complain about it because it's not required to, until you make it complain by trying to use func1
inside something that requires a correct constexpr
function, for example:
std::array<int, func(3)> d;
This won't compile and your compiler will tell you why.
Now my question is how come func1 is constexpr.
Are you sure?
Try asking a compile time value saving it in a constexpr
variable; by example
constexpr int * a = func1(3);
You should get a list of error/warnings like (from my clang++ 3.8.1)
tmp_003-14,gcc,clang.cpp:7:11: warning: address of stack memory associated with
local variable 'b' returned [-Wreturn-stack-address]
return &b;
^
tmp_003-14,gcc,clang.cpp:11:21: error: constexpr variable 'a' must be
initialized by a constant expression
constexpr int * a = func1(3);
^ ~~~~~~~~
tmp_003-14,gcc,clang.cpp:11:21: note: pointer to 'b' is not a constant
expression
tmp_003-14,gcc,clang.cpp:6:7: note: declared here
int b = 4;
^
Well, actually, from my g++ 6.3.0 I get only a warning
tmp_003-14,gcc,clang.cpp: In function ‘constexpr int* func1(int)’:
tmp_003-14,gcc,clang.cpp:7:7: warning: address of local variable ‘b’ returned [-Wreturn-local-addr]
int b = 4;
^
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With