[cfe-dev] constexpr difference between gcc and clang
Richard Smith
richard at metafoo.co.uk
Mon Aug 6 22:44:12 PDT 2012
Hi David,
On Mon, Aug 6, 2012 at 6:54 PM, David Wood <dswood at gmail.com> wrote:
> > The following compiles fine in macports gcc 4.7, but does not in clang
> svn
> > 161307. I believe the key is the const reference in combination with
> the ?:
> > operator.
> >
> > #include <stdexcept>
> >
> > struct A {
> > constexpr A(int a) : value(a) {}
> >
> > constexpr int get() { return value; }
> >
> > private:
> > int value;
> > };
> >
> > constexpr A someFn(const A& a) {
> > return a.get() == 0 ? throw std::exception() : a;
> > }
> >
> > int main(int argc, char** argv) {
> > constexpr A a(4);
> > static_assert( someFn(a).get() == 4, "error" );
> > }
> >
> > Some digging on the internets reveals
> >
> http://stackoverflow.com/questions/5605142/stdmax-and-stdmin-not-constexpr
> ,
> > which seems to point to lvalues, glvalues and memory allocation,
> although I
> > did not follow it very well. There is also the particularly interesting
> > comment :
> >
> > The C++ committee have suggested that it was intended to be possible for
> > function invocation substitution to produce an lvalue referring to a
> > temporary. g++ behaves that way, but clang currently implements the
> standard
> > as written.
>
That comment is out of date. At the most recent C++ standards committee
meeting, we decided to allow such cases, and Clang now supports them.
> > So, I have two questions. 1) Is the way clang handles this in fact
> > conformant to the spec, and gcc is lax?
>
This code is well-formed, we're incorrect to reject it. Please file a bug
at llvm.org/bugs.
We are rejecting it because we have produced a broken AST:
(CompoundStmt 0x4024650 <<stdin>:10:32, line:12:1>
(ReturnStmt 0x4024630 <line:11:3, col:35>
(CXXConstructExpr 0x40245f8 <col:10, col:35> 'struct A''void (const
struct A &) noexcept' elidable
(MaterializeTemporaryExpr 0x40244d0 <col:10, col:35> 'const struct A'
lvalue
(ConditionalOperator 0x4024128 <col:10, col:35> 'const struct A'
(BinaryOperator 0x4024098 <col:10, col:21> '_Bool' '=='
(CXXMemberCallExpr 0x4024050 <col:10, col:16> 'int'
(MemberExpr 0x4024020 <col:10, col:12> '<bound member
function type>' .get 0x4023af0
(DeclRefExpr 0x4023ff8 <col:10> 'const struct A' lvalue
ParmVar 0x4023e90 'a' 'const struct A &')))
(IntegerLiteral 0x4024078 <col:21> 'int' 0))
(CXXThrowExpr 0x40240e0 <col:25, col:31> 'void'
(IntegerLiteral 0x40240c0 <col:31> 'int' 0))
(DeclRefExpr 0x4024100 <col:35> 'const struct A' lvalue ParmVar
0x4023e90 'a' 'const struct A &'))))))
Note that the ConditionalOperator is an rvalue, but its third operand is an
lvalue, with no intervening CXXConstructExpr. That's wrong -- we're
supposed to perform an lvalue-to-rvalue conversion on this operand (see
[expr.cond]p2).
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20120806/3f5e6f21/attachment.html>
More information about the cfe-dev
mailing list