From 5044ab0e64544ee48062cfd2498ce3e11bd49b83 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 18 Sep 2007 18:50:03 -0400 Subject: [PATCH] re PR c++/17743 (dependent expressions in attributes) PR c++/17743 * pt.c (apply_late_template_attributes): Set processing_template_decl. (tsubst_decl) [TYPE_DECL]: Preserve naming typedef, pass ATTR_FLAG_TYPE_IN_PLACE. (tsubst): Do unqualified lookup to find typedefs from current class. [ARRAY_TYPE]: Propagate alignment info. * decl2.c (is_late_template_attribute): Only defer handling of attribute aligned if the expression is dependent. (save_template_attributes): If we're deferring any attributes, make this a naming typedef. From-SVN: r128590 --- gcc/cp/ChangeLog | 18 +++++--- gcc/cp/decl2.c | 18 +++++++- gcc/cp/pt.c | 63 +++++++++++++++++++++++++++- gcc/testsuite/g++.dg/ext/tmplattr3.C | 21 ++++++++++ 4 files changed, 113 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ext/tmplattr3.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index f62266129af..ebf9b3d95ee 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,16 @@ +2007-09-18 Jason Merrill + + PR c++/17743 + * pt.c (apply_late_template_attributes): Set processing_template_decl. + (tsubst_decl) [TYPE_DECL]: Preserve naming typedef, pass + ATTR_FLAG_TYPE_IN_PLACE. + (tsubst): Do unqualified lookup to find typedefs from current class. + [ARRAY_TYPE]: Propagate alignment info. + * decl2.c (is_late_template_attribute): Only defer handling of + attribute aligned if the expression is dependent. + (save_template_attributes): If we're deferring any attributes, + make this a naming typedef. + 2007-09-18 Paolo Carlini PR c++/33462 (again) @@ -38,17 +51,12 @@ 2007-09-16 Nathan Sidwell - cp/ PR c++/32756 * call.c (maybe_handle_implicit_object): Set this_p, clear rvaluedness_matches_p. (compare_ics): Do not compare rvaluedness matching when one of the operands is an implicit object. - testsuite/ - PR c++/32756 - * g++.dg/overload/operator3.C: New. - 2007-09-14 Jason Merrill PR c++/17743, c++/19163 diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 0c0961d90d0..a8c0f9262a0 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -992,7 +992,10 @@ bool is_late_template_attribute (tree attr) { tree name = TREE_PURPOSE (attr); - if (is_attribute_p ("aligned", name)) + tree args = TREE_VALUE (attr); + if (is_attribute_p ("aligned", name) + && args + && value_dependent_expression_p (TREE_VALUE (args))) return true; else return false; @@ -1039,6 +1042,19 @@ save_template_attributes (tree *attr_p, tree *decl_p) if (!late_attrs) return; + /* Give this type a name so we know to look it up again at instantiation + time. */ + if (TREE_CODE (*decl_p) == TYPE_DECL + && DECL_ORIGINAL_TYPE (*decl_p) == NULL_TREE) + { + tree oldt = TREE_TYPE (*decl_p); + tree newt = build_variant_type_copy (oldt); + DECL_ORIGINAL_TYPE (*decl_p) = oldt; + TREE_TYPE (*decl_p) = newt; + TYPE_NAME (newt) = *decl_p; + TREE_USED (newt) = TREE_USED (*decl_p); + } + if (DECL_P (*decl_p)) q = &DECL_ATTRIBUTES (*decl_p); else diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index d918d86a2f3..e54bc5fba1e 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -6493,6 +6493,10 @@ apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags, else TYPE_ATTRIBUTES (*decl_p) = attributes; + /* Set processing_template_decl so we can check for dependent + expressions. */ + ++processing_template_decl; + for (t = attributes; t; t = TREE_CHAIN (t)) if (is_late_template_attribute (t)) late_attrs = tree_cons @@ -6501,6 +6505,8 @@ apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags, /*integral_constant_expression_p=*/false), late_attrs); + --processing_template_decl; + cplus_decl_attributes (decl_p, late_attrs, attr_flags); } @@ -8223,6 +8229,16 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) } determine_visibility (r); } + /* Preserve a typedef that names a type. */ + else if (TREE_CODE (r) == TYPE_DECL + && DECL_ORIGINAL_TYPE (t) + && type != error_mark_node) + { + DECL_ORIGINAL_TYPE (r) = tsubst (DECL_ORIGINAL_TYPE (t), + args, complain, in_decl); + TREE_TYPE (r) = type = build_variant_type_copy (type); + TYPE_NAME (type) = r; + } if (!local_p) { @@ -8241,7 +8257,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) TREE_CHAIN (r) = NULL_TREE; - apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0, + apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), + (int) ATTR_FLAG_TYPE_IN_PLACE, args, complain, in_decl); layout_decl (r, 0); } @@ -8534,6 +8551,43 @@ 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. */ + if (TYPE_P (t) + && TYPE_NAME (t) + && !IS_AGGR_TYPE (t) + && current_class_type + && CLASSTYPE_TEMPLATE_INFO (current_class_type)) + { + 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 (type && TREE_CODE (t) != TYPENAME_TYPE && TREE_CODE (t) != IDENTIFIER_NODE @@ -9013,6 +9067,13 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) } r = build_cplus_array_type (type, domain); + + if (TYPE_USER_ALIGN (t)) + { + TYPE_ALIGN (r) = TYPE_ALIGN (t); + TYPE_USER_ALIGN (r) = 1; + } + return r; } diff --git a/gcc/testsuite/g++.dg/ext/tmplattr3.C b/gcc/testsuite/g++.dg/ext/tmplattr3.C new file mode 100644 index 00000000000..51f5daf19b1 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/tmplattr3.C @@ -0,0 +1,21 @@ +// PR c++/17743 + +template +struct X { + typedef char layout_type[sizeof(T)] + __attribute ((aligned(__alignof(double)))); + layout_type data; +}; + +template +struct Y { + 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;