@@ -27881,15 +27881,26 @@ cp_parser_omp_var_list_no_open (cp_parse
tree name, decl;
token = cp_lexer_peek_token (parser->lexer);
- name = cp_parser_id_expression (parser, /*template_p=*/false,
- /*check_dependency_p=*/true,
- /*template_p=*/NULL,
- /*declarator_p=*/false,
- /*optional_p=*/false);
- if (name == error_mark_node)
- goto skip_comma;
+ if (current_class_ptr && cp_parser_is_keyword (token, RID_THIS))
+ {
+ decl = finish_this_expr ();
+ if (TREE_CODE (decl) == NON_LVALUE_EXPR
+ || CONVERT_EXPR_P (decl))
+ decl = TREE_OPERAND (decl, 0);
+ cp_lexer_consume_token (parser->lexer);
+ }
+ else
+ {
+ name = cp_parser_id_expression (parser, /*template_p=*/false,
+ /*check_dependency_p=*/true,
+ /*template_p=*/NULL,
+ /*declarator_p=*/false,
+ /*optional_p=*/false);
+ if (name == error_mark_node)
+ goto skip_comma;
- decl = cp_parser_lookup_name_simple (parser, name, token->location);
+ decl = cp_parser_lookup_name_simple (parser, name, token->location);
+ }
if (decl == error_mark_node)
cp_parser_name_lookup_error (parser, name, decl, NLE_NULL,
token->location);
@@ -5998,6 +5998,7 @@ extern void note_decl_for_pch (tree);
extern tree omp_reduction_id (enum tree_code, tree, tree);
extern tree cp_remove_omp_priv_cleanup_stmt (tree *, int *, void *);
extern void cp_check_omp_declare_reduction (tree);
+extern void finish_omp_declare_simd_methods (tree);
extern tree finish_omp_clauses (tree, bool, bool = false);
extern tree push_omp_privatization_clauses (bool);
extern void pop_omp_privatization_clauses (tree);
@@ -4390,6 +4390,15 @@ handle_omp_array_sections_1 (tree c, tre
omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
return error_mark_node;
}
+ else if (TREE_CODE (t) == PARM_DECL
+ && DECL_ARTIFICIAL (t)
+ && DECL_NAME (t) == this_identifier)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<this%> allowed in OpenMP only in %<declare simd%>"
+ " clauses");
+ return error_mark_node;
+ }
else if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
&& VAR_P (t) && DECL_THREAD_LOCAL_P (t))
{
@@ -5491,6 +5500,39 @@ finish_omp_reduction_clause (tree c, boo
return false;
}
+/* Called from finish_struct_1. linear(this) or linear(this:step)
+ clauses might not be finalized yet because the class has been incomplete
+ when parsing #pragma omp declare simd methods. Fix those up now. */
+
+void
+finish_omp_declare_simd_methods (tree t)
+{
+ if (processing_template_decl)
+ return;
+
+ for (tree x = TYPE_METHODS (t); x; x = DECL_CHAIN (x))
+ {
+ if (TREE_CODE (TREE_TYPE (x)) != METHOD_TYPE)
+ continue;
+ tree ods = lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (x));
+ if (!ods || !TREE_VALUE (ods))
+ continue;
+ for (tree c = TREE_VALUE (TREE_VALUE (ods)); c; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
+ && integer_zerop (OMP_CLAUSE_DECL (c))
+ && OMP_CLAUSE_LINEAR_STEP (c)
+ && TREE_CODE (TREE_TYPE (OMP_CLAUSE_LINEAR_STEP (c)))
+ == POINTER_TYPE)
+ {
+ tree s = OMP_CLAUSE_LINEAR_STEP (c);
+ s = fold_convert_loc (OMP_CLAUSE_LOCATION (c), sizetype, s);
+ s = fold_build2_loc (OMP_CLAUSE_LOCATION (c), MULT_EXPR,
+ sizetype, s, TYPE_SIZE_UNIT (t));
+ OMP_CLAUSE_LINEAR_STEP (c) = s;
+ }
+ }
+}
+
/* For all elements of CLAUSES, validate them vs OpenMP constraints.
Remove any elements from the list that are invalid. */
@@ -5626,7 +5668,15 @@ finish_omp_clauses (tree clauses, bool a
break;
}
}
- else if (TREE_CODE (type) == POINTER_TYPE)
+ else if (TREE_CODE (type) == POINTER_TYPE
+ /* Can't multiply the step yet if *this
+ is still incomplete type. */
+ && (!declare_simd
+ || TREE_CODE (OMP_CLAUSE_DECL (c)) != PARM_DECL
+ || !DECL_ARTIFICIAL (OMP_CLAUSE_DECL (c))
+ || DECL_NAME (OMP_CLAUSE_DECL (c))
+ != this_identifier
+ || !TYPE_BEING_DEFINED (TREE_TYPE (type))))
{
tree d = convert_from_reference (OMP_CLAUSE_DECL (c));
t = pointer_int_sum (OMP_CLAUSE_LOCATION (c), PLUS_EXPR,
@@ -5655,6 +5705,16 @@ finish_omp_clauses (tree clauses, bool a
else
t = OMP_CLAUSE_DECL (c);
check_dup_generic_t:
+ if (t == current_class_ptr
+ && (!declare_simd
+ || (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
+ && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_UNIFORM)))
+ {
+ error ("%<this%> allowed in OpenMP only in %<declare simd%>"
+ " clauses");
+ remove = true;
+ break;
+ }
if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL
&& (!field_ok || TREE_CODE (t) != FIELD_DECL))
{
@@ -5696,6 +5756,13 @@ finish_omp_clauses (tree clauses, bool a
omp_note_field_privatization (t, OMP_CLAUSE_DECL (c));
else
t = OMP_CLAUSE_DECL (c);
+ if (t == current_class_ptr)
+ {
+ error ("%<this%> allowed in OpenMP only in %<declare simd%>"
+ " clauses");
+ remove = true;
+ break;
+ }
if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL
&& (!allow_fields || TREE_CODE (t) != FIELD_DECL))
{
@@ -5723,6 +5790,13 @@ finish_omp_clauses (tree clauses, bool a
omp_note_field_privatization (t, OMP_CLAUSE_DECL (c));
else
t = OMP_CLAUSE_DECL (c);
+ if (t == current_class_ptr)
+ {
+ error ("%<this%> allowed in OpenMP only in %<declare simd%>"
+ " clauses");
+ remove = true;
+ break;
+ }
if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL
&& (!allow_fields || TREE_CODE (t) != FIELD_DECL))
{
@@ -6000,6 +6074,13 @@ finish_omp_clauses (tree clauses, bool a
case OMP_CLAUSE_ALIGNED:
t = OMP_CLAUSE_DECL (c);
+ if (t == current_class_ptr && !declare_simd)
+ {
+ error ("%<this%> allowed in OpenMP only in %<declare simd%>"
+ " clauses");
+ remove = true;
+ break;
+ }
if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL)
{
if (processing_template_decl)
@@ -6086,6 +6167,12 @@ finish_omp_clauses (tree clauses, bool a
error ("%qE is not a variable in %<depend%> clause", t);
remove = true;
}
+ else if (t == current_class_ptr)
+ {
+ error ("%<this%> allowed in OpenMP only in %<declare simd%>"
+ " clauses");
+ remove = true;
+ }
else if (!processing_template_decl
&& !cxx_mark_addressable (t))
remove = true;
@@ -6139,6 +6226,13 @@ finish_omp_clauses (tree clauses, bool a
omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
remove = true;
}
+ else if (t == current_class_ptr)
+ {
+ error ("%<this%> allowed in OpenMP only in %<declare simd%>"
+ " clauses");
+ remove = true;
+ break;
+ }
else if (!processing_template_decl
&& TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE
&& !cxx_mark_addressable (t))
@@ -6651,6 +6651,8 @@ finish_struct_1 (tree t)
finish_struct_bits (t);
set_method_tm_attributes (t);
+ if (flag_openmp || flag_openmp_simd)
+ finish_omp_declare_simd_methods (t);
/* Complete the rtl for any static member objects of the type we're
working on. */
@@ -0,0 +1,55 @@
+// { dg-require-effective-target vect_simd_clones }
+// { dg-additional-options "-fopenmp-simd -fno-inline -DONE_FILE" }
+// { dg-additional-options "-mavx" { target avx_runtime } }
+
+#include "../../gcc.dg/vect/tree-vect.h"
+
+#ifdef ONE_FILE
+#include "simd-clone-3.cc"
+#else
+#include "simd-clone-2.h"
+#endif
+
+T b __attribute__((aligned (32)));
+
+void
+do_main ()
+{
+ int i, r = 0;
+ S a[64];
+ for (i = 0; i < 64; i++)
+ {
+ a[i].s = i;
+ b.t[i] = i;
+ }
+ #pragma omp simd reduction(+:r)
+ for (i = 0; i < 64; i++)
+ r += a[16].f0 (i);
+ if (r != 64 * 63 / 2 + 64 * 16)
+ __builtin_abort ();
+ r = 0;
+ #pragma omp simd reduction(+:r)
+ for (i = 0; i < 64; i++)
+ r += a[32].f1 (i);
+ if (r != 64 * 63 / 2 + 64 * 32)
+ __builtin_abort ();
+ r = 0;
+ #pragma omp simd reduction(+:r)
+ for (i = 0; i < 64; i++)
+ r += a[i].f2 (i);
+ if (r != 64 * 63)
+ __builtin_abort ();
+ r = 0;
+ #pragma omp simd reduction(+:r)
+ for (i = 0; i < 64; i++)
+ r += b.f3 (i);
+ if (r != 64 * 63 / 2)
+ __builtin_abort ();
+}
+
+int
+main ()
+{
+ check_vect ();
+ do_main ();
+}
@@ -0,0 +1,17 @@
+struct S
+{
+ int s;
+ #pragma omp declare simd notinbranch
+ int f0 (int x);
+ #pragma omp declare simd notinbranch uniform(this)
+ int f1 (int x);
+ #pragma omp declare simd notinbranch linear(this:sizeof(this)/sizeof(this))
+ int f2 (int x);
+};
+
+struct T
+{
+ int t[64];
+ #pragma omp declare simd aligned(this:32) uniform(this) linear(x)
+ int f3 (int x);
+};
@@ -0,0 +1,34 @@
+// { dg-require-effective-target vect_simd_clones }
+// { dg-additional-options "-fopenmp-simd -fno-inline" }
+// { dg-additional-options "-mavx" { target avx_runtime } }
+// { dg-additional-sources "simd-clone-2.cc" }
+
+#include "simd-clone-2.h"
+
+#pragma omp declare simd notinbranch
+int
+S::f0 (int x)
+{
+ return x + s;
+}
+
+#pragma omp declare simd notinbranch uniform(this)
+int
+S::f1 (int x)
+{
+ return x + s;
+}
+
+#pragma omp declare simd notinbranch linear(this:sizeof(this)/sizeof(this))
+int
+S::f2 (int x)
+{
+ return x + this->S::s;
+}
+
+#pragma omp declare simd uniform(this) aligned(this:32) linear(x)
+int
+T::f3 (int x)
+{
+ return t[x];
+}
@@ -0,0 +1,55 @@
+// { dg-require-effective-target vect_simd_clones }
+// { dg-additional-options "-fopenmp-simd -fno-inline -DONE_FILE" }
+// { dg-additional-options "-mavx" { target avx_runtime } }
+
+#include "../../gcc.dg/vect/tree-vect.h"
+
+#ifdef ONE_FILE
+#include "simd-clone-5.cc"
+#else
+#include "simd-clone-4.h"
+#endif
+
+T<0> b __attribute__((aligned (32)));
+
+void
+do_main ()
+{
+ int i, r = 0;
+ S<0> a[64];
+ for (i = 0; i < 64; i++)
+ {
+ a[i].s = i;
+ b.t[i] = i;
+ }
+ #pragma omp simd reduction(+:r)
+ for (i = 0; i < 64; i++)
+ r += a[16].f0 (i);
+ if (r != 64 * 63 / 2 + 64 * 16)
+ __builtin_abort ();
+ r = 0;
+ #pragma omp simd reduction(+:r)
+ for (i = 0; i < 64; i++)
+ r += a[32].f1 (i);
+ if (r != 64 * 63 / 2 + 64 * 32)
+ __builtin_abort ();
+ r = 0;
+ #pragma omp simd reduction(+:r)
+ for (i = 0; i < 64; i++)
+ r += a[i].f2 (i);
+ if (r != 64 * 63)
+ __builtin_abort ();
+ r = 0;
+ #pragma omp simd reduction(+:r)
+ for (i = 0; i < 64; i++)
+ r += b.f3 (i);
+ if (r != 64 * 63 / 2)
+ __builtin_abort ();
+}
+
+int
+main ()
+{
+ check_vect ();
+ do_main ();
+}
@@ -0,0 +1,19 @@
+template <int N>
+struct S
+{
+ int s;
+ #pragma omp declare simd notinbranch
+ int f0 (int x);
+ #pragma omp declare simd notinbranch uniform(this)
+ int f1 (int x);
+ #pragma omp declare simd notinbranch linear(this:sizeof(this)/sizeof(this))
+ int f2 (int x);
+};
+
+template <int N>
+struct T
+{
+ int t[64];
+ #pragma omp declare simd aligned(this:32) uniform(this) linear(x)
+ int f3 (int x);
+};
@@ -0,0 +1,41 @@
+// { dg-require-effective-target vect_simd_clones }
+// { dg-additional-options "-fopenmp-simd -fno-inline" }
+// { dg-additional-options "-mavx" { target avx_runtime } }
+// { dg-additional-sources "simd-clone-4.cc" }
+
+#include "simd-clone-4.h"
+
+#pragma omp declare simd notinbranch
+template <int N>
+int
+S<N>::f0 (int x)
+{
+ return x + s;
+}
+
+#pragma omp declare simd notinbranch uniform(this)
+template <int N>
+int
+S<N>::f1 (int x)
+{
+ return x + s;
+}
+
+#pragma omp declare simd notinbranch linear(this:sizeof(this)/sizeof(this))
+template <int N>
+int
+S<N>::f2 (int x)
+{
+ return x + this->S::s;
+}
+
+#pragma omp declare simd uniform(this) aligned(this:32) linear(x)
+template <int N>
+int
+T<N>::f3 (int x)
+{
+ return t[x];
+}
+
+template struct S<0>;
+template struct T<0>;
@@ -0,0 +1,68 @@
+// { dg-do compile }
+// { dg-options "-fopenmp" }
+
+struct S
+{
+ #pragma omp declare simd linear(this) // { dg-error "is not an function argument" }
+ static void foo ();
+ void bar ();
+};
+
+void
+S::bar ()
+{
+ #pragma omp parallel firstprivate (this) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+ ;
+ #pragma omp parallel for lastprivate (this) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+ for (int i = 0; i < 10; i++)
+ ;
+ #pragma omp parallel shared (this) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+ ;
+ #pragma omp for linear (this) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+ for (int i = 0; i < 10; i++)
+ ;
+ #pragma omp task depend(inout: this) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+ ;
+ #pragma omp task depend(inout: this[0]) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+ ;
+ #pragma omp parallel private (this) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+ {
+ #pragma omp single copyprivate (this) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+ ;
+ }
+}
+
+template <int N>
+struct T
+{
+ #pragma omp declare simd linear(this) // { dg-error "is not an function argument" }
+ static void foo ();
+ void bar ();
+};
+
+template <int N>
+void
+T<N>::bar ()
+{
+ #pragma omp parallel firstprivate (this) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+ ;
+ #pragma omp parallel for lastprivate (this) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+ for (int i = 0; i < 10; i++)
+ ;
+ #pragma omp parallel shared (this) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+ ;
+ #pragma omp for linear (this) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+ for (int i = 0; i < 10; i++)
+ ;
+ #pragma omp task depend(inout: this) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+ ;
+ #pragma omp task depend(inout: this[0]) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+ ;
+ #pragma omp parallel private (this) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+ {
+ #pragma omp single copyprivate (this) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+ ;
+ }
+}
+
+template struct T<0>;
@@ -0,0 +1,42 @@
+// { dg-do compile }
+// { dg-options "-fopenmp" }
+
+struct S
+{
+ void bar (int);
+};
+
+void
+S::bar (int x)
+{
+ #pragma omp target map (this, x) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+ ;
+ #pragma omp target map (this[0], x) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+ ;
+ #pragma omp target update to (this, x) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+ #pragma omp target update to (this[0], x) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+ #pragma omp target update from (this, x) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+ #pragma omp target update from (this[1], x) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+}
+
+template <int N>
+struct T
+{
+ void bar (int);
+};
+
+template <int N>
+void
+T<N>::bar (int x)
+{
+ #pragma omp target map (this, x) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+ ;
+ #pragma omp target map (this[0], x) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+ ;
+ #pragma omp target update to (this, x) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+ #pragma omp target update to (this[0], x) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+ #pragma omp target update from (this, x) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+ #pragma omp target update from (this[1], x) // { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+}
+
+template struct T<0>;