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:
parent
e9475fa369
commit
b1cc95ce4c
7 changed files with 122 additions and 87 deletions
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
140
gcc/cp/pt.c
140
gcc/cp/pt.c
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
|
|
11
gcc/testsuite/g++.dg/template/spec17.C
Normal file
11
gcc/testsuite/g++.dg/template/spec17.C
Normal 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>();
|
|
@ -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>
|
||||
|
|
|
@ -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 "" }
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue