[C++] Improve grokfndecl locations

Message ID a70154a4-30bc-9881-77c9-51172e0afe9f@oracle.com
State New
Headers show
Series
  • [C++] Improve grokfndecl locations
Related show

Commit Message

Paolo Carlini June 19, 2018, 8:55 p.m.
Hi,

the below implements a couple of independent ideas. First, adds a const 
cp_decl_specifier_seq * parameter, similarly to grokvardecl: this way 
the function has available locations[ds_inline], 
locations[ds_constexpr], locations[ds_type_spec] which can use in some 
error messages. Second, the handling of an UNKNOWN_LOCATION as 
location_t argument is reworked a bit - in particular the "deprecated" 
build_lang_decl call is changed to build_lang_decl_loc: everything I 
already tweaked in the function about locations should be now 100% 
correct + the use of the location_t argument can be safely extended to a 
couple of additional places. Tested x86_64-linux.

Thanks, Paolo.

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

	* decl.c (grokfndecl): Add const cp_decl_specifier_seq* parameter;
	tidy handling of a null location_t argument; use proper location
	information in a few additional error messages.
	(grokdeclarator): Update calls.

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

	* g++.dg/template/friend65.C: New.
	* g++.dg/cpp0x/main1.C: Likewise.
	* g++.dg/other/main2.C: Likewise.
	* g++.dg/other/main3.C: Likewise.
	* g++.dg/warn/main-2.C: Update.

Comments

Jason Merrill June 20, 2018, 3:45 p.m. | #1
On Tue, Jun 19, 2018 at 4:55 PM, Paolo Carlini <paolo.carlini@oracle.com> wrote:
> Hi,

>

> the below implements a couple of independent ideas. First, adds a const

> cp_decl_specifier_seq * parameter, similarly to grokvardecl: this way the

> function has available locations[ds_inline], locations[ds_constexpr],

> locations[ds_type_spec] which can use in some error messages. Second, the

> handling of an UNKNOWN_LOCATION as location_t argument is reworked a bit -

> in particular the "deprecated" build_lang_decl call is changed to

> build_lang_decl_loc: everything I already tweaked in the function about

> locations should be now 100% correct + the use of the location_t argument

> can be safely extended to a couple of additional places. Tested

> x86_64-linux.


>+       error_at (location,

>+                 "default arguments are not allowed in declaration "

>+                 "of friend template specialization %qD",

>+                 decl);


You can use defarg_location (or location_of) for the location of a
default argument.  OK with that change.

Jason

Patch

Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 261732)
+++ cp/decl.c	(working copy)
@@ -8591,6 +8591,7 @@  grokfndecl (tree ctype,
 	    tree declarator,
 	    tree parms,
 	    tree orig_declarator,
+	    const cp_decl_specifier_seq *declspecs,
 	    tree decl_reqs,
 	    int virtualp,
 	    enum overload_flags flags,
@@ -8614,6 +8615,9 @@  grokfndecl (tree ctype,
   int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
   tree t;
 
+  if (location == UNKNOWN_LOCATION)
+    location = input_location;
+
   // Was the concept specifier present?
   bool concept_p = inlinep & 4;
 
@@ -8620,13 +8624,13 @@  grokfndecl (tree ctype,
   // Concept declarations must have a corresponding definition.
   if (concept_p && !funcdef_flag)
     {
-      error ("concept %qD has no definition", declarator);
+      error_at (location, "concept %qD has no definition", declarator);
       return NULL_TREE;
     }
 
   type = build_cp_fntype_variant (type, rqual, raises, late_return_type_p);
 
-  decl = build_lang_decl (FUNCTION_DECL, declarator, type);
+  decl = build_lang_decl_loc (location, FUNCTION_DECL, declarator, type);
 
   /* Set the constraints on the declaration. */
   if (flag_concepts)
@@ -8643,11 +8647,6 @@  grokfndecl (tree ctype,
       set_constraints (decl, ci);
     }
 
-  /* 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 = build_this_parm (decl, type, quals);
@@ -8716,17 +8715,19 @@  grokfndecl (tree ctype,
 	    if (TREE_PURPOSE (t)
 		&& TREE_CODE (TREE_PURPOSE (t)) == DEFAULT_ARG)
 	    {
-	      error ("default arguments are not allowed in declaration "
-		     "of friend template specialization %qD",
-		     decl);
+	      error_at (location,
+			"default arguments are not allowed in declaration "
+			"of friend template specialization %qD",
+			decl);
 	      return NULL_TREE;
 	    }
 
 	  if (inlinep & 1)
 	    {
-	      error ("%<inline%> is not allowed in declaration of friend "
-		     "template specialization %qD",
-		     decl);
+	      error_at (declspecs->locations[ds_inline],
+			"%<inline%> is not allowed in declaration of friend "
+			"template specialization %qD",
+			decl);
 	      return NULL_TREE;
 	    }
 	}
@@ -8773,13 +8774,15 @@  grokfndecl (tree ctype,
   if (ctype == NULL_TREE && DECL_MAIN_P (decl))
     {
       if (PROCESSING_REAL_TEMPLATE_DECL_P())
-	error ("cannot declare %<::main%> to be a template");
+	error_at (location, "cannot declare %<::main%> to be a template");
       if (inlinep & 1)
-	error ("cannot declare %<::main%> to be inline");
+	error_at (declspecs->locations[ds_inline],
+		  "cannot declare %<::main%> to be inline");
       if (inlinep & 2)
-	error ("cannot declare %<::main%> to be %<constexpr%>");
+	error_at (declspecs->locations[ds_constexpr],
+		  "cannot declare %<::main%> to be %<constexpr%>");
       if (!publicp)
-	error ("cannot declare %<::main%> to be static");
+	error_at (location, "cannot declare %<::main%> to be static");
       inlinep = 0;
       publicp = 1;
     }
@@ -8992,7 +8995,8 @@  grokfndecl (tree ctype,
 	{
 	  tree oldtypeargs = TYPE_ARG_TYPES (TREE_TYPE (decl));
 	  tree newtype;
-	  error ("%<::main%> must return %<int%>");
+	  error_at (declspecs->locations[ds_type_spec],
+		    "%<::main%> must return %<int%>");
 	  newtype = build_function_type (integer_type_node, oldtypeargs);
 	  TREE_TYPE (decl) = newtype;
 	}
@@ -12148,6 +12152,7 @@  grokdeclarator (const cp_declarator *declarator,
 			       ? unqualified_id : dname,
 			       parms,
 			       unqualified_id,
+			       declspecs,
 			       reqs,
 			       virtualp, flags, memfn_quals, rqual, raises,
 			       friendp ? -1 : 0, friendp, publicp,
@@ -12392,6 +12397,7 @@  grokdeclarator (const cp_declarator *declarator,
 		   || storage_class != sc_static);
 
 	decl = grokfndecl (ctype, type, original_name, parms, unqualified_id,
+			   declspecs,
                            reqs, virtualp, flags, memfn_quals, rqual, raises,
 			   1, friendp,
 			   publicp,
Index: testsuite/g++.dg/concepts/decl-diagnose.C
===================================================================
--- testsuite/g++.dg/concepts/decl-diagnose.C	(revision 261732)
+++ testsuite/g++.dg/concepts/decl-diagnose.C	(working copy)
@@ -6,7 +6,7 @@  void f(concept int); // { dg-error "a parameter ca
 
 template<typename T>
 concept int f2() { return 0; } // { dg-error "return type" }
-concept bool f3(); // { dg-error "no definition" }
+concept bool f3(); // { dg-error "14:concept .f3. has no definition" }
 
 struct X
 {
Index: testsuite/g++.dg/cpp0x/main1.C
===================================================================
--- testsuite/g++.dg/cpp0x/main1.C	(nonexistent)
+++ testsuite/g++.dg/cpp0x/main1.C	(working copy)
@@ -0,0 +1,3 @@ 
+// { dg-do compile { target c++11 } }
+
+constexpr int main();  // { dg-error "1:cannot declare .::main. to be .constexpr." }
Index: testsuite/g++.dg/other/main2.C
===================================================================
--- testsuite/g++.dg/other/main2.C	(nonexistent)
+++ testsuite/g++.dg/other/main2.C	(working copy)
@@ -0,0 +1 @@ 
+float main();  // { dg-error "1:.::main. must return .int." }
Index: testsuite/g++.dg/other/main3.C
===================================================================
--- testsuite/g++.dg/other/main3.C	(nonexistent)
+++ testsuite/g++.dg/other/main3.C	(working copy)
@@ -0,0 +1 @@ 
+inline int main();  // { dg-error "1:cannot declare .::main. to be inline" }
Index: testsuite/g++.dg/template/friend65.C
===================================================================
--- testsuite/g++.dg/template/friend65.C	(nonexistent)
+++ testsuite/g++.dg/template/friend65.C	(working copy)
@@ -0,0 +1,6 @@ 
+template <class T> void foo (int);
+
+template <class T>
+class Q {
+  friend inline void foo<T> (int); // { dg-error "10:.inline. is not allowed in declaration of friend" }
+};
Index: testsuite/g++.dg/warn/main-2.C
===================================================================
--- testsuite/g++.dg/warn/main-2.C	(revision 261732)
+++ testsuite/g++.dg/warn/main-2.C	(working copy)
@@ -7,8 +7,8 @@ 
 
 void f1();  
   
-void
-main()  /* { dg-error "must return" } */
+void  /* { dg-error "1:.\:\:main. must return .int." } */
+main()
 {     
   f1();  
 }