Open Quuxplusone opened 13 years ago
Bugzilla Link | PR10107 |
Status | REOPENED |
Importance | P normal |
Reported by | Allan Odgaard (691D2C6C-B023-46A5-B1D7-ACCBA4713A87@uuid-mail.com) |
Reported on | 2011-06-09 02:42:15 -0700 |
Last modified on | 2012-01-12 15:56:30 -0800 |
Version | 2.9 |
Hardware | Macintosh MacOS X |
CC | dgregor@apple.com, efriedma@quicinc.com, llvm-bugs@lists.llvm.org, richard-llvm@metafoo.co.uk, scshunt@csclub.uwaterloo.ca, zaffanella@cs.unipr.it |
Fixed by commit(s) | |
Attachments | |
Blocks | |
Blocked by | |
See also |
GCC warns here but accepts the code.
Clang errors in all C++ modes, since this is an extension that is extremely
unsafe. You can downgrade the error to a warning with the
-Wno-error=address-of-temporary
command-line option or turn it off entirely with
-Wno-address-of-temporary
As of r147790, clang still crashes on the following line of code, if -W[no-
]address-of-temporary is used:
$ cat bug.cc
int (*pa)[1] = &(int[]) { 1 };
$ clang++ -c bug.cc
bug.cc:1:16: error: taking the address of a temporary object of type
'int [1]'
[-Waddress-of-temporary]
int (*pa)[1] = &(int[]) { 1 };
^~~~~~~~~~~~~~
1 error generated.
$ clang++ -Waddress-of-temporary -c bug.cc
bug.cc:1:16: warning: taking the address of a temporary object of type
'int [1]'
[-Waddress-of-temporary]
int (*pa)[1] = &(int[]) { 1 };
^~~~~~~~~~~~~~
clang: <path>/tools/clang/lib/AST/ExprConstant.cpp:2479: bool
EvaluateLValue(const clang::Expr*, <unnamed>::LValue&,
<unnamed>::EvalInfo&): Assertion `(E->isGLValue() ||
E->getType()->isFunctionType() || E->getType()->isVoidType() ||
isa<CXXTemporaryObjectExpr>(E)) && "can't evaluate expression as an
lvalue"' failed.
[...]
We're building an AST that looks like this:
(UnaryOperator 0x56cd290 <col:40, col:46> 'struct S *' prefix '&'
(CompoundLiteralExpr 0x56ccfd0 <col:41, col:46> 'struct S'
(InitListExpr 0x56ccf80 <col:44, col:46> 'struct S'
This doesn't seem right to me. I would expect that either the compound literal
expression should be an lvalue, or we should be materializing a temporary for
it. Is this really how we want to represent this construct in C++?
For reference, on the following example:
struct S { int n; };
int f() {
struct S *p = &(struct S){1};
return p->n;
}
g++ compiles this to 'return 1' in -x c, and to 'return 0' in -x c++ -
fpermissive, which strongly suggests that in gnu++ mode we should be
materializing a temporary to match g++'s semantics.