Hi,

here certainly we can do better than using input_location. In principle we could also pass the location of the entity (constructor, destructor, etc) itself or something else but I think it makes a lot of sense to simply include locations[ds_type_spec] in the computation, seems consistent with the existing case of spurious qualifiers (ICC does something similar AFAICS). Tested x86_64-linux.

Thanks, Paolo.

//////////////////////

/cp
2019-06-05  Paolo Carlini  <paolo.carl...@oracle.com>

        * decl.c (smallest_type_location): Add.
        (check_special_function_return_type): Use it.
        (grokdeclarator): Lkewise.

/testsuite
2019-06-05  Paolo Carlini  <paolo.carl...@oracle.com>

        * g++.dg/diagnostic/return-type-invalid-1.C: New.
        * g++.old-deja/g++.brendan/crash16.C: Adjust.
        * g++.old-deja/g++.law/ctors5.C: Likewise.
Index: cp/decl.c
===================================================================
--- cp/decl.c   (revision 271949)
+++ cp/decl.c   (working copy)
@@ -10111,6 +10111,15 @@ smallest_type_quals_location (int type_quals, cons
   return loc;
 }
 
+/* Returns the smallest among the latter and locations[ds_type_spec].  */
+
+static location_t
+smallest_type_location (int type_quals, const location_t* locations)
+{
+  location_t loc = smallest_type_quals_location (type_quals, locations);
+  return min_location (loc, locations[ds_type_spec]);
+}
+
 /* Check that it's OK to declare a function with the indicated TYPE
    and TYPE_QUALS.  SFK indicates the kind of special function (if any)
    that this function is.  OPTYPE is the type given in a conversion
@@ -10129,7 +10138,8 @@ check_special_function_return_type (special_functi
     {
     case sfk_constructor:
       if (type)
-       error ("return type specification for constructor invalid");
+       error_at (smallest_type_location (type_quals, locations),
+                 "return type specification for constructor invalid");
       else if (type_quals != TYPE_UNQUALIFIED)
        error_at (smallest_type_quals_location (type_quals, locations),
                  "qualifiers are not allowed on constructor declaration");
@@ -10142,7 +10152,8 @@ check_special_function_return_type (special_functi
 
     case sfk_destructor:
       if (type)
-       error ("return type specification for destructor invalid");
+       error_at (smallest_type_location (type_quals, locations),
+                 "return type specification for destructor invalid");
       else if (type_quals != TYPE_UNQUALIFIED)
        error_at (smallest_type_quals_location (type_quals, locations),
                  "qualifiers are not allowed on destructor declaration");
@@ -10157,7 +10168,8 @@ check_special_function_return_type (special_functi
 
     case sfk_conversion:
       if (type)
-       error ("return type specified for %<operator %T%>", optype);
+       error_at (smallest_type_location (type_quals, locations),
+                 "return type specified for %<operator %T%>", optype);
       else if (type_quals != TYPE_UNQUALIFIED)
        error_at (smallest_type_quals_location (type_quals, locations),
                  "qualifiers are not allowed on declaration of "
@@ -10168,7 +10180,8 @@ check_special_function_return_type (special_functi
 
     case sfk_deduction_guide:
       if (type)
-       error ("return type specified for deduction guide");
+       error_at (smallest_type_location (type_quals, locations),
+                 "return type specified for deduction guide");
       else if (type_quals != TYPE_UNQUALIFIED)
        error_at (smallest_type_quals_location (type_quals, locations),
                  "qualifiers are not allowed on declaration of "
@@ -10438,10 +10451,8 @@ grokdeclarator (const cp_declarator *declarator,
   if (initialized > 1)
     funcdef_flag = true;
 
-  location_t typespec_loc = smallest_type_quals_location (type_quals,
-                                                     declspecs->locations);
-  typespec_loc = min_location (typespec_loc,
-                              declspecs->locations[ds_type_spec]);
+  location_t typespec_loc = smallest_type_location (type_quals,
+                                                   declspecs->locations);
   if (typespec_loc == UNKNOWN_LOCATION)
     typespec_loc = input_location;
 
Index: testsuite/g++.dg/diagnostic/return-type-invalid-1.C
===================================================================
--- testsuite/g++.dg/diagnostic/return-type-invalid-1.C (nonexistent)
+++ testsuite/g++.dg/diagnostic/return-type-invalid-1.C (working copy)
@@ -0,0 +1,27 @@
+struct S1
+{
+  int S1();  // { dg-error "3:return type" }
+  int ~S1();  // { dg-error "3:return type" }
+  int operator int();  // { dg-error "3:return type" }
+};
+
+struct S2
+{
+  const int S2();  // { dg-error "3:return type" }
+  const int ~S2();  // { dg-error "3:return type" }
+  const int operator int();  // { dg-error "3:return type" }
+};
+
+struct S3
+{
+  volatile int S3();  // { dg-error "3:return type" }
+  volatile int ~S3();  // { dg-error "3:return type" }
+  volatile int operator int(); // { dg-error "3:return type" } 
+};
+
+struct S4
+{
+  const volatile int S4();  // { dg-error "3:return type" }
+  const volatile int ~S4();  // { dg-error "3:return type" }
+  const volatile int operator int();  // { dg-error "3:return type" }
+};
Index: testsuite/g++.old-deja/g++.brendan/crash16.C
===================================================================
--- testsuite/g++.old-deja/g++.brendan/crash16.C        (revision 271949)
+++ testsuite/g++.old-deja/g++.brendan/crash16.C        (working copy)
@@ -3,12 +3,13 @@
 // GROUPS passed old-abort
 
 class Graph { // { dg-error "1:new types|1: note: \\(perhaps" }
+// { dg-error "1:return type" "" { target *-*-* } .-1 }
 public:
       unsigned         char N;
       Graph(void) {} // { dg-message "7:'Graph" }
 }
 
-Graph::Graph(void) // { dg-error "18:return type|1: error: redefinition" }
+Graph::Graph(void) // { dg-error "1:redefinition" }
 {    N = 10;
 }
 
Index: testsuite/g++.old-deja/g++.law/ctors5.C
===================================================================
--- testsuite/g++.old-deja/g++.law/ctors5.C     (revision 271949)
+++ testsuite/g++.old-deja/g++.law/ctors5.C     (working copy)
@@ -16,6 +16,7 @@ class X             // { dg-message "7:X::X|candidate ex
 
 class Y // { dg-error "1:new types may not be defined in a return type" "err" }
         // { dg-message "1:\\(perhaps a semicolon is missing after the 
definition of 'Y'\\)" "note" { target *-*-* } .-1 }
+        // { dg-error "1:return type specification for constructor invalid" 
"err"  { target *-*-* } .-2 }
 {
   private:
     X xx;
@@ -22,7 +23,7 @@ class Y // { dg-error "1:new types may not be defi
   public:
     Y();
 }
-X::X( int xi ) // { dg-error "14:return type specification for constructor 
invalid" "err" }
+X::X( int xi )
 // { dg-message "1:X::X|candidate expects" "match candidate text" { target 
*-*-* } .-1 }
 {
     x = xi;

Reply via email to