From d718e1bc42977e21e80731fcc4004c52963cf33e Mon Sep 17 00:00:00 2001 From: jason Date: Thu, 20 Sep 2007 14:13:00 +0000 Subject: [PATCH] PR c++/7586 * pt.c (tsubst): Handle typedefs by looking for the specialization. (retrieve_specialization): Only tagged types use DECL_TEMPLATE_INSTANTIATIONS. (instantiate_class_template): Push nested classes too. (tsubst_decl) [TYPE_DECL]: Only check for canonical decl for tagged types. * cp-tree.h (MAYBE_TAGGED_TYPE_P): New macro. * init.c (is_aggr_type): Remove redundant tests. * class.c (push_nested_class): Use CLASS_TYPE_P. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@128621 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 13 +++++++ gcc/cp/class.c | 12 +----- gcc/cp/cp-tree.h | 4 ++ gcc/cp/init.c | 4 +- gcc/cp/pt.c | 72 ++++++++++++++++++------------------ gcc/testsuite/g++.dg/ext/tmplattr3.C | 21 +++++++++++ gcc/testsuite/g++.dg/ext/tmplattr4.C | 19 ++++++++++ 7 files changed, 95 insertions(+), 50 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ext/tmplattr4.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ebcd865e9b3..efad3f3e59a 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,16 @@ +2007-09-19 Jason Merrill + + PR c++/7586 + * pt.c (tsubst): Handle typedefs by looking for the specialization. + (retrieve_specialization): Only tagged types use + DECL_TEMPLATE_INSTANTIATIONS. + (instantiate_class_template): Push nested classes too. + (tsubst_decl) [TYPE_DECL]: Only check for canonical decl for + tagged types. + * cp-tree.h (MAYBE_TAGGED_TYPE_P): New macro. + * init.c (is_aggr_type): Remove redundant tests. + * class.c (push_nested_class): Use CLASS_TYPE_P. + 2007-09-20 Paolo Carlini PR c++/33459 diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 9e0502fd1fb..5c3e0548044 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -5645,21 +5645,13 @@ currently_open_derived_class (tree t) void push_nested_class (tree type) { - tree context; - /* A namespace might be passed in error cases, like A::B:C. */ if (type == NULL_TREE - || type == error_mark_node - || TREE_CODE (type) == NAMESPACE_DECL - || ! IS_AGGR_TYPE (type) - || TREE_CODE (type) == TEMPLATE_TYPE_PARM - || TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM) + || !CLASS_TYPE_P (type)) return; - context = DECL_CONTEXT (TYPE_MAIN_DECL (type)); + push_nested_class (DECL_CONTEXT (TYPE_MAIN_DECL (type))); - if (context && CLASS_TYPE_P (context)) - push_nested_class (context); pushclass (type); } diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 4f1e88c931e..1ddf88492c6 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -988,6 +988,10 @@ enum languages { lang_c, lang_cplusplus, lang_java }; ((T) == RECORD_TYPE || (T) == UNION_TYPE) #define TAGGED_TYPE_P(T) \ (CLASS_TYPE_P (T) || TREE_CODE (T) == ENUMERAL_TYPE) +/* A tagged type or a dependent type that might be a tagged type when + instantiated. Like IS_AGGR_TYPE, but include enums as well. */ +#define MAYBE_TAGGED_TYPE_P(T) \ + (IS_AGGR_TYPE(T) || TREE_CODE (T) == ENUMERAL_TYPE) #define IS_OVERLOAD_TYPE(T) TAGGED_TYPE_P (T) /* True if this a "Java" type, defined in 'extern "Java"'. */ diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 247879cc5a0..c5c17b1a9e1 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -1281,9 +1281,7 @@ is_aggr_type (tree type, int or_else) if (type == error_mark_node) return 0; - if (! IS_AGGR_TYPE (type) - && TREE_CODE (type) != TEMPLATE_TYPE_PARM - && TREE_CODE (type) != BOUND_TEMPLATE_TEMPLATE_PARM) + if (! IS_AGGR_TYPE (type)) { if (or_else) error ("%qT is not an aggregate type", type); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index e54bc5fba1e..17acbaf220d 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -930,7 +930,8 @@ retrieve_specialization (tree tmpl, tree args, DECL_TEMPLATE_INSTANTIATIONS list; other templates use the DECL_TEMPLATE_SPECIALIZATIONS list. */ if (!class_specializations_p - && TREE_CODE (DECL_TEMPLATE_RESULT (tmpl)) == TYPE_DECL) + && TREE_CODE (DECL_TEMPLATE_RESULT (tmpl)) == TYPE_DECL + && TAGGED_TYPE_P (TREE_TYPE (tmpl))) sp = &DECL_TEMPLATE_INSTANTIATIONS (tmpl); else sp = &DECL_TEMPLATE_SPECIALIZATIONS (tmpl); @@ -6688,8 +6689,8 @@ instantiate_class_template (tree type) class, so that name lookups into base classes, etc. will work correctly. This is precisely analogous to what we do in begin_class_definition when defining an ordinary non-template - class. */ - pushclass (type); + class, except we also need to push the enclosing classes. */ + push_nested_class (type); /* Now members are processed in the order of declaration. */ for (member = CLASSTYPE_DECL_LIST (pattern); @@ -6986,7 +6987,7 @@ instantiate_class_template (tree type) && DECL_TEMPLATE_INFO (t)) tsubst_default_arguments (t); - popclass (); + pop_nested_class (); pop_from_top_level (); pop_deferring_access_checks (); pop_tinst_level (); @@ -8083,7 +8084,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) tree type = NULL_TREE; bool local_p; - if (TREE_CODE (t) == TYPE_DECL) + if (TREE_CODE (t) == TYPE_DECL + && MAYBE_TAGGED_TYPE_P (TREE_TYPE (t))) { type = tsubst (TREE_TYPE (t), args, complain, in_decl); if (TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM @@ -8158,6 +8160,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) /* Create a new node for the specialization we need. */ r = copy_decl (t); + if (type == NULL_TREE) + type = tsubst (TREE_TYPE (t), args, complain, in_decl); if (TREE_CODE (r) == VAR_DECL) { /* Even if the original location is out of scope, the @@ -8165,7 +8169,6 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) DECL_DEAD_FOR_LOCAL (r) = 0; DECL_INITIALIZED_P (r) = 0; DECL_TEMPLATE_INSTANTIATED (r) = 0; - type = tsubst (TREE_TYPE (t), args, complain, in_decl); if (type == error_mark_node) return error_mark_node; if (TREE_CODE (type) == FUNCTION_TYPE) @@ -8551,41 +8554,36 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) gcc_assert (type != unknown_type_node); - /* Reuse typedefs. This is a rather complicated way to check whether the - type is a typedef from the same class template as the current scope, - but I can't think of a better one. - - We need to do this to handle dependent attributes, specifically - attribute aligned. */ + /* Reuse typedefs. We need to do this to handle dependent attributes, + specifically attribute aligned. */ if (TYPE_P (t) && TYPE_NAME (t) - && !IS_AGGR_TYPE (t) - && current_class_type - && CLASSTYPE_TEMPLATE_INFO (current_class_type)) + && !MAYBE_TAGGED_TYPE_P (t) + && TREE_CODE (t) != TEMPLATE_TEMPLATE_PARM + && TREE_CODE (t) != UNBOUND_CLASS_TEMPLATE) { tree decl = TYPE_NAME (t); - tree context = DECL_CONTEXT (decl); - if (context - && CLASS_TYPE_P (context) - && CLASSTYPE_TEMPLATE_INFO (context) - && (CLASSTYPE_TI_TEMPLATE (context) - == CLASSTYPE_TI_TEMPLATE (current_class_type)) - && (tsubst_aggr_type (context, args, complain, in_decl, - /*entering_scope=*/0) - == current_class_type)) - { - r = lookup_name (DECL_NAME (decl)); - if (r && TREE_CODE (r) == TYPE_DECL - && DECL_CONTEXT (r) == current_class_type) - { - r = TREE_TYPE (r); - r = cp_build_qualified_type_real - (r, cp_type_quals (t) | cp_type_quals (r), - complain | tf_ignore_bad_quals); - return r; - /* Else we're instantiating the typedef, so fall through. */ - } - } + + if (DECL_CLASS_SCOPE_P (decl)) + { + tree tmpl = most_general_template (DECL_TI_TEMPLATE (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)) + r = retrieve_local_specialization (decl); + else + r = NULL_TREE; + + if (r) + { + r = TREE_TYPE (r); + r = cp_build_qualified_type_real + (r, cp_type_quals (t) | cp_type_quals (r), + complain | tf_ignore_bad_quals); + return r; + } + /* Else we must be instantiating the typedef, so fall through. */ } if (type diff --git a/gcc/testsuite/g++.dg/ext/tmplattr3.C b/gcc/testsuite/g++.dg/ext/tmplattr3.C index 51f5daf19b1..f8d3c162072 100644 --- a/gcc/testsuite/g++.dg/ext/tmplattr3.C +++ b/gcc/testsuite/g++.dg/ext/tmplattr3.C @@ -14,8 +14,29 @@ struct Y { layout_type data; }; +template +struct Z { + typedef char layout_type[sizeof(T)] + __attribute ((aligned(__alignof(T)))); + struct Z2 { + layout_type data; + } in; +}; + +template +struct A; + +template +struct A { + typedef char layout_type[sizeof(T)] + __attribute ((aligned(__alignof(T)))); + layout_type data; +}; + template struct StaticAssert; template<> struct StaticAssert {}; StaticAssert<__alignof(X) == __alignof(double)> d1; StaticAssert<__alignof(Y) == __alignof(double)> d2; +StaticAssert<__alignof(Z) == __alignof(double)> d3; +StaticAssert<__alignof(A) == __alignof(double)> d4; diff --git a/gcc/testsuite/g++.dg/ext/tmplattr4.C b/gcc/testsuite/g++.dg/ext/tmplattr4.C new file mode 100644 index 00000000000..3d5c6b7d5fb --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/tmplattr4.C @@ -0,0 +1,19 @@ +// PR c++/7586 +// { dg-do run } + +template +int f() +{ + typedef unsigned char type[sizeof (T)] + __attribute((aligned(__alignof(T)))); + + return __alignof (type); +} + +int main() +{ + if (f() == __alignof (int)) + return 0; + else + return 1; +} -- 2.11.4.GIT