forked from OSchip/llvm-project
PR15132: Replace "address expression must be an lvalue or a function
designator" diagnostic with more correct and more human-friendly "cannot take address of rvalue of type 'T'". For the case of & &T::f, provide a custom diagnostic, rather than unhelpfully saying "cannot take address of rvalue of type '<overloaded function type>'". For the case of &array_temporary, treat it just like a class temporary (including allowing it as an extension); the existing diagnostic wording for the class temporary case works fine. llvm-svn: 174262
This commit is contained in:
parent
4be2c36921
commit
c084bd2888
|
@ -4160,12 +4160,14 @@ def err_invalid_form_pointer_member_function : Error<
|
|||
"cannot create a non-constant pointer to member function">;
|
||||
def err_parens_pointer_member_function : Error<
|
||||
"cannot parenthesize the name of a method when forming a member pointer">;
|
||||
def err_typecheck_invalid_lvalue_addrof_addrof_function : Error<
|
||||
"extra '&' taking address of overloaded function">;
|
||||
def err_typecheck_invalid_lvalue_addrof : Error<
|
||||
"address expression must be an lvalue or a function designator">;
|
||||
def ext_typecheck_addrof_class_temporary : ExtWarn<
|
||||
"cannot take the address of an rvalue of type %0">;
|
||||
def ext_typecheck_addrof_temporary : ExtWarn<
|
||||
"taking the address of a temporary object of type %0">,
|
||||
InGroup<DiagGroup<"address-of-temporary">>, DefaultError;
|
||||
def err_typecheck_addrof_class_temporary : Error<
|
||||
def err_typecheck_addrof_temporary : Error<
|
||||
"taking the address of a temporary object of type %0">;
|
||||
def err_typecheck_unary_expr : Error<
|
||||
"invalid argument type %0 to unary expression">;
|
||||
|
|
|
@ -8033,7 +8033,9 @@ static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp,
|
|||
if (const BuiltinType *PTy = OrigOp.get()->getType()->getAsPlaceholderType()){
|
||||
if (PTy->getKind() == BuiltinType::Overload) {
|
||||
if (!isa<OverloadExpr>(OrigOp.get()->IgnoreParens())) {
|
||||
S.Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof)
|
||||
assert(cast<UnaryOperator>(OrigOp.get()->IgnoreParens())->getOpcode()
|
||||
== UO_AddrOf);
|
||||
S.Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof_addrof_function)
|
||||
<< OrigOp.get()->getSourceRange();
|
||||
return QualType();
|
||||
}
|
||||
|
@ -8077,10 +8079,10 @@ static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp,
|
|||
Expr::LValueClassification lval = op->ClassifyLValue(S.Context);
|
||||
unsigned AddressOfError = AO_No_Error;
|
||||
|
||||
if (lval == Expr::LV_ClassTemporary) {
|
||||
if (lval == Expr::LV_ClassTemporary || lval == Expr::LV_ArrayTemporary) {
|
||||
bool sfinae = S.isSFINAEContext();
|
||||
S.Diag(OpLoc, sfinae ? diag::err_typecheck_addrof_class_temporary
|
||||
: diag::ext_typecheck_addrof_class_temporary)
|
||||
S.Diag(OpLoc, sfinae ? diag::err_typecheck_addrof_temporary
|
||||
: diag::ext_typecheck_addrof_temporary)
|
||||
<< op->getType() << op->getSourceRange();
|
||||
if (sfinae)
|
||||
return QualType();
|
||||
|
@ -8128,9 +8130,8 @@ static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp,
|
|||
if (isa<PseudoObjectExpr>(op)) {
|
||||
AddressOfError = AO_Property_Expansion;
|
||||
} else {
|
||||
// FIXME: emit more specific diag...
|
||||
S.Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof)
|
||||
<< op->getSourceRange();
|
||||
<< op->getType() << op->getSourceRange();
|
||||
return QualType();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ namespace array_dtor {
|
|||
struct S { S(); ~S(); };
|
||||
using T = S[3];
|
||||
void f(const T &);
|
||||
void f(T *);
|
||||
// CHECK: define void @_ZN10array_dtor1gEv(
|
||||
void g() {
|
||||
// CHECK: %[[ARRAY:.*]] = alloca [3 x
|
||||
|
@ -68,10 +69,9 @@ namespace array_dtor {
|
|||
// Destruct loop.
|
||||
// CHECK: call void @_ZN10array_dtor1SD1Ev(
|
||||
// CHECK: br i1
|
||||
f(T{});
|
||||
|
||||
// CHECK: ret void
|
||||
|
||||
f(T{});
|
||||
}
|
||||
// CHECK: define void @_ZN10array_dtor1hEv(
|
||||
void h() {
|
||||
|
@ -89,6 +89,23 @@ namespace array_dtor {
|
|||
// CHECK: call void @_ZN10array_dtor1SD1Ev(
|
||||
// CHECK: br i1
|
||||
|
||||
// CHECK: ret void
|
||||
}
|
||||
// CHECK: define void @_ZN10array_dtor1iEv(
|
||||
void i() {
|
||||
// CHECK: %[[ARRAY:.*]] = alloca [3 x
|
||||
// CHECK: br
|
||||
|
||||
// CHECK: call void @_ZN10array_dtor1SC1Ev(
|
||||
// CHECK: br i1
|
||||
|
||||
// CHECK: call void @_ZN10array_dtor1fEPA3_NS_1SE(
|
||||
// CHECK: br
|
||||
|
||||
// CHECK: call void @_ZN10array_dtor1SD1Ev(
|
||||
// CHECK: br i1
|
||||
f(&T{});
|
||||
|
||||
// CHECK: ret void
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ class C {
|
|||
|
||||
[]; // expected-error {{expected body of lambda expression}}
|
||||
[=,foo+] {}; // expected-error {{expected ',' or ']' in lambda capture list}}
|
||||
[&this] {}; // expected-error {{address expression must be an lvalue}}
|
||||
[&this] {}; // expected-error {{cannot take the address of an rvalue of type 'C *'}}
|
||||
[] {};
|
||||
[=] (int i) {};
|
||||
[&] (int) mutable -> void {};
|
||||
|
|
|
@ -4,7 +4,7 @@ void f1() {
|
|||
int a = 1;
|
||||
int b = __imag a;
|
||||
int *c = &__real a;
|
||||
int *d = &__imag a; // expected-error {{must be an lvalue}}
|
||||
int *d = &__imag a; // expected-error {{cannot take the address of an rvalue of type 'int'}}
|
||||
}
|
||||
|
||||
void f2() {
|
||||
|
@ -18,7 +18,7 @@ void f3() {
|
|||
double a = 1;
|
||||
double b = __imag a;
|
||||
double *c = &__real a;
|
||||
double *d = &__imag a; // expected-error {{must be an lvalue}}
|
||||
double *d = &__imag a; // expected-error {{cannot take the address of an rvalue of type 'double'}}
|
||||
}
|
||||
|
||||
void f4() {
|
||||
|
|
|
@ -90,8 +90,8 @@ void f5() {
|
|||
lvalue we would need to give a warning. Note that gcc warns about
|
||||
this as a register before it warns about it as an invalid
|
||||
lvalue. */
|
||||
int *_dummy0 = &(int*) arr; // expected-error {{address expression must be an lvalue or a function designator}}
|
||||
int *_dummy1 = &(arr + 1); // expected-error {{address expression must be an lvalue or a function designator}}
|
||||
int *_dummy0 = &(int*) arr; // expected-error {{cannot take the address of an rvalue}}
|
||||
int *_dummy1 = &(arr + 1); // expected-error {{cannot take the address of an rvalue}}
|
||||
}
|
||||
|
||||
void f6(register int x) {
|
||||
|
@ -109,12 +109,12 @@ char* f7() {
|
|||
}
|
||||
|
||||
void f8() {
|
||||
void *dummy0 = &f8(); // expected-error {{address expression must be an lvalue or a function designator}}
|
||||
void *dummy0 = &f8(); // expected-error {{cannot take the address of an rvalue of type 'void'}}
|
||||
|
||||
extern void v;
|
||||
void *dummy1 = &(1 ? v : f8()); // expected-error {{address expression must be an lvalue or a function designator}}
|
||||
void *dummy1 = &(1 ? v : f8()); // expected-error {{cannot take the address of an rvalue of type 'void'}}
|
||||
|
||||
void *dummy2 = &(f8(), v); // expected-error {{address expression must be an lvalue or a function designator}}
|
||||
void *dummy2 = &(f8(), v); // expected-error {{cannot take the address of an rvalue of type 'void'}}
|
||||
|
||||
void *dummy3 = &({ ; }); // expected-error {{address expression must be an lvalue or a function designator}}
|
||||
void *dummy3 = &({ ; }); // expected-error {{cannot take the address of an rvalue of type 'void'}}
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ void f7(int a, ...) {
|
|||
__builtin_va_start(ap, a);
|
||||
// FIXME: This error message is sub-par.
|
||||
__builtin_va_arg(ap, int) = 1; // expected-error {{expression is not assignable}}
|
||||
int *x = &__builtin_va_arg(ap, int); // expected-error {{address expression must be an lvalue or a function designator}}
|
||||
int *x = &__builtin_va_arg(ap, int); // expected-error {{cannot take the address of an rvalue}}
|
||||
__builtin_va_end(ap);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,12 +22,12 @@ enum E {
|
|||
};
|
||||
|
||||
void test() {
|
||||
(void)&Enumerator; // expected-error{{address expression must be an lvalue or a function designator}}
|
||||
(void)&Enumerator; // expected-error{{cannot take the address of an rvalue of type 'E'}}
|
||||
}
|
||||
|
||||
template<int N>
|
||||
void test2() {
|
||||
(void)&N; // expected-error{{address expression must be an lvalue or a function designator}}
|
||||
(void)&N; // expected-error{{cannot take the address of an rvalue of type 'int'}}
|
||||
}
|
||||
|
||||
// PR clang/3222
|
||||
|
@ -41,7 +41,7 @@ struct PR11066 {
|
|||
};
|
||||
|
||||
void PR11066::test() {
|
||||
int (PR11066::*ptr)(int) = & &PR11066::foo; // expected-error{{address expression must be an lvalue or a function designator}}
|
||||
int (PR11066::*ptr)(int) = & &PR11066::foo; // expected-error{{extra '&' taking address of overloaded function}}
|
||||
}
|
||||
|
||||
namespace test3 {
|
||||
|
|
|
@ -146,7 +146,7 @@ void test()
|
|||
(void)(i1 ? 1 : Ambig()); // expected-error {{conversion from 'Ambig' to 'int' is ambiguous}}
|
||||
(void)(i1 ? Ambig() : 1); // expected-error {{conversion from 'Ambig' to 'int' is ambiguous}}
|
||||
// By the way, this isn't an lvalue:
|
||||
&(i1 ? i1 : i2); // expected-error {{address expression must be an lvalue or a function designator}}
|
||||
&(i1 ? i1 : i2); // expected-error {{cannot take the address of an rvalue}}
|
||||
|
||||
// p4 (lvalue, same type)
|
||||
Fields flds;
|
||||
|
@ -183,7 +183,7 @@ void test()
|
|||
i1 ? &MixedFields::ci : &MixedFields::cvi;
|
||||
(void)(i1 ? &MixedFields::ci : &MixedFields::vi);
|
||||
// Conversion of primitives does not result in an lvalue.
|
||||
&(i1 ? i1 : d1); // expected-error {{address expression must be an lvalue or a function designator}}
|
||||
&(i1 ? i1 : d1); // expected-error {{cannot take the address of an rvalue}}
|
||||
|
||||
(void)&(i1 ? flds.b1 : flds.i1); // expected-error {{address of bit-field requested}}
|
||||
(void)&(i1 ? flds.i1 : flds.b1); // expected-error {{address of bit-field requested}}
|
||||
|
|
|
@ -125,3 +125,8 @@ namespace multidimensional_array {
|
|||
g({{1,2},{3,4}});
|
||||
}
|
||||
}
|
||||
|
||||
namespace array_addressof {
|
||||
using T = int[5];
|
||||
T *p = &T{1,2,3,4,5}; // expected-error {{taking the address of a temporary object of type 'T' (aka 'int [5]')}}
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ nullptr_t f(nullptr_t null)
|
|||
o2(nullptr); // expected-error {{ambiguous}}
|
||||
|
||||
// nullptr is an rvalue, null is an lvalue
|
||||
(void)&nullptr; // expected-error {{address expression must be an lvalue}}
|
||||
(void)&nullptr; // expected-error {{cannot take the address of an rvalue of type 'nullptr_t'}}
|
||||
nullptr_t *pn = &null;
|
||||
|
||||
// You can reinterpret_cast nullptr to an integer.
|
||||
|
|
|
@ -328,7 +328,7 @@ namespace rdar13000548 {
|
|||
template<typename R, R F(int)>
|
||||
struct X {
|
||||
typedef R (*fptype)(int);
|
||||
static fptype f() { return &F; } // expected-error{{address expression must be an lvalue or a function designator}}
|
||||
static fptype f() { return &F; } // expected-error{{cannot take the address of an rvalue of type 'int (*)(int)'}}
|
||||
};
|
||||
|
||||
int g(int);
|
||||
|
|
Loading…
Reference in New Issue