aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2004-08-02 06:25:36 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2004-08-02 06:25:36 +0000
commitb1cc95ce4c15c335589c5e0077c29c06c739e730 (patch)
treec3d8dbd637ffc5e31556926ff4cb38f427e0d90a
parente9475fa369a6f1491864fc3f768a08573a4a5456 (diff)
downloadgcc-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
-rw-r--r--gcc/cp/ChangeLog11
-rw-r--r--gcc/cp/name-lookup.c31
-rw-r--r--gcc/cp/pt.c140
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/g++.dg/template/spec17.C11
-rw-r--r--gcc/testsuite/g++.old-deja/g++.ns/template13.C5
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/lookup10.C4
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 "" }
}