aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2007-09-18 18:50:03 -0400
committerJason Merrill <jason@gcc.gnu.org>2007-09-18 18:50:03 -0400
commit5044ab0e64544ee48062cfd2498ce3e11bd49b83 (patch)
tree2ee8091936fa9f80661d3131455c96b63fb43a40 /gcc
parent80a6ca747aa083f973741bace6b07f12f2933c49 (diff)
downloadgcc-5044ab0e64544ee48062cfd2498ce3e11bd49b83.zip
gcc-5044ab0e64544ee48062cfd2498ce3e11bd49b83.tar.gz
gcc-5044ab0e64544ee48062cfd2498ce3e11bd49b83.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog18
-rw-r--r--gcc/cp/decl2.c18
-rw-r--r--gcc/cp/pt.c63
-rw-r--r--gcc/testsuite/g++.dg/ext/tmplattr3.C21
4 files changed, 113 insertions, 7 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index f622661..ebf9b3d 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,16 @@
+2007-09-18 Jason Merrill <jason@redhat.com>
+
+ 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 <pcarlini@suse.de>
PR c++/33462 (again)
@@ -38,17 +51,12 @@
2007-09-16 Nathan Sidwell <nathan@codesourcery.com>
- 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 <jason@redhat.com>
PR c++/17743, c++/19163
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 0c0961d..a8c0f92 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 d918d86..e54bc5f 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 0000000..51f5daf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/tmplattr3.C
@@ -0,0 +1,21 @@
+// PR c++/17743
+
+template<typename T>
+struct X {
+ typedef char layout_type[sizeof(T)]
+ __attribute ((aligned(__alignof(double))));
+ layout_type data;
+};
+
+template<typename T>
+struct Y {
+ typedef char layout_type[sizeof(T)]
+ __attribute ((aligned(__alignof(T))));
+ layout_type data;
+};
+
+template<bool> struct StaticAssert;
+template<> struct StaticAssert<true> {};
+
+StaticAssert<__alignof(X<double>) == __alignof(double)> d1;
+StaticAssert<__alignof(Y<double>) == __alignof(double)> d2;