aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2013-02-02 02:14:45 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2013-02-02 02:14:45 +0000
commit3fa3feab35096b608f1d79bb541798b37a55e7b9 (patch)
tree9d1266173a5b7da78cf0998856044dea5c9b1e30
parent821b93eec8b58a3e320ef34e7c98906ab61cf8c3 (diff)
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@174262 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td8
-rw-r--r--lib/Sema/SemaExpr.cpp13
-rw-r--r--test/CodeGenCXX/cxx0x-initializer-array.cpp21
-rw-r--r--test/Parser/objcxx0x-lambda-expressions.mm2
-rw-r--r--test/Sema/complex-imag.c4
-rw-r--r--test/Sema/expr-address-of.c12
-rw-r--r--test/Sema/varargs.c2
-rw-r--r--test/SemaCXX/address-of.cpp6
-rw-r--r--test/SemaCXX/conditional-expr.cpp4
-rw-r--r--test/SemaCXX/cxx0x-initializer-aggregates.cpp5
-rw-r--r--test/SemaCXX/nullptr.cpp2
-rw-r--r--test/SemaTemplate/temp_arg_nontype.cpp2
12 files changed, 53 insertions, 28 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 3e3b816ce2..bcc33d1982 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -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">;
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 0465707e7c..ef852d354f 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -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();
}
}
diff --git a/test/CodeGenCXX/cxx0x-initializer-array.cpp b/test/CodeGenCXX/cxx0x-initializer-array.cpp
index 73bbca13b1..3144e941ef 100644
--- a/test/CodeGenCXX/cxx0x-initializer-array.cpp
+++ b/test/CodeGenCXX/cxx0x-initializer-array.cpp
@@ -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() {
@@ -91,4 +91,21 @@ namespace array_dtor {
// 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
+ }
}
diff --git a/test/Parser/objcxx0x-lambda-expressions.mm b/test/Parser/objcxx0x-lambda-expressions.mm
index 1eab15bee9..fb90b16a97 100644
--- a/test/Parser/objcxx0x-lambda-expressions.mm
+++ b/test/Parser/objcxx0x-lambda-expressions.mm
@@ -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 {};
diff --git a/test/Sema/complex-imag.c b/test/Sema/complex-imag.c
index 1c6fb159bc..deaf627753 100644
--- a/test/Sema/complex-imag.c
+++ b/test/Sema/complex-imag.c
@@ -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() {
diff --git a/test/Sema/expr-address-of.c b/test/Sema/expr-address-of.c
index 2b8cfbfa68..32bd0dfdd5 100644
--- a/test/Sema/expr-address-of.c
+++ b/test/Sema/expr-address-of.c
@@ -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'}}
}
diff --git a/test/Sema/varargs.c b/test/Sema/varargs.c
index 07081edd1d..663d3d5947 100644
--- a/test/Sema/varargs.c
+++ b/test/Sema/varargs.c
@@ -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);
}
diff --git a/test/SemaCXX/address-of.cpp b/test/SemaCXX/address-of.cpp
index 677dc8966b..373e44c17e 100644
--- a/test/SemaCXX/address-of.cpp
+++ b/test/SemaCXX/address-of.cpp
@@ -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 {
diff --git a/test/SemaCXX/conditional-expr.cpp b/test/SemaCXX/conditional-expr.cpp
index 7595f1dfa1..692aaefc9d 100644
--- a/test/SemaCXX/conditional-expr.cpp
+++ b/test/SemaCXX/conditional-expr.cpp
@@ -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}}
diff --git a/test/SemaCXX/cxx0x-initializer-aggregates.cpp b/test/SemaCXX/cxx0x-initializer-aggregates.cpp
index 7d1fa7e3ec..f53ac6dff9 100644
--- a/test/SemaCXX/cxx0x-initializer-aggregates.cpp
+++ b/test/SemaCXX/cxx0x-initializer-aggregates.cpp
@@ -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]')}}
+}
diff --git a/test/SemaCXX/nullptr.cpp b/test/SemaCXX/nullptr.cpp
index d148f76698..b49f63b980 100644
--- a/test/SemaCXX/nullptr.cpp
+++ b/test/SemaCXX/nullptr.cpp
@@ -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.
diff --git a/test/SemaTemplate/temp_arg_nontype.cpp b/test/SemaTemplate/temp_arg_nontype.cpp
index 59da9c667e..434054ecbd 100644
--- a/test/SemaTemplate/temp_arg_nontype.cpp
+++ b/test/SemaTemplate/temp_arg_nontype.cpp
@@ -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);