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