Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can constexpr function return pointer of local object?

Tags:

c++

c++14

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

like image 239
code707 Avatar asked Jan 03 '23 08:01

code707


2 Answers

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.

like image 92
Hatted Rooster Avatar answered Jan 04 '23 22:01

Hatted Rooster


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;
       ^
like image 24
max66 Avatar answered Jan 04 '23 20:01

max66