[C++] A few additional location improvements to grokdeclarator and check_tag_decl

Message ID 75c69855-965c-6c03-fe95-905af5d15cc0@oracle.com
State New
Headers show
Series
  • [C++] A few additional location improvements to grokdeclarator and check_tag_decl
Related show

Commit Message

Paolo Carlini June 23, 2019, 11:58 a.m.
Hi,

here there are a couple of rather straightforward improvements in the 
second half of grokdeclarator plus a check_tag_decl change consistent 
with the other existing case of multiple_types_p diagnostic. Tested 
x86_64-linux.

Thanks, Paolo.

/////////////////////
/cp
2019-06-23  Paolo Carlini  <paolo.carlini@oracle.com>

	* decl.c (get_type_quals): New.
	(check_tag_decl): Use smallest_type_location and the latter in
	error_at about multiple types in one declaration.
	(grokdeclarator): Use locations[ds_storage_class] in error_at
	about static cdtor; use id_loc in error_at about flexible
	array member in union; use get_type_quals.

/testsuite
2019-06-23  Paolo Carlini  <paolo.carlini@oracle.com>

	* g++.dg/diagnostic/static-cdtor-1.C: New.
	* g++.dg/cpp1z/has-unique-obj-representations2.C: Test location
	too.
	* g++.dg/other/anon-union3.C: Adjust expected location.
	* g++.dg/parse/error8.C: Likewise.

Comments

Paolo Carlini July 5, 2019, 7:37 p.m. | #1
Hi,

On 23/06/19 13:58, Paolo Carlini wrote:
> Hi,

>

> here there are a couple of rather straightforward improvements in the 

> second half of grokdeclarator plus a check_tag_decl change consistent 

> with the other existing case of multiple_types_p diagnostic. Tested 

> x86_64-linux.


Gently pinging this...

     https://gcc.gnu.org/ml/gcc-patches/2019-06/msg01391.html

Thanks, Paolo.
Jason Merrill July 8, 2019, 9:44 p.m. | #2
On 6/23/19 7:58 AM, Paolo Carlini wrote:
> +    error_at (smallest_type_location (get_type_quals (declspecs),

> +				      declspecs->locations),


How about adding a smallest_type_location overload that just takes 
declspecs?

Jason
Paolo Carlini July 9, 2019, 10:10 a.m. | #3
Hi,

On 08/07/19 23:44, Jason Merrill wrote:
> On 6/23/19 7:58 AM, Paolo Carlini wrote:

>> +    error_at (smallest_type_location (get_type_quals (declspecs),

>> +                      declspecs->locations),

> How about adding a smallest_type_location overload that just takes 

> declspecs?


Sure. The below has an additional location fixlet which I noticed over 
the last days, for "complex invalid for". Tested x86_64-linux, as usual.

Thanks, Paolo.

////////////////
/cp
2019-07-09  Paolo Carlini  <paolo.carlini@oracle.com>

	* decl.c (get_type_quals,
	smallest_type_location (const cp_decl_specifier_seq*)): New.
	(check_tag_decl): Use smallest_type_location in error_at about
	multiple types in one declaration.
	(grokdeclarator): Use locations[ds_complex] in error_at about
	complex invalid; use locations[ds_storage_class] in error_at
	about static cdtor; use id_loc in error_at about flexible
	array member in union; use get_type_quals.

/testsuite
2019-07-09  Paolo Carlini  <paolo.carlini@oracle.com>

	* g++.dg/diagnostic/complex-invalid-1.C: New.
	* g++.dg/diagnostic/static-cdtor-1.C: Likewise.
	* g++.dg/cpp1z/has-unique-obj-representations2.C: Test location
	too.
	* g++.dg/other/anon-union3.C: Adjust expected location.
	* g++.dg/parse/error8.C: Likewise.
Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 273227)
+++ cp/decl.c	(working copy)
@@ -100,6 +100,7 @@ static tree build_cp_library_fn (tree, enum tree_c
 static void store_parm_decls (tree);
 static void initialize_local_var (tree, tree);
 static void expand_static_init (tree, tree);
+static location_t smallest_type_location (const cp_decl_specifier_seq*);
 
 /* The following symbols are subsumed in the cp_global_trees array, and
    listed here individually for documentation purposes.
@@ -4802,6 +4803,24 @@ warn_misplaced_attr_for_class_type (location_t loc
 	    class_type, class_key_or_enum_as_string (class_type));
 }
 
+/* Returns the cv-qualifiers that apply to the type specified
+   by the DECLSPECS.  */
+
+static int
+get_type_quals (const cp_decl_specifier_seq *declspecs)
+{
+  int type_quals = TYPE_UNQUALIFIED;
+
+  if (decl_spec_seq_has_spec_p (declspecs, ds_const))
+    type_quals |= TYPE_QUAL_CONST;
+  if (decl_spec_seq_has_spec_p (declspecs, ds_volatile))
+    type_quals |= TYPE_QUAL_VOLATILE;
+  if (decl_spec_seq_has_spec_p (declspecs, ds_restrict))
+    type_quals |= TYPE_QUAL_RESTRICT;
+
+  return type_quals;
+}
+
 /* Make sure that a declaration with no declarator is well-formed, i.e.
    just declares a tagged type or anonymous union.
 
@@ -4821,7 +4840,8 @@ check_tag_decl (cp_decl_specifier_seq *declspecs,
   bool error_p = false;
 
   if (declspecs->multiple_types_p)
-    error ("multiple types in one declaration");
+    error_at (smallest_type_location (declspecs),
+	      "multiple types in one declaration");
   else if (declspecs->redefined_builtin_type)
     {
       if (!in_system_header_at (input_location))
@@ -10142,6 +10162,13 @@ smallest_type_location (int type_quals, const loca
   return min_location (loc, locations[ds_type_spec]);
 }
 
+static location_t
+smallest_type_location (const cp_decl_specifier_seq *declspecs)
+{
+  int type_quals = get_type_quals (declspecs);
+  return smallest_type_location (type_quals, declspecs->locations);
+}
+
 /* 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
@@ -10407,7 +10434,7 @@ grokdeclarator (const cp_declarator *declarator,
      a member function.  */
   cp_ref_qualifier rqual = REF_QUAL_NONE;
   /* cv-qualifiers that apply to the type specified by the DECLSPECS.  */
-  int type_quals = TYPE_UNQUALIFIED;
+  int type_quals = get_type_quals (declspecs);
   tree raises = NULL_TREE;
   int template_count = 0;
   tree returned_attrs = NULL_TREE;
@@ -10454,13 +10481,6 @@ grokdeclarator (const cp_declarator *declarator,
   if (concept_p)
     constexpr_p = true;
 
-  if (decl_spec_seq_has_spec_p (declspecs, ds_const))
-    type_quals |= TYPE_QUAL_CONST;
-  if (decl_spec_seq_has_spec_p (declspecs, ds_volatile))
-    type_quals |= TYPE_QUAL_VOLATILE;
-  if (decl_spec_seq_has_spec_p (declspecs, ds_restrict))
-    type_quals |= TYPE_QUAL_RESTRICT;
-
   if (decl_context == FUNCDEF)
     funcdef_flag = true, decl_context = NORMAL;
   else if (decl_context == MEMFUNCDEF)
@@ -10999,7 +11019,8 @@ grokdeclarator (const cp_declarator *declarator,
   if (decl_spec_seq_has_spec_p (declspecs, ds_complex))
     {
       if (TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE)
-	error ("complex invalid for %qs", name);
+	error_at (declspecs->locations[ds_complex],
+		  "complex invalid for %qs", name);
       /* If a modifier is specified, the resulting complex is the complex
 	 form of TYPE.  E.g, "complex short" is "complex short int".  */
       else if (type == integer_type_node)
@@ -11578,9 +11599,12 @@ grokdeclarator (const cp_declarator *declarator,
 		   virtual.  A constructor may not be static.
 		   A constructor may not be declared with ref-qualifier. */
 		if (staticp == 2)
-		  error ((flags == DTOR_FLAG)
-			 ? G_("destructor cannot be static member function")
-			 : G_("constructor cannot be static member function"));
+		  error_at (declspecs->locations[ds_storage_class],
+			    (flags == DTOR_FLAG)
+			    ? G_("destructor cannot be static member "
+				 "function")
+			    : G_("constructor cannot be static member "
+				 "function"));
 		if (memfn_quals)
 		  {
 		    error ((flags == DTOR_FLAG)
@@ -12438,7 +12462,7 @@ grokdeclarator (const cp_declarator *declarator,
 		&& (TREE_CODE (ctype) == UNION_TYPE
 		    || TREE_CODE (ctype) == QUAL_UNION_TYPE))
 	      {
-		error ("flexible array member in union");
+		error_at (id_loc, "flexible array member in union");
 		type = error_mark_node;
 	      }
 	    else
Index: testsuite/g++.dg/cpp1z/has-unique-obj-representations2.C
===================================================================
--- testsuite/g++.dg/cpp1z/has-unique-obj-representations2.C	(revision 273227)
+++ testsuite/g++.dg/cpp1z/has-unique-obj-representations2.C	(working copy)
@@ -1,7 +1,7 @@
 struct S;
 struct T { S t; };					// { dg-error "incomplete type" }
 struct U { int u[sizeof (S)]; };			// { dg-error "incomplete type" }
-union V { char c; char d[]; };				// { dg-error "flexible array member in union" }
+union V { char c; char d[]; };				// { dg-error "24:flexible array member in union" }
 bool a = __has_unique_object_representations (S);	// { dg-error "incomplete type" }
 bool b = __has_unique_object_representations (T);
 bool c = __has_unique_object_representations (U);
Index: testsuite/g++.dg/diagnostic/complex-invalid-1.C
===================================================================
--- testsuite/g++.dg/diagnostic/complex-invalid-1.C	(nonexistent)
+++ testsuite/g++.dg/diagnostic/complex-invalid-1.C	(working copy)
@@ -0,0 +1 @@
+__complex__ bool b;  // { dg-error "1:complex invalid" }
Index: testsuite/g++.dg/diagnostic/static-cdtor-1.C
===================================================================
--- testsuite/g++.dg/diagnostic/static-cdtor-1.C	(nonexistent)
+++ testsuite/g++.dg/diagnostic/static-cdtor-1.C	(working copy)
@@ -0,0 +1,5 @@
+struct S
+{
+  static S();  // { dg-error "3:constructor" }
+  static ~S();  // { dg-error "3:destructor" }
+};
Index: testsuite/g++.dg/other/anon-union3.C
===================================================================
--- testsuite/g++.dg/other/anon-union3.C	(revision 273227)
+++ testsuite/g++.dg/other/anon-union3.C	(working copy)
@@ -3,9 +3,9 @@
 class C
 {
   auto union      // { dg-error "storage class" "" { target { ! c++11 } } }
-    {		  // { dg-error "auto" "" { target c++11 } .-1 }
+    {		  // { dg-error "auto|multiple types" "" { target c++11 } .-1 }
       int a;
-    };            // { dg-error "multiple types" "" { target c++11 } }
+    };
   register union  // { dg-error "storage class" }
     {
       int b;
Index: testsuite/g++.dg/parse/error8.C
===================================================================
--- testsuite/g++.dg/parse/error8.C	(revision 273227)
+++ testsuite/g++.dg/parse/error8.C	(working copy)
@@ -5,5 +5,5 @@ struct A { friend typename struct B; };
 
 
 // { dg-error "28:expected nested-name-specifier before 'struct'" "expected" { target *-*-* } 4 }
-// { dg-error "35:multiple types in one declaration" "multiple" { target *-*-* } 4 }
+// { dg-error "19:multiple types in one declaration" "multiple" { target *-*-* } 4 }
 // { dg-error "12:friend declaration does not name a class or function" "friend decl" { target *-*-* } 4 }
Jason Merrill July 9, 2019, 9:03 p.m. | #4
On 7/9/19 6:10 AM, Paolo Carlini wrote:
> Hi,

> 

> On 08/07/19 23:44, Jason Merrill wrote:

>> On 6/23/19 7:58 AM, Paolo Carlini wrote:

>>> +    error_at (smallest_type_location (get_type_quals (declspecs),

>>> +                      declspecs->locations),

>> How about adding a smallest_type_location overload that just takes 

>> declspecs?

> 

> Sure. The below has an additional location fixlet which I noticed over 

> the last days, for "complex invalid for". Tested x86_64-linux, as usual.


OK, thanks.

Jason

Patch

Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 272584)
+++ cp/decl.c	(working copy)
@@ -100,6 +100,7 @@  static tree build_cp_library_fn (tree, enum tree_c
 static void store_parm_decls (tree);
 static void initialize_local_var (tree, tree);
 static void expand_static_init (tree, tree);
+static location_t smallest_type_location (int, const location_t*);
 
 /* The following symbols are subsumed in the cp_global_trees array, and
    listed here individually for documentation purposes.
@@ -4802,6 +4803,24 @@  warn_misplaced_attr_for_class_type (location_t loc
 	    class_type, class_key_or_enum_as_string (class_type));
 }
 
+/* Returns the cv-qualifiers that apply to the type specified
+   by the DECLSPECS.  */
+
+static int
+get_type_quals (const cp_decl_specifier_seq *declspecs)
+{
+  int type_quals = TYPE_UNQUALIFIED;
+
+  if (decl_spec_seq_has_spec_p (declspecs, ds_const))
+    type_quals |= TYPE_QUAL_CONST;
+  if (decl_spec_seq_has_spec_p (declspecs, ds_volatile))
+    type_quals |= TYPE_QUAL_VOLATILE;
+  if (decl_spec_seq_has_spec_p (declspecs, ds_restrict))
+    type_quals |= TYPE_QUAL_RESTRICT;
+
+  return type_quals;
+}
+
 /* Make sure that a declaration with no declarator is well-formed, i.e.
    just declares a tagged type or anonymous union.
 
@@ -4821,7 +4840,9 @@  check_tag_decl (cp_decl_specifier_seq *declspecs,
   bool error_p = false;
 
   if (declspecs->multiple_types_p)
-    error ("multiple types in one declaration");
+    error_at (smallest_type_location (get_type_quals (declspecs),
+				      declspecs->locations),
+	      "multiple types in one declaration");
   else if (declspecs->redefined_builtin_type)
     {
       if (!in_system_header_at (input_location))
@@ -10403,7 +10424,7 @@  grokdeclarator (const cp_declarator *declarator,
      a member function.  */
   cp_ref_qualifier rqual = REF_QUAL_NONE;
   /* cv-qualifiers that apply to the type specified by the DECLSPECS.  */
-  int type_quals = TYPE_UNQUALIFIED;
+  int type_quals = get_type_quals (declspecs);
   tree raises = NULL_TREE;
   int template_count = 0;
   tree returned_attrs = NULL_TREE;
@@ -10449,13 +10470,6 @@  grokdeclarator (const cp_declarator *declarator,
   if (concept_p)
     constexpr_p = true;
 
-  if (decl_spec_seq_has_spec_p (declspecs, ds_const))
-    type_quals |= TYPE_QUAL_CONST;
-  if (decl_spec_seq_has_spec_p (declspecs, ds_volatile))
-    type_quals |= TYPE_QUAL_VOLATILE;
-  if (decl_spec_seq_has_spec_p (declspecs, ds_restrict))
-    type_quals |= TYPE_QUAL_RESTRICT;
-
   if (decl_context == FUNCDEF)
     funcdef_flag = true, decl_context = NORMAL;
   else if (decl_context == MEMFUNCDEF)
@@ -11571,9 +11585,12 @@  grokdeclarator (const cp_declarator *declarator,
 		   virtual.  A constructor may not be static.
 		   A constructor may not be declared with ref-qualifier. */
 		if (staticp == 2)
-		  error ((flags == DTOR_FLAG)
-			 ? G_("destructor cannot be static member function")
-			 : G_("constructor cannot be static member function"));
+		  error_at (declspecs->locations[ds_storage_class],
+			    (flags == DTOR_FLAG)
+			    ? G_("destructor cannot be static member "
+				 "function")
+			    : G_("constructor cannot be static member "
+				 "function"));
 		if (memfn_quals)
 		  {
 		    error ((flags == DTOR_FLAG)
@@ -12431,7 +12448,7 @@  grokdeclarator (const cp_declarator *declarator,
 		&& (TREE_CODE (ctype) == UNION_TYPE
 		    || TREE_CODE (ctype) == QUAL_UNION_TYPE))
 	      {
-		error ("flexible array member in union");
+		error_at (id_loc, "flexible array member in union");
 		type = error_mark_node;
 	      }
 	    else
Index: testsuite/g++.dg/cpp1z/has-unique-obj-representations2.C
===================================================================
--- testsuite/g++.dg/cpp1z/has-unique-obj-representations2.C	(revision 272583)
+++ testsuite/g++.dg/cpp1z/has-unique-obj-representations2.C	(working copy)
@@ -1,7 +1,7 @@ 
 struct S;
 struct T { S t; };					// { dg-error "incomplete type" }
 struct U { int u[sizeof (S)]; };			// { dg-error "incomplete type" }
-union V { char c; char d[]; };				// { dg-error "flexible array member in union" }
+union V { char c; char d[]; };				// { dg-error "24:flexible array member in union" }
 bool a = __has_unique_object_representations (S);	// { dg-error "incomplete type" }
 bool b = __has_unique_object_representations (T);
 bool c = __has_unique_object_representations (U);
Index: testsuite/g++.dg/diagnostic/static-cdtor-1.C
===================================================================
--- testsuite/g++.dg/diagnostic/static-cdtor-1.C	(nonexistent)
+++ testsuite/g++.dg/diagnostic/static-cdtor-1.C	(working copy)
@@ -0,0 +1,5 @@ 
+struct S
+{
+  static S();  // { dg-error "3:constructor" }
+  static ~S();  // { dg-error "3:destructor" }
+};
Index: testsuite/g++.dg/other/anon-union3.C
===================================================================
--- testsuite/g++.dg/other/anon-union3.C	(revision 272583)
+++ testsuite/g++.dg/other/anon-union3.C	(working copy)
@@ -3,9 +3,9 @@ 
 class C
 {
   auto union      // { dg-error "storage class" "" { target { ! c++11 } } }
-    {		  // { dg-error "auto" "" { target c++11 } .-1 }
+    {		  // { dg-error "auto|multiple types" "" { target c++11 } .-1 }
       int a;
-    };            // { dg-error "multiple types" "" { target c++11 } }
+    };
   register union  // { dg-error "storage class" }
     {
       int b;
Index: testsuite/g++.dg/parse/error8.C
===================================================================
--- testsuite/g++.dg/parse/error8.C	(revision 272583)
+++ testsuite/g++.dg/parse/error8.C	(working copy)
@@ -5,5 +5,5 @@  struct A { friend typename struct B; };
 
 
 // { dg-error "28:expected nested-name-specifier before 'struct'" "expected" { target *-*-* } 4 }
-// { dg-error "35:multiple types in one declaration" "multiple" { target *-*-* } 4 }
+// { dg-error "19:multiple types in one declaration" "multiple" { target *-*-* } 4 }
 // { dg-error "12:friend declaration does not name a class or function" "friend decl" { target *-*-* } 4 }