decl.c (grokdeclarator): Use id_loc in five additional places in the last part of the function.

/cp
2019-06-13  Paolo Carlini  <paolo.carlini@oracle.com>

	* decl.c (grokdeclarator): Use id_loc in five additional places
	in the last part of the function.

/testsuite
2019-06-13  Paolo Carlini  <paolo.carlini@oracle.com>

	* g++.dg/diagnostic/variably-modified-type-1.C: New.
	* g++.dg/cpp0x/alias-decl-1.C: Test the location too.
	* g++.dg/other/pr84792-1.C: Likewise.
	* g++.dg/other/pr84792-2.C: Likewise.
	* g++.dg/parse/error24.C: Likewise.
	* g++.dg/parse/error32.C: Likewise.
	* g++.dg/parse/error33.C: Likewise.
	* g++.dg/parse/saved1.C: Likewise.
	* g++.dg/template/operator6.C: Likewise.
	* g++.dg/template/pr61745.C: Likewise.
	* g++.dg/template/typedef41.C: Likewise.
	* g++.old-deja/g++.jason/crash10.C: Likewise.

/cp
2019-06-13  Paolo Carlini  <paolo.carlini@oracle.com>

	* decl.c (grokdeclarator): Move further up the declaration of
	id_loc, use it immediately, update its value after the loop
	over declarator, use it again in the final part of function;
	improve locations of error messages about multiple data types
	and conflicting specifiers.

/testsuite
2019-06-13  Paolo Carlini  <paolo.carlini@oracle.com>

	* g++.dg/diagnostic/conflicting-specifiers-1.C: New.
	* g++.dg/diagnostic/two-or-more-data-types-1.C: Likewise.
	* g++.dg/parse/error10.C: Adjust location.
	* g++.dg/parse/pragma2.C: Likewise.

From-SVN: r272236
This commit is contained in:
Paolo Carlini 2019-06-13 08:45:46 +00:00 committed by Paolo Carlini
parent a8b98e2fc0
commit 52ffa82671
19 changed files with 105 additions and 49 deletions

View File

@ -1,3 +1,16 @@
2019-06-13 Paolo Carlini <paolo.carlini@oracle.com>
* decl.c (grokdeclarator): Use id_loc in five additional places
in the last part of the function.
2019-06-13 Paolo Carlini <paolo.carlini@oracle.com>
* decl.c (grokdeclarator): Move further up the declaration of
id_loc, use it immediately, update its value after the loop
over declarator, use it again in the final part of function;
improve locations of error messages about multiple data types
and conflicting specifiers.
2019-06-13 Richard Biener <rguenther@suse.de>
PR c++/90801

View File

@ -10456,6 +10456,10 @@ grokdeclarator (const cp_declarator *declarator,
if (typespec_loc == UNKNOWN_LOCATION)
typespec_loc = input_location;
location_t id_loc = declarator ? declarator->id_loc : input_location;
if (id_loc == UNKNOWN_LOCATION)
id_loc = input_location;
/* Look inside a declarator for the name being declared
and get it as a string, for an error message. */
for (id_declarator = declarator;
@ -10620,8 +10624,7 @@ grokdeclarator (const cp_declarator *declarator,
D1 ( parameter-declaration-clause) ... */
if (funcdef_flag && innermost_code != cdk_function)
{
error_at (declarator->id_loc,
"function definition does not declare parameters");
error_at (id_loc, "function definition does not declare parameters");
return error_mark_node;
}
@ -10629,8 +10632,7 @@ grokdeclarator (const cp_declarator *declarator,
&& innermost_code != cdk_function
&& ! (ctype && !declspecs->any_specifiers_p))
{
error_at (declarator->id_loc,
"declaration of %qD as non-function", dname);
error_at (id_loc, "declaration of %qD as non-function", dname);
return error_mark_node;
}
@ -10639,8 +10641,7 @@ grokdeclarator (const cp_declarator *declarator,
if (UDLIT_OPER_P (dname)
&& innermost_code != cdk_function)
{
error_at (declarator->id_loc,
"declaration of %qD as non-function", dname);
error_at (id_loc, "declaration of %qD as non-function", dname);
return error_mark_node;
}
@ -10648,14 +10649,12 @@ grokdeclarator (const cp_declarator *declarator,
{
if (typedef_p)
{
error_at (declarator->id_loc,
"declaration of %qD as %<typedef%>", dname);
error_at (id_loc, "declaration of %qD as %<typedef%>", dname);
return error_mark_node;
}
else if (decl_context == PARM || decl_context == CATCHPARM)
{
error_at (declarator->id_loc,
"declaration of %qD as parameter", dname);
error_at (id_loc, "declaration of %qD as parameter", dname);
return error_mark_node;
}
}
@ -10705,13 +10704,16 @@ grokdeclarator (const cp_declarator *declarator,
issue an error message. */
if (declspecs->multiple_types_p)
{
error ("two or more data types in declaration of %qs", name);
error_at (typespec_loc,
"two or more data types in declaration of %qs", name);
return error_mark_node;
}
if (declspecs->conflicting_specifiers_p)
{
error ("conflicting specifiers in declaration of %qs", name);
error_at (min_location (declspecs->locations[ds_typedef],
declspecs->locations[ds_storage_class]),
"conflicting specifiers in declaration of %qs", name);
return error_mark_node;
}
@ -11861,6 +11863,8 @@ grokdeclarator (const cp_declarator *declarator,
}
}
id_loc = declarator ? declarator->id_loc : input_location;
/* A `constexpr' specifier used in an object declaration declares
the object as `const'. */
if (constexpr_p && innermost_code != cdk_function)
@ -11884,8 +11888,6 @@ grokdeclarator (const cp_declarator *declarator,
unqualified_id = dname;
}
location_t loc = declarator ? declarator->id_loc : input_location;
/* If TYPE is a FUNCTION_TYPE, but the function name was explicitly
qualified with a class-name, turn it into a METHOD_TYPE, unless
we know that the function is static. We take advantage of this
@ -11912,7 +11914,7 @@ grokdeclarator (const cp_declarator *declarator,
friendp = 0;
}
else
permerror (loc, "extra qualification %<%T::%> on member %qs",
permerror (id_loc, "extra qualification %<%T::%> on member %qs",
ctype, name);
}
else if (/* If the qualifying type is already complete, then we
@ -11941,7 +11943,7 @@ grokdeclarator (const cp_declarator *declarator,
if (current_class_type
&& (!friendp || funcdef_flag || initialized))
{
error_at (loc, funcdef_flag || initialized
error_at (id_loc, funcdef_flag || initialized
? G_("cannot define member function %<%T::%s%> "
"within %qT")
: G_("cannot declare member function %<%T::%s%> "
@ -11952,7 +11954,7 @@ grokdeclarator (const cp_declarator *declarator,
}
else if (typedef_p && current_class_type)
{
error_at (loc, "cannot declare member %<%T::%s%> within %qT",
error_at (id_loc, "cannot declare member %<%T::%s%> within %qT",
ctype, name, current_class_type);
return error_mark_node;
}
@ -12000,9 +12002,11 @@ grokdeclarator (const cp_declarator *declarator,
&& variably_modified_type_p (type, NULL_TREE))
{
if (decl_context == FIELD)
error ("data member may not have variably modified type %qT", type);
error_at (id_loc,
"data member may not have variably modified type %qT", type);
else
error ("parameter may not have variably modified type %qT", type);
error_at (id_loc,
"parameter may not have variably modified type %qT", type);
type = error_mark_node;
}
@ -12106,14 +12110,14 @@ grokdeclarator (const cp_declarator *declarator,
if (id_declarator && declarator->u.id.qualifying_scope)
{
error ("typedef name may not be a nested-name-specifier");
error_at (id_loc, "typedef name may not be a nested-name-specifier");
type = error_mark_node;
}
if (decl_context == FIELD)
decl = build_lang_decl_loc (loc, TYPE_DECL, unqualified_id, type);
decl = build_lang_decl_loc (id_loc, TYPE_DECL, unqualified_id, type);
else
decl = build_decl (loc, TYPE_DECL, unqualified_id, type);
decl = build_decl (id_loc, TYPE_DECL, unqualified_id, type);
if (decl_context != FIELD)
{
@ -12130,7 +12134,7 @@ grokdeclarator (const cp_declarator *declarator,
}
else if (current_class_type
&& constructor_name_p (unqualified_id, current_class_type))
permerror (input_location, "ISO C++ forbids nested type %qD with same name "
permerror (id_loc, "ISO C++ forbids nested type %qD with same name "
"as enclosing class",
unqualified_id);
@ -12288,7 +12292,7 @@ grokdeclarator (const cp_declarator *declarator,
/* Only functions may be declared using an operator-function-id. */
if (dname && IDENTIFIER_ANY_OP_P (dname))
{
error ("declaration of %qD as non-function", dname);
error_at (id_loc, "declaration of %qD as non-function", dname);
return error_mark_node;
}
@ -12398,8 +12402,8 @@ grokdeclarator (const cp_declarator *declarator,
if (in_system_header_at (input_location))
/* Do not warn on flexible array members in system
headers because glibc uses them. */;
else if (name && declarator)
pedwarn (declarator->id_loc, OPT_Wpedantic,
else if (name)
pedwarn (id_loc, OPT_Wpedantic,
"ISO C++ forbids flexible array member %qs", name);
else
pedwarn (input_location, OPT_Wpedantic,
@ -12551,7 +12555,7 @@ grokdeclarator (const cp_declarator *declarator,
initialized == SD_DELETED, sfk,
funcdef_flag, late_return_type_p,
template_count, in_namespace,
attrlist, declarator->id_loc);
attrlist, id_loc);
decl = set_virt_specifiers (decl, virt_specifiers);
if (decl == NULL_TREE)
return error_mark_node;
@ -12584,8 +12588,7 @@ grokdeclarator (const cp_declarator *declarator,
{
if (unqualified_id)
{
error_at (declarator->id_loc,
"field %qD has incomplete type %qT",
error_at (id_loc, "field %qD has incomplete type %qT",
unqualified_id, type);
cxx_incomplete_type_inform (strip_array_types (type));
}
@ -12600,8 +12603,8 @@ grokdeclarator (const cp_declarator *declarator,
{
if (friendp)
{
if (unqualified_id && declarator)
error_at (declarator->id_loc,
if (unqualified_id)
error_at (id_loc,
"%qE is neither function nor member function; "
"cannot be declared friend", unqualified_id);
else
@ -12645,7 +12648,7 @@ grokdeclarator (const cp_declarator *declarator,
{
/* C++ allows static class members. All other work
for this is done by grokfield. */
decl = build_lang_decl_loc (loc, VAR_DECL,
decl = build_lang_decl_loc (id_loc, VAR_DECL,
unqualified_id, type);
set_linkage_for_static_data_member (decl);
if (concept_p)
@ -12693,7 +12696,7 @@ grokdeclarator (const cp_declarator *declarator,
unqualified_id);
constexpr_p = false;
}
decl = build_decl (loc, FIELD_DECL, unqualified_id, type);
decl = build_decl (id_loc, FIELD_DECL, unqualified_id, type);
DECL_NONADDRESSABLE_P (decl) = bitfield;
if (bitfield && !unqualified_id)
{
@ -12811,7 +12814,7 @@ grokdeclarator (const cp_declarator *declarator,
funcdef_flag,
late_return_type_p,
template_count, in_namespace, attrlist,
declarator->id_loc);
id_loc);
if (decl == NULL_TREE)
return error_mark_node;
@ -12858,7 +12861,7 @@ grokdeclarator (const cp_declarator *declarator,
concept_p,
template_count,
ctype ? ctype : in_namespace,
loc);
id_loc);
if (decl == NULL_TREE)
return error_mark_node;
@ -12904,7 +12907,7 @@ grokdeclarator (const cp_declarator *declarator,
if (innermost_code == cdk_decomp)
{
gcc_assert (declarator && declarator->kind == cdk_decomp);
DECL_SOURCE_LOCATION (decl) = declarator->id_loc;
DECL_SOURCE_LOCATION (decl) = id_loc;
DECL_ARTIFICIAL (decl) = 1;
fit_decomposition_lang_decl (decl, NULL_TREE);
}

View File

@ -1,3 +1,25 @@
2019-06-13 Paolo Carlini <paolo.carlini@oracle.com>
* g++.dg/diagnostic/variably-modified-type-1.C: New.
* g++.dg/cpp0x/alias-decl-1.C: Test the location too.
* g++.dg/other/pr84792-1.C: Likewise.
* g++.dg/other/pr84792-2.C: Likewise.
* g++.dg/parse/error24.C: Likewise.
* g++.dg/parse/error32.C: Likewise.
* g++.dg/parse/error33.C: Likewise.
* g++.dg/parse/saved1.C: Likewise.
* g++.dg/template/operator6.C: Likewise.
* g++.dg/template/pr61745.C: Likewise.
* g++.dg/template/typedef41.C: Likewise.
* g++.old-deja/g++.jason/crash10.C: Likewise.
2019-06-13 Paolo Carlini <paolo.carlini@oracle.com>
* g++.dg/diagnostic/conflicting-specifiers-1.C: New.
* g++.dg/diagnostic/two-or-more-data-types-1.C: Likewise.
* g++.dg/parse/error10.C: Adjust location.
* g++.dg/parse/pragma2.C: Likewise.
2019-06-13 Feng Xue <fxue@os.amperecomputing.com>
PR tree-optimization/89713

View File

@ -11,5 +11,6 @@ template <class U> using Ptr = U*;
template<class U> struct Ptr<U*> {}; // { dg-error "specialization" }
struct A {
using A = int;//{ dg-error "nested|has|same name as|class|in which|declared" }
using A = int; // { dg-error "11:ISO C\\+\\+ forbids nested type .A." }
// { dg-error "same name as" "" { target c++11 } .-1 }
};

View File

@ -0,0 +1 @@
static typedef int i __attribute__((unused)); // { dg-error "1:conflicting specifiers" }

View File

@ -0,0 +1 @@
char int i __attribute__((unused)); // { dg-error "1:two or more data types" }

View File

@ -0,0 +1,12 @@
// { dg-options "" }
void foo ()
{
int n;
typedef int X[n];
struct Z
{
X x __attribute__((unused)); // { dg-error "7:data member may not have variably modified type" }
void bar (X x __attribute__((unused))); // { dg-error "17:parameter may not have variably modified type" }
};
}

View File

@ -3,4 +3,4 @@ struct A {};
typedef struct
{
virtual void foo() {}
} A::B; // { dg-error "typedef" }
} A::B; // { dg-error "3:typedef" }

View File

@ -3,4 +3,4 @@ struct A {};
typedef struct
{
void foo() {}
} A::B; // { dg-error "typedef" }
} A::B; // { dg-error "3:typedef" }

View File

@ -14,4 +14,4 @@ template <typename T> void foo()
enum typename A<T>::E e4;
}
// { dg-error "28:two or more data types in declaration of 'e4'" "2 or more" { target *-*-* } 14 }
// { dg-error "3:two or more data types in declaration of 'e4'" "2 or more" { target *-*-* } 14 }

View File

@ -2,7 +2,7 @@
// PR c++/19395
struct A {
typedef int ::X; // { dg-error "17:typedef name may not be a nested-name-specifier" }
typedef int ::X; // { dg-error "15:typedef name may not be a nested-name-specifier" }
};

View File

@ -3,7 +3,7 @@
struct A {};
typedef void (A::T)(); /* { dg-error "typedef name may not be a nested-name-specifier" } */
typedef void (A::T)(); /* { dg-error "15:typedef name may not be a nested-name-specifier" } */
void foo()
{

View File

@ -6,7 +6,7 @@ struct A
void foo();
};
typedef void (A::T)(); /* { dg-error "typedef name may not be a nested" } */
typedef void (A::T)(); /* { dg-error "15:typedef name may not be a nested" } */
void bar(T); /* { dg-message "note: declared here" } */

View File

@ -4,5 +4,6 @@
// does not.
int f(int x,
#pragma interface // { dg-error "not allowed here" }
// { dg-bogus "two or more" "" { xfail *-*-* } .-1 }
// The parser gets confused and issues an error on the next line.
int y); // { dg-bogus "" "" { xfail *-*-* } }
int y);

View File

@ -1,6 +1,7 @@
// Test that the parser doesn't go into an infinite loop from ignoring the
// PRE_PARSED_FUNCTION_DECL token.
class C { static void* operator new(size_t); }; // { dg-error "" }
class C { static void* operator new(size_t); }; // { dg-error "24:declaration of .operator new. as non-function" }
// { dg-error "expected|ISO C\\+\\+ forbids" "" { target *-*-* } .-1 }
void* C::operator new(size_t) { return 0; } // { dg-error "" }
class D { D(int i): integer(i){}}; // { dg-error "" }

View File

@ -1,4 +1,4 @@
// PR c++/27315
// { dg-do compile }
template void operator+; // { dg-error "non-function" }
template void operator+; // { dg-error "15:declaration of .operator\\+. as non-function" }

View File

@ -20,5 +20,6 @@ public:
Zp operator-() const { return Zp(p-val); }
// In C++2A, we have an unqualified-id (operator-) followed by
// '<', and name lookup found a function.
friend Zp<INT,P> operator- <>(const Zp<INT,P>& a, const Zp<INT,P>& b); // { dg-error "declaration|expected" "" { target c++17_down } }
friend Zp<INT,P> operator- <>(const Zp<INT,P>& a, const Zp<INT,P>& b); // { dg-error "20:declaration of .operator\\-. as non-function" "" { target c++17_down } }
// { dg-error "expected" "" { target c++17_down } .-1 }
};

View File

@ -2,7 +2,7 @@
template<int> struct A
{
typedef int ::X; // { dg-error "" }
typedef int ::X; // { dg-error "15:typedef name" }
};
A<0> a;

View File

@ -5,4 +5,4 @@ struct A {
enum foo { bar };
};
typedef A::foo A::foo; // { dg-error "" } causes compiler segfault
typedef A::foo A::foo; // { dg-error "16:typedef name" } causes compiler segfault