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.carl...@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.carl...@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.
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();  
 }  

Reply via email to