summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog11
-rw-r--r--gcc/cp/pt.c36
-rw-r--r--gcc/testsuite/g++.dg/template/nested5.C19
-rw-r--r--gcc/testsuite/g++.dg/template/typedef10.C14
-rw-r--r--gcc/testsuite/g++.dg/template/typedef9.C25
5 files changed, 91 insertions, 14 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index fa48f7c54aa..807f1b5be45 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,16 @@
2008-01-21 Jason Merrill <jason@redhat.com>
+ PR c++/33959
+ * pt.c (tsubst_aggr_type): Make sure our context is complete.
+
+ PR c++/34573
+ * pt.c (retrieve_local_specialization): Robustify.
+ (tsubst_pack_expansion, tsubst_decl): Remove redundant checks.
+
+ PR c++/34846
+ * pt.c (tsubst): Only call retrieve_local_specialization if the
+ original typedef was in a function template.
+
PR c++/34196
* decl.c (wrap_cleanups_r): Set TRY_CATCH_IS_CLEANUP.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 87c4bf5a853..e61915da272 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -976,8 +976,13 @@ retrieve_specialization (tree tmpl, tree args,
static tree
retrieve_local_specialization (tree tmpl)
{
- tree spec = (tree) htab_find_with_hash (local_specializations, tmpl,
- htab_hash_pointer (tmpl));
+ tree spec;
+
+ if (local_specializations == NULL)
+ return NULL_TREE;
+
+ spec = (tree) htab_find_with_hash (local_specializations, tmpl,
+ htab_hash_pointer (tmpl));
return spec ? TREE_PURPOSE (spec) : NULL_TREE;
}
@@ -7305,10 +7310,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
tree orig_arg = NULL_TREE;
if (TREE_CODE (parm_pack) == PARM_DECL)
- {
- if (local_specializations)
- arg_pack = retrieve_local_specialization (parm_pack);
- }
+ arg_pack = retrieve_local_specialization (parm_pack);
else
{
int level, idx, levels;
@@ -7688,8 +7690,14 @@ tsubst_aggr_type (tree t,
up. */
context = TYPE_CONTEXT (t);
if (context)
- context = tsubst_aggr_type (context, args, complain,
- in_decl, /*entering_scope=*/1);
+ {
+ context = tsubst_aggr_type (context, args, complain,
+ in_decl, /*entering_scope=*/1);
+ /* If context is a nested class inside a class template,
+ it may still need to be instantiated (c++/33959). */
+ if (TYPE_P (context))
+ context = complete_type (context);
+ }
/* Then, figure out what arguments are appropriate for the
type we are trying to find. For example, given:
@@ -8201,9 +8209,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
substitution from inside tsubst_pack_expansion. Just
return the local specialization (which will be a single
parm). */
- tree spec = NULL_TREE;
- if (local_specializations)
- spec = retrieve_local_specialization (t);
+ tree spec = retrieve_local_specialization (t);
if (spec
&& TREE_CODE (spec) == PARM_DECL
&& TREE_CODE (TREE_TYPE (spec)) != TYPE_PACK_EXPANSION)
@@ -8855,11 +8861,13 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
tree gen_args = tsubst (DECL_TI_ARGS (decl), args, complain, in_decl);
r = retrieve_specialization (tmpl, gen_args, false);
}
- else if (DECL_FUNCTION_SCOPE_P (decl))
+ else if (DECL_FUNCTION_SCOPE_P (decl)
+ && DECL_TEMPLATE_INFO (DECL_CONTEXT (decl)))
r = retrieve_local_specialization (decl);
else
- r = NULL_TREE;
-
+ /* The typedef is from a non-template context. */
+ return t;
+
if (r)
{
r = TREE_TYPE (r);
diff --git a/gcc/testsuite/g++.dg/template/nested5.C b/gcc/testsuite/g++.dg/template/nested5.C
new file mode 100644
index 00000000000..3850fdace3a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/nested5.C
@@ -0,0 +1,19 @@
+// PR c++/33959
+
+template <typename T> struct A
+{
+ struct C
+ {
+ template <typename U> struct D {};
+ };
+ template <typename S> static C::D<S> bar (S const &);
+};
+
+struct E {};
+
+int
+main ()
+{
+ E e;
+ A<E>::bar (e);
+}
diff --git a/gcc/testsuite/g++.dg/template/typedef10.C b/gcc/testsuite/g++.dg/template/typedef10.C
new file mode 100644
index 00000000000..c2a2108f04a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typedef10.C
@@ -0,0 +1,14 @@
+// PR c++/34573
+
+template < class Gtr_>
+void compute_gr()
+{
+ typedef int Less_chain;
+ struct utils {
+ utils(const Less_chain& lc) {};
+ };
+ utils U(1);
+}
+int main(void){
+ compute_gr<int>();
+}
diff --git a/gcc/testsuite/g++.dg/template/typedef9.C b/gcc/testsuite/g++.dg/template/typedef9.C
new file mode 100644
index 00000000000..8d2ed36757c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typedef9.C
@@ -0,0 +1,25 @@
+// PR c++/34846
+
+template<typename, typename> struct __are_same { enum { __value = 0 }; };
+template<typename _Tp> struct __are_same<_Tp, _Tp> { enum { __value = 1 }; };
+template<typename, bool> struct __enable_if { };
+template<typename _Tp> struct __enable_if<_Tp, true> { typedef _Tp __type; };
+template<typename _Iterator, typename _Container> class __normal_iterator {
+public:
+ __normal_iterator();
+ template<typename _Iter>
+ __normal_iterator(
+ const __normal_iterator<_Iter, typename __enable_if<_Container,
+(__are_same<_Iter, typename _Container::pointer>::__value) >::__type>& __i)
+ { }
+};
+template<typename _Tp> class vector {
+public:
+ typedef _Tp* pointer;
+ typedef __normal_iterator<int, vector<_Tp> > iterator;
+};
+void test() {
+ typedef int t;
+ vector<t*>::iterator x;
+ vector<t*>::iterator y = x;
+}