diff options
author | Mark Mitchell <mark@codesourcery.com> | 2004-08-02 06:25:36 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2004-08-02 06:25:36 +0000 |
commit | b1cc95ce4c15c335589c5e0077c29c06c739e730 (patch) | |
tree | c3d8dbd637ffc5e31556926ff4cb38f427e0d90a /gcc | |
parent | e9475fa369a6f1491864fc3f768a08573a4a5456 (diff) | |
download | gcc-b1cc95ce4c15c335589c5e0077c29c06c739e730.zip gcc-b1cc95ce4c15c335589c5e0077c29c06c739e730.tar.gz gcc-b1cc95ce4c15c335589c5e0077c29c06c739e730.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/cp/name-lookup.c | 31 | ||||
-rw-r--r-- | gcc/cp/pt.c | 140 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/spec17.C | 11 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.ns/template13.C | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/lookup10.C | 4 |
7 files changed, 122 insertions, 87 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index fffa892..81a819a 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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 diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 8c36fe8..c445412 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -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. */ diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index ad48910..1e9bbb1 100644 --- a/gcc/cp/pt.c +++ b/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)); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e394b1f..eb04ff1 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 diff --git a/gcc/testsuite/g++.dg/template/spec17.C b/gcc/testsuite/g++.dg/template/spec17.C new file mode 100644 index 0000000..2375576 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/spec17.C @@ -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>(); diff --git a/gcc/testsuite/g++.old-deja/g++.ns/template13.C b/gcc/testsuite/g++.old-deja/g++.ns/template13.C index d7e4b79..058d7b9 100644 --- a/gcc/testsuite/g++.old-deja/g++.ns/template13.C +++ b/gcc/testsuite/g++.old-deja/g++.ns/template13.C @@ -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> diff --git a/gcc/testsuite/g++.old-deja/g++.pt/lookup10.C b/gcc/testsuite/g++.old-deja/g++.pt/lookup10.C index c0b4389..1c04250 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/lookup10.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/lookup10.C @@ -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 "" } } |