Bug 58777 - Taking address of variant/union member is not always a constant expression
Summary: Taking address of variant/union member is not always a constant expression
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.9.0
: P3 normal
Target Milestone: 5.0
Assignee: Jason Merrill
URL:
Keywords:
Depends on:
Blocks: constexpr
  Show dependency treegraph
 
Reported: 2013-10-18 05:00 UTC by lucdanton
Modified: 2015-01-14 21:36 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2013-10-18 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description lucdanton 2013-10-18 05:00:46 UTC
$ g++-trunk --version
g++-trunk (GCC) 4.9.0 20131017 (experimental)

$ cat main.cpp 
union foo { int i; double d; };

constexpr int const* addr(foo const& f)
{ return &f.i; }

constexpr int const& ref(foo const& f)
{ return f.i; }

int main()
{
    constexpr foo f { 42 };
    // Fine
    static_assert( &f.i, "" );
    // Not fine
    static_assert( addr(f), "" );
    // Not fine
    static_assert( &ref(f), "" );
}

$ g++-trunk -std=c++11 -Wall main.cpp 
main.cpp: In function 'int main()':
main.cpp:15:5: error: non-constant condition for static assertion
     static_assert( addr(f), "" );
     ^
main.cpp:15:5: error: '& f.foo::i' is not a constant expression
main.cpp:17:5: error: non-constant condition for static assertion
     static_assert( &ref(f), "" );
     ^
main.cpp:17:5: error: '& f.foo::i' is not a constant expression
Comment 1 Paolo Carlini 2013-10-18 09:12:18 UTC
I added Jason in CC because this impacts the library (and we already discussed constexpr vs pointers, we have other bugs likely duplicates): Luc, can you use a workaround for the time being?
Comment 2 lucdanton 2013-10-18 23:15:30 UTC
Not that I can think of: the same functions are used in non-constant expressions as well. They *could* be made non-constexpr so as to avoid advertising incomplete features, but the thing is some things do work in a constant expression context.

E.g. static_assert( ref(f) == 42, "" ); works, and in the context of optional values that make them useful as a literal type. In fact, things like *&ref(f) == 42 are also accepted (through CTFE, too). I expect using the contained value to be much more useful that using its address, until optional references at least.
Comment 3 Jason Merrill 2015-01-13 21:05:16 UTC
Author: jason
Date: Tue Jan 13 21:04:43 2015
New Revision: 219559

URL: https://gcc.gnu.org/viewcvs?rev=219559&root=gcc&view=rev
Log:
	PR c++/64356
	PR libstdc++/58777
	* constexpr.c (cxx_eval_binary_expression): Don't VERIFY_CONSTANT
	pointer expressions.
	(cxx_eval_increment_expression): Likewise.

Added:
    trunk/gcc/testsuite/g++.dg/cpp1y/constexpr-local2.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/constexpr.c
    trunk/gcc/testsuite/g++.dg/cpp1y/pr63996.C
    trunk/libstdc++-v3/testsuite/experimental/optional/constexpr/make_optional.cc
    trunk/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/2.cc
    trunk/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/3.cc
Comment 4 Jason Merrill 2015-01-14 21:36:18 UTC
Fixed for GCC 5.