diff options
author | Jason Merrill <jason@redhat.com> | 2016-08-09 18:03:07 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2016-08-09 18:03:07 -0400 |
commit | f3365c1201908df5e3f929cc8fec3f4b88c126c6 (patch) | |
tree | aff9bbf2a3b0a1784c16e435791500d42f2046d1 /gcc | |
parent | b7597ae57977ff3d4ff359141a471acf22001f92 (diff) | |
download | gcc-f3365c1201908df5e3f929cc8fec3f4b88c126c6.zip gcc-f3365c1201908df5e3f929cc8fec3f4b88c126c6.tar.gz gcc-f3365c1201908df5e3f929cc8fec3f4b88c126c6.tar.bz2 |
PR c++/68703 - bogus error with dependent vector length
gcc/c-family/
* c-common.c (c_common_attribute_table): vector_size affects type
identity.
gcc/cp/
* decl2.c (any_dependent_type_attributes_p): New.
* pt.c (dependent_type_p_r, type_dependent_expression_p): Check it.
* semantics.c (finish_id_expression): Check it.
* typeck.c (finish_class_member_access_expr): Check it.
From-SVN: r239309
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/c-family/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/c-family/c-common.c | 2 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 1 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 16 | ||||
-rw-r--r-- | gcc/cp/pt.c | 9 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 6 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/vector32.C | 18 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/vector32a.C | 18 |
10 files changed, 85 insertions, 1 deletions
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index a1dbc73..def4e11 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,8 @@ +2016-08-09 Jason Merrill <jason@redhat.com> + + * c-common.c (c_common_attribute_table): vector_size affects type + identity. + 2016-08-09 Marek Polacek <polacek@redhat.com> PR c/7652 diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 569f000..7fd84ee 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -754,7 +754,7 @@ const struct attribute_spec c_common_attribute_table[] = { "deprecated", 0, 1, false, false, false, handle_deprecated_attribute, false }, { "vector_size", 1, 1, false, true, false, - handle_vector_size_attribute, false }, + handle_vector_size_attribute, true }, { "visibility", 1, 1, false, false, false, handle_visibility_attribute, false }, { "tls_model", 1, 1, true, false, false, diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index c71ea17..ca04d64 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,11 @@ 2016-08-09 Jason Merrill <jason@redhat.com> + PR c++/68703 + * decl2.c (any_dependent_type_attributes_p): New. + * pt.c (dependent_type_p_r, type_dependent_expression_p): Check it. + * semantics.c (finish_id_expression): Check it. + * typeck.c (finish_class_member_access_expr): Check it. + PR c++/71712 * class.c (check_abi_tags): Don't duplicate tags for conversion ops. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index f32613c..f98b1c4 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5852,6 +5852,7 @@ 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, tree); +extern bool any_dependent_type_attributes_p (tree); extern tree cp_reconstruct_complex_type (tree, tree); extern bool attributes_naming_typedef_ok (tree); extern void cplus_decl_attributes (tree *, tree, int); diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 1daa9f5..55bb987 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -1305,6 +1305,22 @@ save_template_attributes (tree *attr_p, tree *decl_p) } } +/* True if ATTRS contains any dependent attributes that affect type + identity. */ + +bool +any_dependent_type_attributes_p (tree attrs) +{ + for (tree a = attrs; a; a = TREE_CHAIN (a)) + if (ATTR_IS_DEPENDENT (a)) + { + const attribute_spec *as = lookup_attribute_spec (TREE_PURPOSE (a)); + if (as && as->affects_type_identity) + return true; + } + return false; +} + /* Return true iff ATTRS are acceptable attributes to be applied in-place to a typedef which gives a previously unnamed class or enum a name for linkage purposes. */ diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 3884082..2638564 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -22673,6 +22673,9 @@ dependent_type_p_r (tree type) if (TREE_CODE (type) == TYPE_PACK_EXPANSION) return true; + if (any_dependent_type_attributes_p (TYPE_ATTRIBUTES (type))) + return true; + /* The standard does not specifically mention types that are local to template functions or local classes, but they should be considered dependent too. For example: @@ -23225,6 +23228,12 @@ type_dependent_expression_p (tree expression) gcc_assert (TREE_CODE (expression) != TYPE_DECL); + /* Dependent type attributes might not have made it from the decl to + the type yet. */ + if (DECL_P (expression) + && any_dependent_type_attributes_p (DECL_ATTRIBUTES (expression))) + return true; + return (dependent_type_p (TREE_TYPE (expression))); } diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 4bffe6d..bffdddb 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -3548,6 +3548,12 @@ finish_id_expression (tree id_expression, resolve the name at instantiation time. */ if (dependent_p) { + if (DECL_P (decl) + && any_dependent_type_attributes_p (DECL_ATTRIBUTES (decl))) + /* Dependent type attributes on the decl mean that the TREE_TYPE is + wrong, so just return the identifier. */ + return id_expression; + /* If we found a variable, then name lookup during the instantiation will always resolve to the same VAR_DECL (or an instantiation thereof). */ diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index bedc453..a591d29 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -2853,6 +2853,11 @@ finish_class_member_access_expr (cp_expr object, tree name, bool template_p, } if (member == error_mark_node) return error_mark_node; + if (DECL_P (member) + && any_dependent_type_attributes_p (DECL_ATTRIBUTES (member))) + /* Dependent type attributes on the decl mean that the TREE_TYPE is + wrong, so don't use it. */ + goto dependent; if (TREE_CODE (member) == USING_DECL && DECL_DEPENDENT_P (member)) goto dependent; } diff --git a/gcc/testsuite/g++.dg/ext/vector32.C b/gcc/testsuite/g++.dg/ext/vector32.C new file mode 100644 index 0000000..8901d0b --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/vector32.C @@ -0,0 +1,18 @@ +// PR c++/68703 + +template <int N> +struct D { + int v __attribute__((vector_size (N * sizeof (int)))); + int f1 () { return this->v[N-1]; } + int f2 () { return v[N-1]; } +}; + +int +main () +{ + D<4> a = { { 0, 1, 2, 3 } }; + D<8> b = { { 0, 1, 2, 3, 4, 5, 6, 7 } }; + if (a.f1 () != 3 || a.f2 () != 3 + || b.f1 () != 7 || b.f2 () != 7) + __builtin_abort (); +} diff --git a/gcc/testsuite/g++.dg/ext/vector32a.C b/gcc/testsuite/g++.dg/ext/vector32a.C new file mode 100644 index 0000000..8901d0b --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/vector32a.C @@ -0,0 +1,18 @@ +// PR c++/68703 + +template <int N> +struct D { + int v __attribute__((vector_size (N * sizeof (int)))); + int f1 () { return this->v[N-1]; } + int f2 () { return v[N-1]; } +}; + +int +main () +{ + D<4> a = { { 0, 1, 2, 3 } }; + D<8> b = { { 0, 1, 2, 3, 4, 5, 6, 7 } }; + if (a.f1 () != 3 || a.f2 () != 3 + || b.f1 () != 7 || b.f2 () != 7) + __builtin_abort (); +} |