[patch] C++: locations for function declarations

Aldy Hernandez aldyh@redhat.com
Fri Sep 12 15:35:00 GMT 2008


Hi folks.

This patch provides correct column information for C++ function
definitions.  This is the C++ counterpart for my recent committed patch
of:

	http://gcc.gnu.org/ml/gcc-patches/2008-09/msg00649.html

For C++ I have used the id_loc field in `struct cp_declarator' which is
currently only used for cdk_id's.  I have now expanded it to get set for
cdk_functions as well.  This seemed a lot cleaner than either adding
another field somewhere, or passing a new argument to the slew of
cp_*declarator* functions.

With this patch, errors are now correctly reported on the function's
name, while retaining the prologue location at the function brace.

I have tested this patch on x86_64 Linux for *both* the GCC and GDB
testsuites.

OK for mainline?

Aldy

testsuite/
	* g++.old-deja/g++.brendan/crash16.C: Function name is the correct 
	location for an error regarding a function.
	* g++.old-deja/g++.other/pmf3.C: Same.
	* g++.old-deja/g++.law/ctors5.C: Same.
	* g++.old-deja/g++.pt/explicit34.C: Same.
	* g++.dg/parse/error28.C: Same.
	* g++.dg/parse/error17.C: Same.
	* g++.dg/template/friend44.C: Same.
cp/
	* decl.c (duplicate_decls): Call error_at.
	(grokfndecl): New location argument.  Use location if available.
	(grokdeclarator): Pass declarator location to grokfndecl.
	* cp-tree.h (struct cp_declarator): Update comment for id_loc.
	* decl2.c (check_classfn): Use error_at.
	* parser.c (cp_parser_init_declarator): Set function_start_locus
	to brace location.
	(cp_parser_member_declaration): Set id_loc for function declarators.

Index: testsuite/g++.old-deja/g++.brendan/crash16.C
===================================================================
--- testsuite/g++.old-deja/g++.brendan/crash16.C	(revision 140319)
+++ testsuite/g++.old-deja/g++.brendan/crash16.C	(working copy)
@@ -5,10 +5,10 @@
 class Graph { // { dg-error "1: error: new types|1: note: \\(perhaps" }
 public:
       unsigned         char N;
-      Graph(void) {} // { dg-error "17: error: 'Graph" }
+      Graph(void) {} // { dg-error "7: error: 'Graph" }
 }
 
-Graph::Graph(void) // { dg-error "18: error: return type|18: error: redefinition" }
+Graph::Graph(void) // { dg-error "18: error: return type|1: error: redefinition" }
 {    N = 10;
 }
 
Index: testsuite/g++.old-deja/g++.other/pmf3.C
===================================================================
--- testsuite/g++.old-deja/g++.other/pmf3.C	(revision 140319)
+++ testsuite/g++.old-deja/g++.other/pmf3.C	(working copy)
@@ -3,9 +3,9 @@
 // Bug: g++ was crashing after giving errors.
 
 template<class T>
-  void connect_to_method(
+  void connect_to_method( // { dg-error "candidates are" }
     T *receiver,
-    void (T::*method)()) // { dg-error "candidates are" }
+    void (T::*method)())
   {}
 
 class Gtk_Base
Index: testsuite/g++.old-deja/g++.law/ctors5.C
===================================================================
--- testsuite/g++.old-deja/g++.law/ctors5.C	(revision 140319)
+++ testsuite/g++.old-deja/g++.law/ctors5.C	(working copy)
@@ -21,7 +21,7 @@ class Y // { dg-error "1: error: new typ
   public:
     Y();
 }
-X::X( int xi ) // { dg-error "14: error: return type specification for constructor invalid|14: note: candidates are: X::X\\(int\\)" }
+X::X( int xi ) // { dg-error "14: error: return type specification for constructor invalid|1: note: candidates are: X::X\\(int\\)" }
 {
     x = xi;
 }
Index: testsuite/g++.old-deja/g++.pt/explicit34.C
===================================================================
--- testsuite/g++.old-deja/g++.pt/explicit34.C	(revision 140319)
+++ testsuite/g++.old-deja/g++.pt/explicit34.C	(working copy)
@@ -1,10 +1,11 @@
 // { dg-do assemble  }
+// { dg-options "-fshow-column" }
 // GROUPS passed templates
 template <class T>
 void foo(T t);
 
 template <>
-void foo(int) {}; // { dg-error "" } previously defined here.
+void foo(int) {}; // { dg-error "6:" } previously defined here.
 
 template <>
-void foo<int>(int) {} // { dg-error "" } duplicate specialization.
+void foo<int>(int) {} // { dg-error "6:" } duplicate specialization.
Index: testsuite/g++.dg/parse/error28.C
===================================================================
--- testsuite/g++.dg/parse/error28.C	(revision 140319)
+++ testsuite/g++.dg/parse/error28.C	(working copy)
@@ -3,7 +3,7 @@
 
 struct virt { virt () {} virt (int i) {} };
 struct der : public virtual virt { // { dg-error "34: note:                 der::der" }
-  der (int i) : virt(i) {} // { dg-error "13: note: candidates are: der" }
+  der (int i) : virt(i) {} // { dg-error "3: note: candidates are: der" }
 };
 struct top : public der { 
   top () {} // { dg-bogus "der\\(const" }
Index: testsuite/g++.dg/parse/error17.C
===================================================================
--- testsuite/g++.dg/parse/error17.C	(revision 140319)
+++ testsuite/g++.dg/parse/error17.C	(working copy)
@@ -2,7 +2,7 @@
 // PR c++/16965
 
 template <typename T> struct B { 
-  static int Bar(T); // { dg-error "19: error: candidates are: |19: error:  " }
+  static int Bar(T); // { dg-error "14: error: candidates are: |14: error:  " }
 }; 
 struct D : B<int>, B<char> {}; 
  
Index: testsuite/g++.dg/template/friend44.C
===================================================================
--- testsuite/g++.dg/template/friend44.C	(revision 140319)
+++ testsuite/g++.dg/template/friend44.C	(working copy)
@@ -1,8 +1,9 @@
+// { dg-options "-fshow-column" }
 //PR c++/28260
 
 template<int> struct A
 {
-  friend int foo(); // { dg-error "new declaration" }
+  friend int foo(); // { dg-error "14: error: new declaration" }
 };
 
-void foo() { A<0> a; } // { dg-error "ambiguates old declaration" } 
+void foo() { A<0> a; } // { dg-error "6: error: ambiguates old declaration" } 
Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 140319)
+++ cp/decl.c	(working copy)
@@ -1459,7 +1459,7 @@ duplicate_decls (tree newdecl, tree oldd
       const char *errmsg = redeclaration_error_message (newdecl, olddecl);
       if (errmsg)
 	{
-	  error (errmsg, newdecl);
+	  error_at (DECL_SOURCE_LOCATION (newdecl), errmsg, newdecl);
 	  if (DECL_NAME (olddecl) != NULL_TREE)
 	    error ((DECL_INITIAL (olddecl) && namespace_bindings_p ())
 			 ? "%q+#D previously defined here"
@@ -6497,7 +6497,8 @@ grokfndecl (tree ctype,
 	    bool funcdef_flag,
 	    int template_count,
 	    tree in_namespace,
-	    tree* attrlist)
+	    tree* attrlist,
+	    location_t location)
 {
   tree decl;
   int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
@@ -6507,6 +6508,12 @@ grokfndecl (tree ctype,
     type = build_exception_variant (type, raises);
 
   decl = build_lang_decl (FUNCTION_DECL, declarator, type);
+
+  /* If we have an explicit location, use it, otherwise use whatever
+     build_lang_decl used (probably input_location).  */
+  if (location != UNKNOWN_LOCATION)
+    DECL_SOURCE_LOCATION (decl) = location;
+
   if (TREE_CODE (type) == METHOD_TYPE)
     {
       tree parm;
@@ -9018,7 +9025,8 @@ grokdeclarator (const cp_declarator *dec
 			       virtualp, flags, memfn_quals, raises,
 			       friendp ? -1 : 0, friendp, publicp, inlinep,
 			       sfk,
-			       funcdef_flag, template_count, in_namespace, attrlist);
+			       funcdef_flag, template_count, in_namespace,
+			       attrlist, declarator->id_loc);
 	    if (decl == NULL_TREE)
 	      return error_mark_node;
 #if 0
@@ -9060,7 +9068,8 @@ grokdeclarator (const cp_declarator *dec
 			       virtualp, flags, memfn_quals, raises,
 			       friendp ? -1 : 0, friendp, 1, 0, sfk,
 			       funcdef_flag, template_count, in_namespace,
-			       attrlist);
+			       attrlist,
+			       declarator->id_loc);
 	    if (decl == NULL_TREE)
 	      return error_mark_node;
 	  }
@@ -9255,7 +9264,8 @@ grokdeclarator (const cp_declarator *dec
 			   virtualp, flags, memfn_quals, raises,
 			   1, friendp,
 			   publicp, inlinep, sfk, funcdef_flag,
-			   template_count, in_namespace, attrlist);
+			   template_count, in_namespace, attrlist,
+			   declarator->id_loc);
 	if (decl == NULL_TREE)
 	  return error_mark_node;
 
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h	(revision 140319)
+++ cp/cp-tree.h	(working copy)
@@ -4089,7 +4089,7 @@ struct cp_declarator {
   /* For all but cdk_id and cdk_error, the contained declarator.  For
      cdk_id and cdk_error, guaranteed to be NULL.  */
   cp_declarator *declarator;
-  location_t id_loc; /* Currently only set for cdk_id. */
+  location_t id_loc; /* Currently only set for cdk_id and cdk_function. */
   union {
     /* For identifiers.  */
     struct {
Index: cp/decl2.c
===================================================================
--- cp/decl2.c	(revision 140319)
+++ cp/decl2.c	(working copy)
@@ -638,8 +638,9 @@ check_classfn (tree ctype, tree function
 	  return OVL_CURRENT (fndecls);
 	}
       
-      error ("prototype for %q#D does not match any in class %qT",
-	     function, ctype);
+      error_at (DECL_SOURCE_LOCATION (function),
+		"prototype for %q#D does not match any in class %qT",
+		function, ctype);
       is_conv_op = DECL_CONV_FN_P (fndecl);
 
       if (is_conv_op)
Index: cp/parser.c
===================================================================
--- cp/parser.c	(revision 140319)
+++ cp/parser.c	(working copy)
@@ -12563,6 +12563,9 @@ cp_parser_init_declarator (cp_parser* pa
 	}
       else
 	{
+	  location_t func_brace_location
+	    = cp_lexer_peek_token (parser->lexer)->location;
+
 	  /* Neither attributes nor an asm-specification are allowed
 	     on a function-definition.  */
 	  if (asm_specification)
@@ -12586,6 +12589,13 @@ cp_parser_init_declarator (cp_parser* pa
 	      = (cp_parser_function_definition_from_specifiers_and_declarator
 		 (parser, decl_specifiers, prefix_attributes, declarator));
 
+	  if (decl != error_mark_node && DECL_STRUCT_FUNCTION (decl))
+	    {
+	      /* This is where the prologue starts...  */
+	      DECL_STRUCT_FUNCTION (decl)->function_start_locus
+		= func_brace_location;
+	    }
+
 	  return decl;
 	}
     }
@@ -15791,6 +15801,8 @@ cp_parser_member_declaration (cp_parser*
 		  return;
 		}
 	      else
+		if (declarator->kind == cdk_function)
+		  declarator->id_loc = token->location;
 		/* Create the declaration.  */
 		decl = grokfield (declarator, &decl_specifiers,
 				  initializer, /*init_const_expr_p=*/true,



More information about the Gcc-patches mailing list