diff mbox

C, C++: Fix PR 69733 (bad location for ignored qualifiers warning)

Message ID 571A2697.4050208@t-online.de
State New
Headers show

Commit Message

Bernd Schmidt April 22, 2016, 1:26 p.m. UTC
The PR is for a C++ form of the form

const double val() const { ... }

where the warning location is at the second const (by accident, in 
reality it's just past the function's declarator), while the first const 
is the one that we are warning about.

This patch adds some logic to the C and C++ frontends to look for the 
qualifier, or a typedef name, and point the warning there. C needs a 
little more work because the ignored qualifier could also be an address 
space.

Bootstrapped and tested on x86_64-linux (a while ago, will retest). Ok 
for trunk?


Bernd

Comments

Jason Merrill April 22, 2016, 2 p.m. UTC | #1
The C++ change is OK.

Jason
Joseph Myers April 25, 2016, 8:18 p.m. UTC | #2
On Fri, 22 Apr 2016, Bernd Schmidt wrote:

> +/* Returns the smallest location != UNKNOWN_LOCATION in LOCATIONS,
> +   considering only those c_declspec_words found in LIST, which
> +   must be terminated by cdw_number_of_elements.  */
> +
> +static location_t
> +smallest_type_quals_location (const location_t* locations,
> +			      c_declspec_word *list)

I'd expect list to be a pointer to const...

> @@ -6101,6 +6122,18 @@ grokdeclarator (const struct c_declarato
>  	       qualify the return type, not the function type.  */
>  	    if (type_quals)
>  	      {
> +		enum c_declspec_word ignored_quals_list[] =
> +		  {
> +		    cdw_const, cdw_volatile, cdw_restrict, cdw_address_space,
> +		    cdw_number_of_elements
> +		  };

 ... and ignored_quals_list to be static const here.
diff mbox

Patch

c/
	PR c++/69733
	* c-decl.c (smallest_type_quals_location): New static function.
	(grokdeclarator): Try to find the correct location for an ignored
	qualifier.
cp/
	PR c++/69733
	* decl.c (grokdeclarator): Try to find the correct location for an
	ignored qualifier.
testsuite/
	PR c++/69733
	* c-c++-common/pr69733.c: New test.
	* gcc.target/i386/pr69733.c: New test.

Index: gcc/c/c-decl.c
===================================================================
--- gcc/c/c-decl.c	(revision 234183)
+++ gcc/c/c-decl.c	(working copy)
@@ -5291,6 +5291,27 @@  warn_defaults_to (location_t location, i
   va_end (ap);
 }
 
+/* Returns the smallest location != UNKNOWN_LOCATION in LOCATIONS,
+   considering only those c_declspec_words found in LIST, which
+   must be terminated by cdw_number_of_elements.  */
+
+static location_t
+smallest_type_quals_location (const location_t* locations,
+			      c_declspec_word *list)
+{
+  location_t loc = UNKNOWN_LOCATION;
+  while (*list != cdw_number_of_elements)
+    {
+      location_t newloc = locations[*list];
+      if (loc == UNKNOWN_LOCATION
+	  || (newloc != UNKNOWN_LOCATION && newloc < loc))
+	loc = newloc;
+      list++;
+    }
+
+  return loc;
+}
+
 /* Given declspecs and a declarator,
    determine the name and type of the object declared
    and construct a ..._DECL node for it.
@@ -6101,6 +6122,18 @@  grokdeclarator (const struct c_declarato
 	       qualify the return type, not the function type.  */
 	    if (type_quals)
 	      {
+		enum c_declspec_word ignored_quals_list[] =
+		  {
+		    cdw_const, cdw_volatile, cdw_restrict, cdw_address_space,
+		    cdw_number_of_elements
+		  };
+		location_t specs_loc
+		    = smallest_type_quals_location (declspecs->locations,
+						    ignored_quals_list);
+		if (specs_loc == UNKNOWN_LOCATION)
+		  specs_loc = declspecs->locations[cdw_typedef];
+		if (specs_loc == UNKNOWN_LOCATION)
+		  specs_loc = loc;
 		/* Type qualifiers on a function return type are
 		   normally permitted by the standard but have no
 		   effect, so give a warning at -Wreturn-type.
@@ -6108,10 +6141,10 @@  grokdeclarator (const struct c_declarato
 		   function definitions in ISO C; GCC used to used
 		   them for noreturn functions.  */
 		if (VOID_TYPE_P (type) && really_funcdef)
-		  pedwarn (loc, 0,
+		  pedwarn (specs_loc, 0,
 			   "function definition has qualified void return type");
 		else
-		  warning_at (loc, OPT_Wignored_qualifiers,
+		  warning_at (specs_loc, OPT_Wignored_qualifiers,
 			   "type qualifiers ignored on function return type");
 
 		type = c_build_qualified_type (type, type_quals);
Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c	(revision 234183)
+++ gcc/cp/decl.c	(working copy)
@@ -10010,8 +10010,15 @@  grokdeclarator (const cp_declarator *dec
 	    if (type_quals != TYPE_UNQUALIFIED)
 	      {
 		if (SCALAR_TYPE_P (type) || VOID_TYPE_P (type))
-		  warning (OPT_Wignored_qualifiers,
-			   "type qualifiers ignored on function return type");
+		  {
+		    location_t loc;
+		    loc = smallest_type_quals_location (type_quals,
+							declspecs->locations);
+		    if (loc == UNKNOWN_LOCATION)
+		      loc = declspecs->locations[ds_type_spec];
+		    warning_at (loc, OPT_Wignored_qualifiers, "type "
+				"qualifiers ignored on function return type");
+		  }
 		/* We now know that the TYPE_QUALS don't apply to the
 		   decl, but to its return type.  */
 		type_quals = TYPE_UNQUALIFIED;
Index: gcc/testsuite/c-c++-common/pr69733.c
===================================================================
--- gcc/testsuite/c-c++-common/pr69733.c	(revision 0)
+++ gcc/testsuite/c-c++-common/pr69733.c	(working copy)
@@ -0,0 +1,24 @@ 
+/* { dg-do compile } */
+/* { dg-options "-W -fdiagnostics-show-caret" } */
+
+typedef const double cd;
+double val;
+
+const double val0() {return val;} /* { dg-warning "qualifiers ignored" } */
+/* { dg-begin-multiline-output "" }
+ const double val0() {return val;}
+ ^~~~~
+{ dg-end-multiline-output "" } */
+
+volatile double val1() {return val;} /* { dg-warning "qualifiers ignored" } */
+/* { dg-begin-multiline-output "" }
+ volatile double val1() {return val;}
+ ^~~~~~~~
+{ dg-end-multiline-output "" } */
+
+cd val2() {return val;} /* { dg-warning "qualifiers ignored" } */
+/* { dg-begin-multiline-output "" }
+ cd val2() {return val;}
+ ^~
+{ dg-end-multiline-output "" } */
+
Index: gcc/testsuite/gcc.target/i386/pr69733.c
===================================================================
--- gcc/testsuite/gcc.target/i386/pr69733.c	(revision 0)
+++ gcc/testsuite/gcc.target/i386/pr69733.c	(working copy)
@@ -0,0 +1,30 @@ 
+/* { dg-do compile } */
+/* { dg-options "-W -fdiagnostics-show-caret" } */
+
+typedef const double cd;
+double val;
+
+const double val0() {return val;} /* { dg-warning "qualifiers ignored" } */
+/* { dg-begin-multiline-output "" }
+ const double val0() {return val;}
+ ^~~~~
+{ dg-end-multiline-output "" } */
+
+volatile double val1() {return val;} /* { dg-warning "qualifiers ignored" } */
+/* { dg-begin-multiline-output "" }
+ volatile double val1() {return val;}
+ ^~~~~~~~
+{ dg-end-multiline-output "" } */
+
+cd val2() {return val;} /* { dg-warning "qualifiers ignored" } */
+/* { dg-begin-multiline-output "" }
+ cd val2() {return val;}
+ ^~
+{ dg-end-multiline-output "" } */
+
+__seg_fs int val3() {return val;} /* { dg-warning "qualifiers ignored" } */
+/* { dg-begin-multiline-output "" }
+ __seg_fs int val3() {return val;}
+ ^~~~~~~~
+{ dg-end-multiline-output "" } */
+