Commit 4155777d by Nathan Sidwell Committed by Nathan Sidwell

[C++ PATCH] refactor duplicate_decls

https://gcc.gnu.org/ml/gcc-patches/2018-11/msg00085.html
	gcc/cp/
	* decl.c (duplicate_decls): Refactor checks.
	gcc/testsuite/
	* g++.dg/lookup/crash6.C: Adjust error
	* g++.dg/parse/crash38.C: Likewise.

From-SVN: r265744
parent 97f5962a
2018-11-02 Nathan Sidwell <nathan@acm.org>
* decl.c (duplicate_decls): Refactor checks.
2018-11-01 Marek Polacek <polacek@redhat.com>
Implement P0846R0, ADL and function templates.
......
......@@ -1370,47 +1370,6 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
|| TREE_TYPE (olddecl) == error_mark_node)
return error_mark_node;
if (DECL_NAME (newdecl)
&& DECL_NAME (olddecl)
&& UDLIT_OPER_P (DECL_NAME (newdecl))
&& UDLIT_OPER_P (DECL_NAME (olddecl)))
{
if (TREE_CODE (newdecl) == TEMPLATE_DECL
&& TREE_CODE (olddecl) != TEMPLATE_DECL
&& check_raw_literal_operator (olddecl))
error_at (newdecl_loc,
"literal operator template %qD conflicts with"
" raw literal operator %qD", newdecl, olddecl);
else if (TREE_CODE (newdecl) != TEMPLATE_DECL
&& TREE_CODE (olddecl) == TEMPLATE_DECL
&& check_raw_literal_operator (newdecl))
error_at (newdecl_loc,
"raw literal operator %qD conflicts with"
" literal operator template %qD", newdecl, olddecl);
}
/* True to merge attributes between the declarations, false to
set OLDDECL's attributes to those of NEWDECL (for template
explicit specializations that specify their own attributes
independent of those specified for the primary template). */
const bool merge_attr = (TREE_CODE (newdecl) != FUNCTION_DECL
|| !DECL_TEMPLATE_SPECIALIZATION (newdecl)
|| DECL_TEMPLATE_SPECIALIZATION (olddecl));
if (DECL_P (olddecl)
&& TREE_CODE (newdecl) == FUNCTION_DECL
&& TREE_CODE (olddecl) == FUNCTION_DECL
&& merge_attr
&& diagnose_mismatched_attributes (olddecl, newdecl))
{
if (DECL_INITIAL (olddecl))
inform (olddecl_loc,
"previous definition of %qD was here", olddecl);
else
inform (olddecl_loc,
"previous declaration of %qD was here", olddecl);
}
/* Check for redeclaration and other discrepancies. */
if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_ARTIFICIAL (olddecl))
......@@ -1634,38 +1593,45 @@ next_arg:;
/* C++ Standard, 3.3, clause 4:
"[Note: a namespace name or a class template name must be unique
in its declarative region (7.3.2, clause 14). ]" */
if (TREE_CODE (olddecl) != NAMESPACE_DECL
&& TREE_CODE (newdecl) != NAMESPACE_DECL
&& (TREE_CODE (olddecl) != TEMPLATE_DECL
|| TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) != TYPE_DECL)
&& (TREE_CODE (newdecl) != TEMPLATE_DECL
|| TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) != TYPE_DECL))
{
if ((TREE_CODE (olddecl) == TYPE_DECL && DECL_ARTIFICIAL (olddecl)
&& TREE_CODE (newdecl) != TYPE_DECL)
|| (TREE_CODE (newdecl) == TYPE_DECL && DECL_ARTIFICIAL (newdecl)
&& TREE_CODE (olddecl) != TYPE_DECL))
{
/* We do nothing special here, because C++ does such nasty
things with TYPE_DECLs. Instead, just let the TYPE_DECL
get shadowed, and know that if we need to find a TYPE_DECL
for a given name, we can look in the IDENTIFIER_TYPE_VALUE
slot of the identifier. */
return NULL_TREE;
}
if ((TREE_CODE (newdecl) == FUNCTION_DECL
&& DECL_FUNCTION_TEMPLATE_P (olddecl))
|| (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_FUNCTION_TEMPLATE_P (newdecl)))
return NULL_TREE;
if (TREE_CODE (olddecl) == NAMESPACE_DECL
|| TREE_CODE (newdecl) == NAMESPACE_DECL)
/* Namespace conflicts with not namespace. */;
else if (DECL_TYPE_TEMPLATE_P (olddecl)
|| DECL_TYPE_TEMPLATE_P (newdecl))
/* Class template conflicts. */;
else if ((TREE_CODE (newdecl) == FUNCTION_DECL
&& DECL_FUNCTION_TEMPLATE_P (olddecl))
|| (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_FUNCTION_TEMPLATE_P (newdecl)))
{
/* One is a function and the other is a template
function. */
if (!UDLIT_OPER_P (DECL_NAME (newdecl)))
return NULL_TREE;
/* There can only be one! */
if (TREE_CODE (newdecl) == TEMPLATE_DECL
&& check_raw_literal_operator (olddecl))
error_at (newdecl_loc,
"literal operator %q#D conflicts with"
" raw literal operator", newdecl);
else if (check_raw_literal_operator (newdecl))
error_at (newdecl_loc,
"raw literal operator %q#D conflicts with"
" literal operator template", newdecl);
else
return NULL_TREE;
inform (olddecl_loc, "previous declaration %q#D", olddecl);
return error_mark_node;
}
else if (DECL_IMPLICIT_TYPEDEF_P (olddecl)
|| DECL_IMPLICIT_TYPEDEF_P (newdecl))
/* One is an implicit typedef, that's ok. */
return NULL_TREE;
error ("%q#D redeclared as different kind of symbol", newdecl);
if (TREE_CODE (olddecl) == TREE_LIST)
olddecl = TREE_VALUE (olddecl);
inform (olddecl_loc,
"previous declaration %q#D", olddecl);
error ("%q#D redeclared as different kind of entity", newdecl);
inform (olddecl_loc, "previous declaration %q#D", olddecl);
return error_mark_node;
}
......@@ -1700,8 +1666,8 @@ next_arg:;
return type. */
&& same_type_p (TREE_TYPE (TREE_TYPE (newdecl)),
TREE_TYPE (TREE_TYPE (olddecl)))
// Template functions can also be disambiguated by
// constraints.
/* Template functions can also be disambiguated by
constraints. */
&& equivalently_constrained (olddecl, newdecl))
{
error_at (newdecl_loc, "ambiguating new declaration %q#D",
......@@ -1938,16 +1904,30 @@ next_arg:;
|| DECL_IMPLICIT_TYPEDEF_P (newdecl)))
return NULL_TREE;
if (!validate_constexpr_redeclaration (olddecl, newdecl))
return error_mark_node;
/* We have committed to returning OLDDECL at this point. */
/* If new decl is `static' and an `extern' was seen previously,
warn about it. */
warn_extern_redeclared_static (newdecl, olddecl);
if (!validate_constexpr_redeclaration (olddecl, newdecl))
return error_mark_node;
/* True to merge attributes between the declarations, false to
set OLDDECL's attributes to those of NEWDECL (for template
explicit specializations that specify their own attributes
independent of those specified for the primary template). */
const bool merge_attr = (TREE_CODE (newdecl) != FUNCTION_DECL
|| !DECL_TEMPLATE_SPECIALIZATION (newdecl)
|| DECL_TEMPLATE_SPECIALIZATION (olddecl));
/* We have committed to returning 1 at this point. */
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
if (merge_attr && diagnose_mismatched_attributes (olddecl, newdecl))
inform (olddecl_loc, DECL_INITIAL (olddecl)
? G_("previous definition of %qD here")
: G_("previous declaration of %qD here"), olddecl);
/* Now that functions must hold information normally held
by field decls, there is extra work to do so that
declaration information does not get destroyed during
......@@ -2027,7 +2007,7 @@ next_arg:;
else
DECL_ATTRIBUTES (olddecl) = DECL_ATTRIBUTES (newdecl);
if (DECL_DECLARES_FUNCTION_P (olddecl) && DECL_DECLARES_FUNCTION_P (newdecl))
if (DECL_DECLARES_FUNCTION_P (olddecl))
{
olddecl_friend = DECL_FRIEND_P (olddecl);
olddecl_hidden_friend = DECL_HIDDEN_FRIEND_P (olddecl);
......
2018-11-02 Nathan Sidwell <nathan@acm.org>
* g++.dg/lookup/crash6.C: Adjust error
* g++.dg/parse/crash38.C: Likewise.
2018-11-02 Andreas Schwab <schwab@linux-m68k.org>
* gcc.c-torture/execute/20010904-2.c: Fix last change.
......
......@@ -5,4 +5,4 @@
// PR c++/18652: ICE redeclaring variable as template.
int A; // { dg-message "previous declaration" }
template<int> struct A; // { dg-error "different kind of symbol" }
template<int> struct A; // { dg-error "different kind of" }
......@@ -2,10 +2,10 @@
/* This would not ICE. */
namespace M { } /* { dg-message "previous declaration" } */
struct M; /* { dg-error "redeclared as different kind of symbol" } */
struct M; /* { dg-error "redeclared as different kind of" } */
M *p; /* { dg-error "does not name a type" } */
/* This would ICE when processing 'p'. */
namespace N { } /* { dg-message "previous declaration" } */
struct N; /* { dg-error "redeclared as different kind of symbol" } */
struct N* p; /* { dg-error "redeclared as different kind of symbol|invalid type" } */
struct N; /* { dg-error "redeclared as different kind of" } */
struct N* p; /* { dg-error "redeclared as different kind of" } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment