summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2007-09-23 02:36:34 +0000
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2007-09-23 02:36:34 +0000
commit2fdd6488b59abc8f1da3d423d45044ffb82533cd (patch)
tree17a3573bc82b532229f930f45caf02beb84bdead /gcc
parent6d51dde5dd855acc798372dab5e072014888647e (diff)
downloadgcc-2fdd6488b59abc8f1da3d423d45044ffb82533cd.tar.gz
PR c++/19407
* cp/cp-tree.h (ATTR_IS_DEPENDENT): New macro. (MAYBE_TAGGED_TYPE_P): Remove. * cp/pt.c (apply_late_template_attributes): Check ATTR_IS_DEPENDENT instead of calling is_late_template_attribute again. (tsubst_decl) [TYPE_DECL]: Just check if the name is the tag. (tsubst): A typedef is a TYPE_NAME != TYPE_MAIN_DECL. Don't crash on typedefs from non-template classes. * cp/decl2.c (grokfield): Don't sorry about attrs on template parms. (is_late_template_attribute): All attributes applied to template parms or typename types are dependent. Static, take decl. (splice_template_attributes): Pass decl through. (save_template_attributes): Likewise. * attribs.c (lookup_attribute_spec): Split out... (decl_attributes): From here. * tree.h: Declare it. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@128681 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/attribs.c23
-rw-r--r--gcc/cp/ChangeLog16
-rw-r--r--gcc/cp/cp-tree.h10
-rw-r--r--gcc/cp/decl2.c43
-rw-r--r--gcc/cp/pt.c37
-rw-r--r--gcc/testsuite/g++.dg/ext/attrib20.C6
-rw-r--r--gcc/testsuite/g++.dg/ext/tmplattr5.C33
-rw-r--r--gcc/testsuite/g++.dg/template/typedef7.C15
-rw-r--r--gcc/tree.h2
10 files changed, 136 insertions, 56 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 85934036f35..2de9c65b9ad 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2007-09-22 Jason Merrill <jason@redhat.com>
+
+ PR c++/19407
+ * attribs.c (lookup_attribute_spec): Split out...
+ (decl_attributes): From here.
+ * tree.h: Declare it.
+
2007-09-22 Richard Sandiford <rsandifo@nildram.co.uk>
* doc/sourcebuild.texi: Document dg-add-options mips16_attribute.
diff --git a/gcc/attribs.c b/gcc/attribs.c
index feb1c301570..31b92cad508 100644
--- a/gcc/attribs.c
+++ b/gcc/attribs.c
@@ -195,6 +195,20 @@ init_attributes (void)
}
attributes_initialized = true;
}
+
+/* Return the spec for the attribute named NAME. */
+
+const struct attribute_spec *
+lookup_attribute_spec (tree name)
+{
+ struct substring attr;
+
+ attr.str = IDENTIFIER_POINTER (name);
+ attr.length = IDENTIFIER_LENGTH (name);
+ extract_attribute_substring (&attr);
+ return htab_find_with_hash (attribute_hash, &attr,
+ substring_hash (attr.str, attr.length));
+}
/* Process the attributes listed in ATTRIBUTES and install them in *NODE,
which is either a DECL (including a TYPE_DECL) or a TYPE. If a DECL,
@@ -221,16 +235,9 @@ decl_attributes (tree *node, tree attributes, int flags)
tree name = TREE_PURPOSE (a);
tree args = TREE_VALUE (a);
tree *anode = node;
- const struct attribute_spec *spec = NULL;
+ const struct attribute_spec *spec = lookup_attribute_spec (name);
bool no_add_attrs = 0;
tree fn_ptr_tmp = NULL_TREE;
- struct substring attr;
-
- attr.str = IDENTIFIER_POINTER (name);
- attr.length = IDENTIFIER_LENGTH (name);
- extract_attribute_substring (&attr);
- spec = htab_find_with_hash (attribute_hash, &attr,
- substring_hash (attr.str, attr.length));
if (spec == NULL)
{
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 5310aa9e4a9..4c4e5847d3a 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,19 @@
+2007-09-22 Jason Merrill <jason@redhat.com>
+
+ PR c++/19407
+ * cp-tree.h (ATTR_IS_DEPENDENT): New macro.
+ (MAYBE_TAGGED_TYPE_P): Remove.
+ * pt.c (apply_late_template_attributes): Check ATTR_IS_DEPENDENT
+ instead of calling is_late_template_attribute again.
+ (tsubst_decl) [TYPE_DECL]: Just check if the name is the tag.
+ (tsubst): A typedef is a TYPE_NAME != TYPE_MAIN_DECL.
+ Don't crash on typedefs from non-template classes.
+ * decl2.c (grokfield): Don't sorry about attrs on template parms.
+ (is_late_template_attribute): All attributes applied to template
+ parms or typename types are dependent. Static.
+ (splice_template_attributes): Pass decl through.
+ (save_template_attributes): Likewise.
+
2007-09-20 Jakub Jelinek <jakub@redhat.com>
PR c++/33496
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 1ddf88492c6..fbe1bcc0170 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -58,6 +58,7 @@ struct diagnostic_context;
TARGET_EXPR_IMPLICIT_P (in TARGET_EXPR)
TEMPLATE_PARM_PARAMETER_PACK (in TEMPLATE_PARM_INDEX)
TYPE_REF_IS_RVALUE (in REFERENCE_TYPE)
+ ATTR_IS_DEPENDENT (in the TREE_LIST for an attribute)
1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE)
TI_PENDING_TEMPLATE_FLAG.
TEMPLATE_PARMS_FOR_INLINE.
@@ -988,10 +989,6 @@ 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"'. */
@@ -2134,6 +2131,10 @@ struct lang_decl GTY(())
directives */
#define TREE_INDIRECT_USING(NODE) (TREE_LIST_CHECK (NODE)->base.lang_flag_0)
+/* In a TREE_LIST in an attribute list, indicates that the attribute
+ must be applied at instantiation time. */
+#define ATTR_IS_DEPENDENT(NODE) (TREE_LIST_CHECK (NODE)->base.lang_flag_0)
+
extern tree decl_shadowed_for_var_lookup (tree);
extern void decl_shadowed_for_var_insert (tree, tree);
@@ -4280,7 +4281,6 @@ extern tree grokfield (const cp_declarator *, cp_decl_specifier_seq *,
tree, bool, tree, tree);
extern tree grokbitfield (const cp_declarator *, cp_decl_specifier_seq *,
tree);
-extern bool is_late_template_attribute (tree);
extern void cplus_decl_attributes (tree *, tree, int);
extern void finish_anon_union (tree);
extern void cp_write_global_declarations (void);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index a8c0f9262a0..d58194265db 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -800,16 +800,7 @@ grokfield (const cp_declarator *declarator,
value = push_template_decl (value);
if (attrlist)
- {
- /* Avoid storing attributes in template parameters:
- tsubst is not ready to handle them. */
- tree type = TREE_TYPE (value);
- if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
- || TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
- sorry ("applying attributes to template parameters is not implemented");
- else
- cplus_decl_attributes (&value, attrlist, 0);
- }
+ cplus_decl_attributes (&value, attrlist, 0);
return value;
}
@@ -988,24 +979,43 @@ grokbitfield (const cp_declarator *declarator,
/* Returns true iff ATTR is an attribute which needs to be applied at
instantiation time rather than template definition time. */
-bool
-is_late_template_attribute (tree attr)
+static bool
+is_late_template_attribute (tree attr, tree decl)
{
tree name = TREE_PURPOSE (attr);
tree args = TREE_VALUE (attr);
+ const struct attribute_spec *spec = lookup_attribute_spec (name);
+
if (is_attribute_p ("aligned", name)
&& args
&& value_dependent_expression_p (TREE_VALUE (args)))
+ /* Can't apply this until we know the desired alignment. */
return true;
+ else if (TREE_CODE (decl) == TYPE_DECL || spec->type_required)
+ {
+ tree type = TYPE_P (decl) ? decl : TREE_TYPE (decl);
+
+ /* We can't apply any attributes to a completely unknown type until
+ instantiation time. */
+ enum tree_code code = TREE_CODE (type);
+ if (code == TEMPLATE_TYPE_PARM
+ || code == BOUND_TEMPLATE_TEMPLATE_PARM
+ || code == TYPENAME_TYPE)
+ return true;
+ else
+ return false;
+ }
else
return false;
}
/* ATTR_P is a list of attributes. Remove any attributes which need to be
- applied at instantiation time and return them. */
+ applied at instantiation time and return them. If IS_DEPENDENT is true,
+ the declaration itself is dependent, so all attributes should be applied
+ at instantiation time. */
static tree
-splice_template_attributes (tree *attr_p)
+splice_template_attributes (tree *attr_p, tree decl)
{
tree *p = attr_p;
tree late_attrs = NULL_TREE;
@@ -1016,8 +1026,9 @@ splice_template_attributes (tree *attr_p)
for (; *p; )
{
- if (is_late_template_attribute (*p))
+ if (is_late_template_attribute (*p, decl))
{
+ ATTR_IS_DEPENDENT (*p) = 1;
*q = *p;
*p = TREE_CHAIN (*p);
q = &TREE_CHAIN (*q);
@@ -1036,7 +1047,7 @@ splice_template_attributes (tree *attr_p)
static void
save_template_attributes (tree *attr_p, tree *decl_p)
{
- tree late_attrs = splice_template_attributes (attr_p);
+ tree late_attrs = splice_template_attributes (attr_p, *decl_p);
tree *q;
if (!late_attrs)
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 8accea4afad..c9ec37034a5 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -6494,20 +6494,14 @@ 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))
+ if (ATTR_IS_DEPENDENT (t))
late_attrs = tree_cons
(TREE_PURPOSE (t),
tsubst_expr (TREE_VALUE (t), args, complain, in_decl,
/*integral_constant_expression_p=*/false),
late_attrs);
- --processing_template_decl;
-
cplus_decl_attributes (decl_p, late_attrs, attr_flags);
}
@@ -8085,20 +8079,16 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
bool local_p;
if (TREE_CODE (t) == TYPE_DECL
- && MAYBE_TAGGED_TYPE_P (TREE_TYPE (t)))
+ && t == TYPE_MAIN_DECL (TREE_TYPE (t)))
{
+ /* If this is the canonical decl, we don't have to
+ mess with instantiations, and often we can't (for
+ typename, template type parms and such). Note that
+ TYPE_NAME is not correct for the above test if
+ we've copied the type for a typedef. */
type = tsubst (TREE_TYPE (t), args, complain, in_decl);
- if (TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM
- || t == TYPE_MAIN_DECL (TREE_TYPE (t)))
- {
- /* If this is the canonical decl, we don't have to
- mess with instantiations, and often we can't (for
- typename, template type parms and such). Note that
- TYPE_NAME is not correct for the above test if
- we've copied the type for a typedef. */
- r = TYPE_NAME (type);
- break;
- }
+ r = TYPE_NAME (type);
+ break;
}
/* Check to see if we already have the specialization we
@@ -8555,16 +8545,15 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
gcc_assert (type != unknown_type_node);
/* Reuse typedefs. We need to do this to handle dependent attributes,
- specifically attribute aligned. */
+ such as attribute aligned. */
if (TYPE_P (t)
&& TYPE_NAME (t)
- && !MAYBE_TAGGED_TYPE_P (t)
- && TREE_CODE (t) != TEMPLATE_TEMPLATE_PARM
- && TREE_CODE (t) != UNBOUND_CLASS_TEMPLATE)
+ && TYPE_NAME (t) != TYPE_MAIN_DECL (t))
{
tree decl = TYPE_NAME (t);
- if (DECL_CLASS_SCOPE_P (decl))
+ if (DECL_CLASS_SCOPE_P (decl)
+ && CLASSTYPE_TEMPLATE_INFO (DECL_CONTEXT (decl)))
{
tree tmpl = most_general_template (DECL_TI_TEMPLATE (decl));
tree gen_args = tsubst (DECL_TI_ARGS (decl), args, complain, in_decl);
diff --git a/gcc/testsuite/g++.dg/ext/attrib20.C b/gcc/testsuite/g++.dg/ext/attrib20.C
index e46e8ae2077..25b27f307b5 100644
--- a/gcc/testsuite/g++.dg/ext/attrib20.C
+++ b/gcc/testsuite/g++.dg/ext/attrib20.C
@@ -7,8 +7,8 @@ template <typename T>
struct BVector
{
typedef T T2;
- typedef T value_type __attribute__ ((aligned(8))); // { dg-bogus "attribute" "attribute" { xfail *-*-* } }
- typedef T2 value_type2 __attribute__ ((aligned(8))); // { dg-bogus "attribute" "attribute" { xfail *-*-* } }
+ typedef T value_type __attribute__ ((aligned(8))); // { dg-bogus "attribute" "attribute" }
+ typedef T2 value_type2 __attribute__ ((aligned(8))); // { dg-bogus "attribute" "attribute" }
value_type v;
};
BVector<int> m;
@@ -16,7 +16,7 @@ BVector<int> m;
template <template <class> class T>
struct BV2
{
- typedef T<float> value_type __attribute__((aligned(8))); // { dg-bogus "attribute" "attribute" { xfail *-*-* } }
+ typedef T<float> value_type __attribute__((aligned(8))); // { dg-bogus "attribute" "attribute" }
value_type v;
};
BV2<BVector> m2;
diff --git a/gcc/testsuite/g++.dg/ext/tmplattr5.C b/gcc/testsuite/g++.dg/ext/tmplattr5.C
new file mode 100644
index 00000000000..30138d44aab
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/tmplattr5.C
@@ -0,0 +1,33 @@
+// PR c++/19407
+// { dg-do run }
+
+typedef float global_vector_type __attribute__((vector_size(16)));
+
+template <class T> struct A
+{
+ typedef T type;
+};
+
+template < typename Val > struct S
+{
+ typedef typename A<Val>::type vector_type __attribute__((vector_size(16)));
+ typedef Val vector_type2 __attribute__((vector_size(16)));
+ int pr_size() { return sizeof(vector_type); }
+ int pr_size2() { return sizeof(vector_type2); }
+};
+
+int main()
+{
+ if (sizeof (S<float>::vector_type) != sizeof (global_vector_type))
+ return 1;
+ if (sizeof (S<float>::vector_type2) != sizeof (global_vector_type))
+ return 2;
+
+ S<float> x;
+ if (x.pr_size() != sizeof (global_vector_type))
+ return 3;
+ if (x.pr_size2() != sizeof (global_vector_type))
+ return 4;
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/template/typedef7.C b/gcc/testsuite/g++.dg/template/typedef7.C
new file mode 100644
index 00000000000..2d39c90b9ee
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typedef7.C
@@ -0,0 +1,15 @@
+// An intermediate version of the fix for c++/19407 broke this example.
+
+struct A
+{
+ typedef struct { int i; } S;
+};
+
+template <class T>
+struct B: public A
+{
+ template <class U>
+ static S f ();
+};
+
+template struct B<int>;
diff --git a/gcc/tree.h b/gcc/tree.h
index d7ca0b2a78d..e893dea098a 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -5002,6 +5002,8 @@ extern bool must_pass_in_stack_var_size_or_pad (enum machine_mode, const_tree);
/* In attribs.c. */
+extern const struct attribute_spec *lookup_attribute_spec (tree);
+
/* Process the attributes listed in ATTRIBUTES and install them in *NODE,
which is either a DECL (including a TYPE_DECL) or a TYPE. If a DECL,
it should be modified in place; if a TYPE, a copy should be created