summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/c-family/ChangeLog11
-rw-r--r--gcc/c-family/c-common.c35
-rw-r--r--gcc/c-family/c-common.h2
-rw-r--r--gcc/c/ChangeLog7
-rw-r--r--gcc/c/c-typeck.c14
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/typeck.c7
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/c-c++-common/pr63764-1.c21
-rw-r--r--gcc/testsuite/c-c++-common/pr63764-2.c35
10 files changed, 133 insertions, 10 deletions
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index cf919132e4d..c9003ec66bd 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,14 @@
+2014-11-21 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/63764
+ * c-common.h (convert_vector_to_pointer_for_subscript): Change
+ return type to bool.
+ * c-common.c: Include gimple-expr.c.
+ (convert_vector_to_pointer_for_subscript): Change return type to
+ bool. If *vecp is not lvalue_p and has VECTOR_TYPE, return true
+ and copy it into a TARGET_EXPR and use that instead of *vecp
+ directly.
+
2014-11-19 David Malcolm <dmalcolm@redhat.com>
Merger of git branch "gimple-classes-v2-option-3".
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 95b6b1b93e0..bff8c2a5a9d 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -60,6 +60,7 @@ along with GCC; see the file COPYING3. If not see
#include "target-def.h"
#include "gimplify.h"
#include "wide-int-print.h"
+#include "gimple-expr.h"
cpp_reader *parse_in; /* Declared in c-pragma.h. */
@@ -12030,22 +12031,47 @@ build_userdef_literal (tree suffix_id, tree value,
}
/* For vector[index], convert the vector to a
- pointer of the underlying type. */
-void
+ pointer of the underlying type. Return true if the resulting
+ ARRAY_REF should not be an lvalue. */
+
+bool
convert_vector_to_pointer_for_subscript (location_t loc,
- tree* vecp, tree index)
+ tree *vecp, tree index)
{
+ bool ret = false;
if (TREE_CODE (TREE_TYPE (*vecp)) == VECTOR_TYPE)
{
tree type = TREE_TYPE (*vecp);
tree type1;
+ ret = !lvalue_p (*vecp);
if (TREE_CODE (index) == INTEGER_CST)
if (!tree_fits_uhwi_p (index)
|| tree_to_uhwi (index) >= TYPE_VECTOR_SUBPARTS (type))
warning_at (loc, OPT_Warray_bounds, "index value is out of bound");
- c_common_mark_addressable_vec (*vecp);
+ if (ret)
+ {
+ tree tmp = create_tmp_var_raw (type, NULL);
+ DECL_SOURCE_LOCATION (tmp) = loc;
+ *vecp = c_save_expr (*vecp);
+ if (TREE_CODE (*vecp) == C_MAYBE_CONST_EXPR)
+ {
+ bool non_const = C_MAYBE_CONST_EXPR_NON_CONST (*vecp);
+ *vecp = C_MAYBE_CONST_EXPR_EXPR (*vecp);
+ *vecp
+ = c_wrap_maybe_const (build4 (TARGET_EXPR, type, tmp,
+ *vecp, NULL_TREE, NULL_TREE),
+ non_const);
+ }
+ else
+ *vecp = build4 (TARGET_EXPR, type, tmp, *vecp,
+ NULL_TREE, NULL_TREE);
+ SET_EXPR_LOCATION (*vecp, loc);
+ c_common_mark_addressable_vec (tmp);
+ }
+ else
+ c_common_mark_addressable_vec (*vecp);
type = build_qualified_type (TREE_TYPE (type), TYPE_QUALS (type));
type1 = build_pointer_type (TREE_TYPE (*vecp));
bool ref_all = TYPE_REF_CAN_ALIAS_ALL (type1);
@@ -12065,6 +12091,7 @@ convert_vector_to_pointer_for_subscript (location_t loc,
*vecp = build1 (ADDR_EXPR, type1, *vecp);
*vecp = convert (type, *vecp);
}
+ return ret;
}
/* Determine which of the operands, if any, is a scalar that needs to be
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 7e53923a551..658cef0427d 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1310,7 +1310,7 @@ extern tree build_userdef_literal (tree suffix_id, tree value,
enum overflow_type overflow,
tree num_string);
-extern void convert_vector_to_pointer_for_subscript (location_t, tree*, tree);
+extern bool convert_vector_to_pointer_for_subscript (location_t, tree *, tree);
/* Possibe cases of scalar_to_vector conversion. */
enum stv_conv {
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index fa3c925e746..79d41830ee1 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,10 @@
+2014-11-21 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/63764
+ * c-typeck.c (build_array_ref): Adjust
+ convert_vector_to_pointer_for_subscript caller. If it returns true,
+ call non_lvalue_loc on the result.
+
2014-11-11 Richard Biener <rguenther@suse.de>
* c-decl.c (c_init_decl_processing): Do not set pedantic_lvalues
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 338ef44eefb..67efb465a24 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -2495,7 +2495,8 @@ build_array_ref (location_t loc, tree array, tree index)
gcc_assert (TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE);
- convert_vector_to_pointer_for_subscript (loc, &array, index);
+ bool non_lvalue
+ = convert_vector_to_pointer_for_subscript (loc, &array, index);
if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE)
{
@@ -2557,6 +2558,8 @@ build_array_ref (location_t loc, tree array, tree index)
| TREE_THIS_VOLATILE (array));
ret = require_complete_type (rval);
protected_set_expr_location (ret, loc);
+ if (non_lvalue)
+ ret = non_lvalue_loc (loc, ret);
return ret;
}
else
@@ -2569,9 +2572,12 @@ build_array_ref (location_t loc, tree array, tree index)
gcc_assert (TREE_CODE (TREE_TYPE (ar)) == POINTER_TYPE);
gcc_assert (TREE_CODE (TREE_TYPE (TREE_TYPE (ar))) != FUNCTION_TYPE);
- return build_indirect_ref
- (loc, build_binary_op (loc, PLUS_EXPR, ar, index, 0),
- RO_ARRAY_INDEXING);
+ ret = build_indirect_ref (loc, build_binary_op (loc, PLUS_EXPR, ar,
+ index, 0),
+ RO_ARRAY_INDEXING);
+ if (non_lvalue)
+ ret = non_lvalue_loc (loc, ret);
+ return ret;
}
}
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index ee431a1091d..033ce7b7499 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2014-11-21 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/63764
+ * typeck.c (cp_build_array_ref): Adjust
+ convert_vector_to_pointer_for_subscript caller. If it returns true,
+ call non_lvalue_loc on the result.
+
2014-11-20 Jason Merrill <jason@redhat.com>
PR c++/63658
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 71568515389..e100d70b1f2 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -3072,7 +3072,8 @@ cp_build_array_ref (location_t loc, tree array, tree idx,
break;
}
- convert_vector_to_pointer_for_subscript (loc, &array, idx);
+ bool non_lvalue
+ = convert_vector_to_pointer_for_subscript (loc, &array, idx);
if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE)
{
@@ -3155,6 +3156,8 @@ cp_build_array_ref (location_t loc, tree array, tree idx,
ret = require_complete_type_sfinae (fold_if_not_in_template (rval),
complain);
protected_set_expr_location (ret, loc);
+ if (non_lvalue)
+ ret = non_lvalue_loc (loc, ret);
return ret;
}
@@ -3194,6 +3197,8 @@ cp_build_array_ref (location_t loc, tree array, tree idx,
RO_ARRAY_INDEXING,
complain);
protected_set_expr_location (ret, loc);
+ if (non_lvalue)
+ ret = non_lvalue_loc (loc, ret);
return ret;
}
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index f065cc24c19..034f4d94174 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,9 @@
2014-11-21 Jakub Jelinek <jakub@redhat.com>
+ PR target/63764
+ * c-c++-common/pr63764-1.c: New test.
+ * c-c++-common/pr63764-2.c: New test.
+
PR target/63910
* gcc.target/i386/pr63910.c: New test.
diff --git a/gcc/testsuite/c-c++-common/pr63764-1.c b/gcc/testsuite/c-c++-common/pr63764-1.c
new file mode 100644
index 00000000000..a858747c7d8
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr63764-1.c
@@ -0,0 +1,21 @@
+/* PR target/63764 */
+/* { dg-do compile } */
+
+#define A __attribute__((vector_size (4 * sizeof (float))))
+typedef float V A;
+
+void
+fn1 (V *x)
+{
+ V a = *x;
+ ((V) a)[0] = 0; /* { dg-error "lvalue required as left operand of assignment" } */
+ *x = a;
+}
+
+void
+fn2 (V *x)
+{
+ float A a = *x;
+ ((float A) a)[0] = 0; /* { dg-error "lvalue required as left operand of assignment" } */
+ *x = a;
+}
diff --git a/gcc/testsuite/c-c++-common/pr63764-2.c b/gcc/testsuite/c-c++-common/pr63764-2.c
new file mode 100644
index 00000000000..6bbf6611e6c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr63764-2.c
@@ -0,0 +1,35 @@
+/* PR target/63764 */
+/* { dg-do compile } */
+
+#define A __attribute__((vector_size (4 * sizeof (float))))
+typedef float V A;
+
+float
+fn1 (V *x)
+{
+ V a = *x;
+ return ((V) a)[0];
+}
+
+float
+fn2 (V *x)
+{
+ float A a = *x;
+ return ((float A) a)[0];
+}
+
+void
+fn3 (V *x)
+{
+ V a = *x;
+ a[0] = 0;
+ *x = a;
+}
+
+void
+fn4 (V *x)
+{
+ float A a = *x;
+ a[0] = 0;
+ *x = a;
+}