[C++] Improve check_special_function_return_type locations

Message ID 19fe3e47-a1a6-6ac5-aad6-e780b48381a2@oracle.com
State New
Headers show
Series
  • [C++] Improve check_special_function_return_type locations
Related show

Commit Message

Paolo Carlini June 5, 2019, 3:06 p.m.
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.carlini@oracle.com>

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

/testsuite
2019-06-05  Paolo Carlini  <paolo.carlini@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.

Comments

Jason Merrill June 5, 2019, 5:47 p.m. | #1
On 6/5/19 11:06 AM, Paolo Carlini wrote:
> 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.


OK.

Jason

Patch

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;