[C++] Fix some locations

Message ID efd12365-35b4-41a6-d919-1fadef556c2d@oracle.com
State New
Headers show
Series
  • [C++] Fix some locations
Related show

Commit Message

Paolo Carlini June 1, 2018, 9:03 p.m.
Hi,

while working on some bugs I noticed that in a few places in decl.c we 
could do better in terms of locations within the current infrastructure, 
some simple, straightforward improvements. I'm attaching below a tiny 
first patch, more to follow, I hope.

For example, a function which could be improved in many places is 
grok_ctor_properties and, before going ahead, I'd like to ask about 
something I noticed yesterday:

   /* There can be no default arguments.  */
   for (tree arg = argtypes; arg != void_list_node; arg = TREE_CHAIN (arg))
     if (TREE_PURPOSE (arg))
       {
         TREE_PURPOSE (arg) = NULL_TREE;
         if (operator_code == POSTINCREMENT_EXPR
             || operator_code == POSTDECREMENT_EXPR)
           pedwarn (input_location, OPT_Wpedantic,
                    "%qD cannot have default arguments", decl);
         else
           {
             error ("%qD cannot have default arguments", decl);
             return false;
           }
       }

the special casing seems weird, so far I haven't been able to find 
anything in the standard about it and all the other compilers I have at 
hand (Oracle, Intel, Clang) don't seem to have it. Shall we keep it or 
not? Maybe with an additional comment explaining the rationale? The 
affected testcases would be parse/defarg11.C and g++.jason/operator.C.

Thanks, Paolo.

///////////////////
/cp
2018-06-01  Paolo Carlini  <paolo.carlini@oracle.com>

	* decl.c (grokfndecl): Use the location_t argument in two more places.

/testsuite
2018-06-01  Paolo Carlini  <paolo.carlini@oracle.com>

	* g++.dg/template/friend64.C: New.
	* g++.old-deja/g++.other/friend4.C: Test the location too.
	* g++.old-deja/g++.pt/crash23.C: Likewise.

Comments

Jason Merrill June 1, 2018, 9:29 p.m. | #1
On Fri, Jun 1, 2018 at 5:03 PM, Paolo Carlini <paolo.carlini@oracle.com> wrote:
> while working on some bugs I noticed that in a few places in decl.c we could

> do better in terms of locations within the current infrastructure, some

> simple, straightforward improvements. I'm attaching below a tiny first

> patch, more to follow, I hope.

>

> For example, a function which could be improved in many places is

> grok_ctor_properties and, before going ahead, I'd like to ask about

> something I noticed yesterday:

>

>   /* There can be no default arguments.  */

>   for (tree arg = argtypes; arg != void_list_node; arg = TREE_CHAIN (arg))

>     if (TREE_PURPOSE (arg))

>       {

>         TREE_PURPOSE (arg) = NULL_TREE;

>         if (operator_code == POSTINCREMENT_EXPR

>             || operator_code == POSTDECREMENT_EXPR)

>           pedwarn (input_location, OPT_Wpedantic,

>                    "%qD cannot have default arguments", decl);

>         else

>           {

>             error ("%qD cannot have default arguments", decl);

>             return false;

>           }

>       }

>

> the special casing seems weird, so far I haven't been able to find anything

> in the standard about it and all the other compilers I have at hand (Oracle,

> Intel, Clang) don't seem to have it. Shall we keep it or not? Maybe with an

> additional comment explaining the rationale? The affected testcases would be

> parse/defarg11.C and g++.jason/operator.C.


I think in the olden days, with a default argument one function could
support both prefix and postfix inc/decrement syntax:

struct A {
  A& operator++(int = 0);
};

int main()
{
  A a;
  ++a;
  a++;
}

...but that hasn't actually worked in forever, so it shouldn't be a
problem to make the ++ case an error, too.

Jason
Paolo Carlini June 4, 2018, 8:32 a.m. | #2
Hi,

On 01/06/2018, 23:29, Jason Merrill wrote:
> On Fri, Jun 1, 2018 at 5:03 PM, Paolo Carlini <paolo.carlini@oracle.com> wrote:

>> while working on some bugs I noticed that in a few places in decl.c we could

>> do better in terms of locations within the current infrastructure, some

>> simple, straightforward improvements. I'm attaching below a tiny first

>> patch, more to follow, I hope.

>>

>> For example, a function which could be improved in many places is

>> grok_ctor_properties and, before going ahead, I'd like to ask about

>> something I noticed yesterday:

>>

>>    /* There can be no default arguments.  */

>>    for (tree arg = argtypes; arg != void_list_node; arg = TREE_CHAIN (arg))

>>      if (TREE_PURPOSE (arg))

>>        {

>>          TREE_PURPOSE (arg) = NULL_TREE;

>>          if (operator_code == POSTINCREMENT_EXPR

>>              || operator_code == POSTDECREMENT_EXPR)

>>            pedwarn (input_location, OPT_Wpedantic,

>>                     "%qD cannot have default arguments", decl);

>>          else

>>            {

>>              error ("%qD cannot have default arguments", decl);

>>              return false;

>>            }

>>        }

>>

>> the special casing seems weird, so far I haven't been able to find anything

>> in the standard about it and all the other compilers I have at hand (Oracle,

>> Intel, Clang) don't seem to have it. Shall we keep it or not? Maybe with an

>> additional comment explaining the rationale? The affected testcases would be

>> parse/defarg11.C and g++.jason/operator.C.

> I think in the olden days, with a default argument one function could

> support both prefix and postfix inc/decrement syntax:

>

> struct A {

>    A& operator++(int = 0);

> };

>

> int main()

> {

>    A a;

>    ++a;

>    a++;

> }

>

> ...but that hasn't actually worked in forever, so it shouldn't be a

> problem to make the ++ case an error, too.

Thanks for the explanation. If we can remove the special casing, fixing 
some other issues will be easier, for example setting TREE_PURPOSE 
unconditionally error_mark_node fixes a Bugzilla bug (I don't have the 
number with me, more when I'm back home next week ;)

Thanks,
Paolo.

Patch

Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 261078)
+++ cp/decl.c	(working copy)
@@ -8674,8 +8674,9 @@  grokfndecl (tree ctype,
   if (friendp && TREE_CODE (orig_declarator) == TEMPLATE_ID_EXPR)
     {
       if (funcdef_flag)
-	error ("defining explicit specialization %qD in friend declaration",
-	       orig_declarator);
+	error_at (location,
+		  "defining explicit specialization %qD in friend declaration",
+		  orig_declarator);
       else
 	{
 	  tree fns = TREE_OPERAND (orig_declarator, 0);
@@ -8684,9 +8685,10 @@  grokfndecl (tree ctype,
 	  if (PROCESSING_REAL_TEMPLATE_DECL_P ())
 	    {
 	      /* Something like `template <class T> friend void f<T>()'.  */
-	      error ("invalid use of template-id %qD in declaration "
-		     "of primary template",
-		     orig_declarator);
+	      error_at (location,
+			"invalid use of template-id %qD in declaration "
+			"of primary template",
+			orig_declarator);
 	      return NULL_TREE;
 	    }
 
Index: testsuite/g++.dg/template/friend64.C
===================================================================
--- testsuite/g++.dg/template/friend64.C	(nonexistent)
+++ testsuite/g++.dg/template/friend64.C	(working copy)
@@ -0,0 +1,6 @@ 
+template <class T> void foo (int);
+
+template <class T>
+class Q {
+  friend void foo<T> (int) { }  // { dg-error "15:defining explicit specialization" }
+};
Index: testsuite/g++.old-deja/g++.other/friend4.C
===================================================================
--- testsuite/g++.old-deja/g++.other/friend4.C	(revision 261078)
+++ testsuite/g++.old-deja/g++.other/friend4.C	(working copy)
@@ -11,7 +11,7 @@ 
 template <class A, class B> void foo();
 template <class C> class bar {
   int i; // { dg-message "" } private
-  template <class B> friend void foo<C,B>(); // { dg-error "" } bogus declaration
+  template <class B> friend void foo<C,B>(); // { dg-error "34:invalid use of template-id" }
 };
 template <class A, class B> void foo() {
   bar<A> baz; baz.i = 1;   // { dg-error "" } foo cannot access bar<int>::i
Index: testsuite/g++.old-deja/g++.pt/crash23.C
===================================================================
--- testsuite/g++.old-deja/g++.pt/crash23.C	(revision 261078)
+++ testsuite/g++.old-deja/g++.pt/crash23.C	(working copy)
@@ -4,7 +4,7 @@  template <class A, class B> void foo();
 template <class C> class bar {
 public:
   int i;
-  template <class B> friend void foo<C,B>(); // { dg-error "" } template-id
+  template <class B> friend void foo<C,B>(); // { dg-error "34:invalid use of template-id" }
 };
 template <class A, class B> void foo() {
   bar<A> baz; baz.i = 1;