r174262 - PR15132: Replace "address expression must be an lvalue or a function

Richard Smith richard-llvm at metafoo.co.uk
Fri Feb 1 18:14:46 PST 2013


Author: rsmith
Date: Fri Feb  1 20:14:45 2013
New Revision: 174262

URL: http://llvm.org/viewvc/llvm-project?rev=174262&view=rev
Log:
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.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/test/CodeGenCXX/cxx0x-initializer-array.cpp
    cfe/trunk/test/Parser/objcxx0x-lambda-expressions.mm
    cfe/trunk/test/Sema/complex-imag.c
    cfe/trunk/test/Sema/expr-address-of.c
    cfe/trunk/test/Sema/varargs.c
    cfe/trunk/test/SemaCXX/address-of.cpp
    cfe/trunk/test/SemaCXX/conditional-expr.cpp
    cfe/trunk/test/SemaCXX/cxx0x-initializer-aggregates.cpp
    cfe/trunk/test/SemaCXX/nullptr.cpp
    cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=174262&r1=174261&r2=174262&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Feb  1 20:14:45 2013
@@ -4160,12 +4160,14 @@ def err_invalid_form_pointer_member_func
   "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">;

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=174262&r1=174261&r2=174262&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Feb  1 20:14:45 2013
@@ -8033,7 +8033,9 @@ static QualType CheckAddressOfOperand(Se
   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(Se
   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(Se
       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();
       }
     }

Modified: cfe/trunk/test/CodeGenCXX/cxx0x-initializer-array.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx0x-initializer-array.cpp?rev=174262&r1=174261&r2=174262&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/cxx0x-initializer-array.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/cxx0x-initializer-array.cpp Fri Feb  1 20:14:45 2013
@@ -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
+  }
 }

Modified: cfe/trunk/test/Parser/objcxx0x-lambda-expressions.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/objcxx0x-lambda-expressions.mm?rev=174262&r1=174261&r2=174262&view=diff
==============================================================================
--- cfe/trunk/test/Parser/objcxx0x-lambda-expressions.mm (original)
+++ cfe/trunk/test/Parser/objcxx0x-lambda-expressions.mm Fri Feb  1 20:14:45 2013
@@ -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 {}; 

Modified: cfe/trunk/test/Sema/complex-imag.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/complex-imag.c?rev=174262&r1=174261&r2=174262&view=diff
==============================================================================
--- cfe/trunk/test/Sema/complex-imag.c (original)
+++ cfe/trunk/test/Sema/complex-imag.c Fri Feb  1 20:14:45 2013
@@ -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() {

Modified: cfe/trunk/test/Sema/expr-address-of.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/expr-address-of.c?rev=174262&r1=174261&r2=174262&view=diff
==============================================================================
--- cfe/trunk/test/Sema/expr-address-of.c (original)
+++ cfe/trunk/test/Sema/expr-address-of.c Fri Feb  1 20:14:45 2013
@@ -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'}}
 }

Modified: cfe/trunk/test/Sema/varargs.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/varargs.c?rev=174262&r1=174261&r2=174262&view=diff
==============================================================================
--- cfe/trunk/test/Sema/varargs.c (original)
+++ cfe/trunk/test/Sema/varargs.c Fri Feb  1 20:14:45 2013
@@ -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);
 }
 

Modified: cfe/trunk/test/SemaCXX/address-of.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/address-of.cpp?rev=174262&r1=174261&r2=174262&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/address-of.cpp (original)
+++ cfe/trunk/test/SemaCXX/address-of.cpp Fri Feb  1 20:14:45 2013
@@ -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 {

Modified: cfe/trunk/test/SemaCXX/conditional-expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/conditional-expr.cpp?rev=174262&r1=174261&r2=174262&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/conditional-expr.cpp (original)
+++ cfe/trunk/test/SemaCXX/conditional-expr.cpp Fri Feb  1 20:14:45 2013
@@ -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}}

Modified: cfe/trunk/test/SemaCXX/cxx0x-initializer-aggregates.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-initializer-aggregates.cpp?rev=174262&r1=174261&r2=174262&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx0x-initializer-aggregates.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx0x-initializer-aggregates.cpp Fri Feb  1 20:14:45 2013
@@ -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]')}}
+}

Modified: cfe/trunk/test/SemaCXX/nullptr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/nullptr.cpp?rev=174262&r1=174261&r2=174262&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/nullptr.cpp (original)
+++ cfe/trunk/test/SemaCXX/nullptr.cpp Fri Feb  1 20:14:45 2013
@@ -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.

Modified: cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp?rev=174262&r1=174261&r2=174262&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp (original)
+++ cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp Fri Feb  1 20:14:45 2013
@@ -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);





More information about the cfe-commits mailing list