aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2010-02-18 11:27:18 -0500
committerJason Merrill <jason@gcc.gnu.org>2010-02-18 11:27:18 -0500
commit04daa92ba7e36a63dfd7bb1b5959d8afa187ecd1 (patch)
treef48f260ba50e9024ae229afffa80939640581a5c /gcc
parent935c0a5d24f70295aee602e4dcdff465d1931024 (diff)
downloadgcc-04daa92ba7e36a63dfd7bb1b5959d8afa187ecd1.zip
gcc-04daa92ba7e36a63dfd7bb1b5959d8afa187ecd1.tar.gz
gcc-04daa92ba7e36a63dfd7bb1b5959d8afa187ecd1.tar.bz2
re PR c++/26261 (Rejects template with const static data member used in return type)
PR c++/26261 PR c++/43101 * pt.c (tsubst_qualified_id): Do normal lookup in non-dependent scope. (maybe_update_decl_type): New fn. * parser.c (cp_parser_init_declarator): Use it. From-SVN: r156865
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/parser.c5
-rw-r--r--gcc/cp/pt.c60
-rw-r--r--gcc/testsuite/ChangeLog3
-rw-r--r--gcc/testsuite/g++.dg/template/dependent-name6.C17
6 files changed, 84 insertions, 8 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 357b925..1fdeef4 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,11 @@
2010-02-18 Jason Merrill <jason@redhat.com>
+ PR c++/26261
+ PR c++/43101
+ * pt.c (tsubst_qualified_id): Do normal lookup in non-dependent scope.
+ (maybe_update_decl_type): New fn.
+ * parser.c (cp_parser_init_declarator): Use it.
+
PR c++/43109
* semantics.c (begin_class_definition): Don't crash on unnamed ns.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index b5330a3..8b5bb56 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4896,6 +4896,7 @@ extern tree process_template_parm (tree, location_t, tree,
bool, bool);
extern tree end_template_parm_list (tree);
extern void end_template_decl (void);
+extern tree maybe_update_decl_type (tree, tree);
extern bool check_default_tmpl_args (tree, tree, int, int, int);
extern tree push_template_decl (tree);
extern tree push_template_decl_real (tree, bool);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 690f2c0..55d0517 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -13477,6 +13477,11 @@ cp_parser_init_declarator (cp_parser* parser,
we compute it now. */
scope = get_scope_of_declarator (declarator);
+ /* Perform any lookups in the declared type which were thought to be
+ dependent, but are not in the scope of the declarator. */
+ decl_specifiers->type
+ = maybe_update_decl_type (decl_specifiers->type, scope);
+
/* If we're allowing GNU extensions, look for an asm-specification
and attributes. */
if (cp_parser_allow_gnu_extensions_p (parser))
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 0165a7d..9e159a2 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -3672,6 +3672,55 @@ current_template_args (void)
return args;
}
+/* Update the declared TYPE by doing any lookups which were thought to be
+ dependent, but are not now that we know the SCOPE of the declarator. */
+
+tree
+maybe_update_decl_type (tree orig_type, tree scope)
+{
+ tree type = orig_type;
+
+ if (type == NULL_TREE)
+ return type;
+
+ if (TREE_CODE (orig_type) == TYPE_DECL)
+ type = TREE_TYPE (type);
+
+ if (scope && TYPE_P (scope) && dependent_type_p (scope)
+ && dependent_type_p (type)
+ /* Don't bother building up the args in this case. */
+ && TREE_CODE (type) != TEMPLATE_TYPE_PARM)
+ {
+ /* tsubst in the args corresponding to the template parameters,
+ including auto if present. Most things will be unchanged, but
+ make_typename_type and tsubst_qualified_id will resolve
+ TYPENAME_TYPEs and SCOPE_REFs that were previously dependent. */
+ tree args = current_template_args ();
+ tree auto_node = type_uses_auto (type);
+ if (auto_node)
+ {
+ tree auto_vec = make_tree_vec (1);
+ TREE_VEC_ELT (auto_vec, 0) = auto_node;
+ args = add_to_template_args (args, auto_vec);
+ }
+ push_scope (scope);
+ type = tsubst (type, args, tf_warning_or_error, NULL_TREE);
+ pop_scope (scope);
+ }
+
+ if (type == error_mark_node)
+ return orig_type;
+
+ if (TREE_CODE (orig_type) == TYPE_DECL)
+ {
+ if (same_type_p (type, TREE_TYPE (orig_type)))
+ type = orig_type;
+ else
+ type = TYPE_NAME (type);
+ }
+ return type;
+}
+
/* Return a TEMPLATE_DECL corresponding to DECL, using the indicated
template PARMS. If MEMBER_TEMPLATE_P is true, the new template is
a member template. Used by push_template_decl below. */
@@ -10609,14 +10658,9 @@ tsubst_qualified_id (tree qualified_id, tree args,
else
expr = name;
- if (dependent_type_p (scope))
- {
- tree type = NULL_TREE;
- if (DECL_P (expr) && !dependent_scope_p (scope))
- type = TREE_TYPE (expr);
- return build_qualified_name (type, scope, expr,
- QUALIFIED_NAME_IS_TEMPLATE (qualified_id));
- }
+ if (dependent_scope_p (scope))
+ return build_qualified_name (NULL_TREE, scope, expr,
+ QUALIFIED_NAME_IS_TEMPLATE (qualified_id));
if (!BASELINK_P (name) && !DECL_P (expr))
{
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index dbc8226..4225d99 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,8 @@
2010-02-18 Jason Merrill <jason@redhat.com>
+ PR c++/26261
+ * g++.dg/template/dependent-name6.C: New.
+
PR c++/43109
* g++.dg/parse/namespace12.C: New.
diff --git a/gcc/testsuite/g++.dg/template/dependent-name6.C b/gcc/testsuite/g++.dg/template/dependent-name6.C
new file mode 100644
index 0000000..e08bbe1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/dependent-name6.C
@@ -0,0 +1,17 @@
+// PR c++/26261
+// { dg-final { scan-assembler "_ZN1YIiE1fIiEE1XILi1EEv" } }
+
+template <int dim> class X {};
+
+template <class T> struct Y {
+ static const unsigned int dim = 1;
+ template <class U> X<Y<T>::dim> f();
+};
+
+template <class T> template <class U>
+X<Y<T>::dim> Y<T>::f() { return X<dim>(); }
+
+int main()
+{
+ Y<int>().f<int>();
+}