re PR c++/16224 (internal compiler error: in write_unscoped_name (template/namespace))

PR c++/16224
	* name-lookup.c (decl_namespace): Remove.
	(current_decl_namespace): Use decl_namespace_context instead of
	decl_namespace.
	(push_decl_namespace): Likewise.
	(arg_assoc_class): Likewise.
	(arg_assoc_type): Likewise.
	* pt.c (check_specialization_namespace): New function.
	(maybe_process_partial_specialization): Use it.
	(register_specialization): Likewise.

	PR c++/16224
	* g++.dg/template/spec17.C: New test.
	* g++.old-deja/g++.ns/template13.C: Remove XFAIL.
	* g++.old-deja/g++.pt/lookup10.C: Add dg-error marker.

From-SVN: r85431
This commit is contained in:
Mark Mitchell 2004-08-02 06:25:36 +00:00 committed by Mark Mitchell
parent e9475fa369
commit b1cc95ce4c
7 changed files with 122 additions and 87 deletions

View file

@ -1,5 +1,16 @@
2004-08-01 Mark Mitchell <mark@codesourcery.com>
PR c++/16224
* name-lookup.c (decl_namespace): Remove.
(current_decl_namespace): Use decl_namespace_context instead of
decl_namespace.
(push_decl_namespace): Likewise.
(arg_assoc_class): Likewise.
(arg_assoc_type): Likewise.
* pt.c (check_specialization_namespace): New function.
(maybe_process_partial_specialization): Use it.
(register_specialization): Likewise.
PR c++/16489
* cp-tree.h (DECL_INTEGRAL_CONSTANT_VAR_P): New macro.
* call.c (null_ptr_cst_p): Handle variables with constant

View file

@ -2991,27 +2991,6 @@ set_namespace_binding (tree name, tree scope, tree val)
timevar_pop (TV_NAME_LOOKUP);
}
/* Compute the namespace where a declaration is defined. */
static tree
decl_namespace (tree decl)
{
timevar_push (TV_NAME_LOOKUP);
if (TYPE_P (decl))
decl = TYPE_STUB_DECL (decl);
while (DECL_CONTEXT (decl))
{
decl = DECL_CONTEXT (decl);
if (TREE_CODE (decl) == NAMESPACE_DECL)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
if (TYPE_P (decl))
decl = TYPE_STUB_DECL (decl);
my_friendly_assert (DECL_P (decl), 390);
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, global_namespace);
}
/* Set the context of a declaration to scope. Complain if we are not
outside scope. */
@ -3080,9 +3059,9 @@ current_decl_namespace (void)
return TREE_PURPOSE (decl_namespace_list);
if (current_class_type)
result = decl_namespace (TYPE_STUB_DECL (current_class_type));
result = decl_namespace_context (current_class_type);
else if (current_function_decl)
result = decl_namespace (current_function_decl);
result = decl_namespace_context (current_function_decl);
else
result = current_namespace;
return result;
@ -3210,7 +3189,7 @@ void
push_decl_namespace (tree decl)
{
if (TREE_CODE (decl) != NAMESPACE_DECL)
decl = decl_namespace (decl);
decl = decl_namespace_context (decl);
decl_namespace_list = tree_cons (ORIGINAL_NAMESPACE (decl),
NULL_TREE, decl_namespace_list);
}
@ -4394,7 +4373,7 @@ arg_assoc_class (struct arg_lookup *k, tree type)
return false;
k->classes = tree_cons (type, NULL_TREE, k->classes);
context = decl_namespace (TYPE_MAIN_DECL (type));
context = decl_namespace_context (type);
if (arg_assoc_namespace (k, context))
return true;
@ -4483,7 +4462,7 @@ arg_assoc_type (struct arg_lookup *k, tree type)
return arg_assoc_type (k, TREE_TYPE (type));
case UNION_TYPE:
case ENUMERAL_TYPE:
return arg_assoc_namespace (k, decl_namespace (TYPE_MAIN_DECL (type)));
return arg_assoc_namespace (k, decl_namespace_context (type));
case METHOD_TYPE:
/* The basetype is referenced in the first arg type, so just
fall through. */

View file

@ -708,6 +708,36 @@ end_explicit_instantiation (void)
processing_explicit_instantiation = false;
}
/* A explicit specialization or partial specialization TMPL is being
declared. Check that the namespace in which the specialization is
occurring is permissible. Returns false iff it is invalid to
specialize TMPL in the current namespace. */
static bool
check_specialization_namespace (tree tmpl)
{
tree tpl_ns = decl_namespace_context (tmpl);
/* [tmpl.expl.spec]
An explicit specialization shall be declared in the namespace of
which the template is a member, or, for member templates, in the
namespace of which the enclosing class or enclosing class
template is a member. An explicit specialization of a member
function, member class or static data member of a class template
shall be declared in the namespace of which the class template is
a member. */
if (is_associated_namespace (current_namespace, tpl_ns))
/* Same or super-using namespace. */
return true;
else
{
pedwarn ("specialization of `%D' in different namespace", tmpl);
cp_pedwarn_at (" from definition of `%#D'", tmpl);
return false;
}
}
/* The TYPE is being declared. If it is a template type, that means it
is a partial specialization. Do appropriate error-checking. */
@ -733,15 +763,7 @@ maybe_process_partial_specialization (tree type)
if (CLASSTYPE_IMPLICIT_INSTANTIATION (type)
&& !COMPLETE_TYPE_P (type))
{
tree tpl_ns = decl_namespace_context (CLASSTYPE_TI_TEMPLATE (type));
if (is_associated_namespace (current_namespace, tpl_ns))
/* Same or super-using namespace. */;
else
{
pedwarn ("specializing `%#T' in different namespace", type);
cp_pedwarn_at (" from definition of `%#D'",
CLASSTYPE_TI_TEMPLATE (type));
}
check_specialization_namespace (CLASSTYPE_TI_TEMPLATE (type));
SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (type);
if (processing_template_decl)
push_template_decl (TYPE_MAIN_DECL (type));
@ -1057,64 +1079,68 @@ register_specialization (tree spec, tree tmpl, tree args)
more convenient to simply allow this than to try to prevent it. */
if (fn == spec)
return spec;
else if (comp_template_args (TREE_PURPOSE (s), args))
else if (comp_template_args (TREE_PURPOSE (s), args)
&& DECL_TEMPLATE_SPECIALIZATION (spec))
{
if (DECL_TEMPLATE_SPECIALIZATION (spec))
if (DECL_TEMPLATE_INSTANTIATION (fn))
{
if (DECL_TEMPLATE_INSTANTIATION (fn))
if (TREE_USED (fn)
|| DECL_EXPLICIT_INSTANTIATION (fn))
{
if (TREE_USED (fn)
|| DECL_EXPLICIT_INSTANTIATION (fn))
{
error ("specialization of %D after instantiation",
fn);
return spec;
}
else
{
/* This situation should occur only if the first
specialization is an implicit instantiation,
the second is an explicit specialization, and
the implicit instantiation has not yet been
used. That situation can occur if we have
implicitly instantiated a member function and
then specialized it later.
We can also wind up here if a friend
declaration that looked like an instantiation
turns out to be a specialization:
template <class T> void foo(T);
class S { friend void foo<>(int) };
template <> void foo(int);
We transform the existing DECL in place so that
any pointers to it become pointers to the
updated declaration.
If there was a definition for the template, but
not for the specialization, we want this to
look as if there were no definition, and vice
versa. */
DECL_INITIAL (fn) = NULL_TREE;
duplicate_decls (spec, fn);
return fn;
}
error ("specialization of %D after instantiation",
fn);
return spec;
}
else if (DECL_TEMPLATE_SPECIALIZATION (fn))
else
{
if (!duplicate_decls (spec, fn) && DECL_INITIAL (spec))
/* Dup decl failed, but this is a new
definition. Set the line number so any errors
match this new definition. */
DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (spec);
/* This situation should occur only if the first
specialization is an implicit instantiation, the
second is an explicit specialization, and the
implicit instantiation has not yet been used.
That situation can occur if we have implicitly
instantiated a member function and then
specialized it later.
We can also wind up here if a friend declaration
that looked like an instantiation turns out to be
a specialization:
template <class T> void foo(T);
class S { friend void foo<>(int) };
template <> void foo(int);
We transform the existing DECL in place so that
any pointers to it become pointers to the updated
declaration.
If there was a definition for the template, but
not for the specialization, we want this to look
as if there were no definition, and vice
versa. */
DECL_INITIAL (fn) = NULL_TREE;
duplicate_decls (spec, fn);
return fn;
}
}
else if (DECL_TEMPLATE_SPECIALIZATION (fn))
{
if (!duplicate_decls (spec, fn) && DECL_INITIAL (spec))
/* Dup decl failed, but this is a new definition. Set
the line number so any errors match this new
definition. */
DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (spec);
return fn;
}
}
}
}
/* A specialization must be declared in the same namespace as the
template it is specializing. */
if (DECL_TEMPLATE_SPECIALIZATION (spec)
&& !check_specialization_namespace (tmpl))
DECL_CONTEXT (spec) = decl_namespace_context (tmpl);
DECL_TEMPLATE_SPECIALIZATIONS (tmpl)
= tree_cons (args, spec, DECL_TEMPLATE_SPECIALIZATIONS (tmpl));

View file

@ -1,3 +1,10 @@
2004-08-01 Mark Mitchell <mark@codesourcery.com>
PR c++/16224
* g++.dg/template/spec17.C: New test.
* g++.old-deja/g++.ns/template13.C: Remove XFAIL.
* g++.old-deja/g++.pt/lookup10.C: Add dg-error marker.
2004-08-02 David Billinghurst
PR fortran/16292

View file

@ -0,0 +1,11 @@
// PR c++/16224
namespace io {
template <typename> int foo(); // { dg-error "" }
}
using namespace io;
template<> int foo<int>(); // { dg-error "" }
int a = foo<int>();

View file

@ -2,8 +2,9 @@
// Templates defined outside must be declared inside
namespace bar
{
// trick it to provide some prior declaration
template<class T>
void foo(); // trick it to provide some prior declaration
void foo(); // { dg-error "definition" }
template<class T>class X; // { dg-error "" } previous declaration
}
@ -15,7 +16,7 @@ bar::foo(T const &a)
}
template<> void bar::foo<int>()
{ // { dg-error "" "" { xfail *-*-* } } not declared in bar -
{ // { dg-error "" }
}
template<class T,class U>

View file

@ -13,8 +13,8 @@ namespace Outer {
namespace Core = Core_Real;
namespace Core_Real {
template<class T> void Foo (T *) {}
template<class T> void Foo (T *) {} // { dg-error "definition" }
}
template<> void Core::Foo<> (Render_Real::Type *) {}
template<> void Core::Foo<> (Render_Real::Type *) {} // { dg-error "" }
}