Hi! As the following testcases show, diagnosing non-mappable type already in c*_decl_attributes is too early, the type might not be finalized and completed at that point for some variables yet.
This patch defers it until *finish_decl. Bootstrapped/regtested on x86_64-linux and i686-linux, committed to trunk and 8.2. 2018-07-12 Jakub Jelinek <ja...@redhat.com> * c-attribs.c (c_common_attribute_table): Add "omp declare target implicit" attribute. * c-decl.c (c_decl_attributes): Don't diagnose vars without mappable type here, instead add "omp declare target implicit" attribute. (finish_decl): Diagnose vars without mappable type here. * decl2.c (cplus_decl_attributes): Don't diagnose vars without mappable type here, instead add "omp declare target implicit" attribute. Add that attribute instead of "omp declare target" also when processing_template_decl. * decl.c (cp_finish_decl): Diagnose vars without mappable type here, and before calling cp_omp_mappable_type call complete_type. * c-c++-common/gomp/declare-target-3.c: New test. * g++.dg/gomp/declare-target-2.C: New test. --- gcc/c-family/c-attribs.c.jj 2018-07-12 09:33:07.648102554 +0200 +++ gcc/c-family/c-attribs.c 2018-07-12 16:18:46.483238747 +0200 @@ -439,6 +439,8 @@ const struct attribute_spec c_common_att handle_omp_declare_target_attribute, NULL }, { "omp declare target link", 0, 0, true, false, false, false, handle_omp_declare_target_attribute, NULL }, + { "omp declare target implicit", 0, 0, true, false, false, false, + handle_omp_declare_target_attribute, NULL }, { "alloc_align", 1, 1, false, true, true, false, handle_alloc_align_attribute, attr_alloc_exclusions }, --- gcc/c/c-decl.c.jj 2018-06-13 10:05:04.996092971 +0200 +++ gcc/c/c-decl.c 2018-07-12 17:48:35.370278519 +0200 @@ -4643,8 +4643,8 @@ c_decl_attributes (tree *node, tree attr { if (VAR_P (*node) && !lang_hooks.types.omp_mappable_type (TREE_TYPE (*node))) - error ("%q+D in declare target directive does not have mappable type", - *node); + attributes = tree_cons (get_identifier ("omp declare target implicit"), + NULL_TREE, attributes); else attributes = tree_cons (get_identifier ("omp declare target"), NULL_TREE, attributes); @@ -5223,7 +5223,27 @@ finish_decl (tree decl, location_t init_ diagnose_uninitialized_cst_member (decl, type); } - invoke_plugin_callbacks (PLUGIN_FINISH_DECL, decl); + if (flag_openmp + && VAR_P (decl) + && lookup_attribute ("omp declare target implicit", + DECL_ATTRIBUTES (decl))) + { + DECL_ATTRIBUTES (decl) + = remove_attribute ("omp declare target implicit", + DECL_ATTRIBUTES (decl)); + if (!lang_hooks.types.omp_mappable_type (TREE_TYPE (decl))) + error ("%q+D in declare target directive does not have mappable type", + decl); + else if (!lookup_attribute ("omp declare target", + DECL_ATTRIBUTES (decl)) + && !lookup_attribute ("omp declare target link", + DECL_ATTRIBUTES (decl))) + DECL_ATTRIBUTES (decl) + = tree_cons (get_identifier ("omp declare target"), + NULL_TREE, DECL_ATTRIBUTES (decl)); + } + + invoke_plugin_callbacks (PLUGIN_FINISH_DECL, decl); } /* Given a parsed parameter declaration, decode it into a PARM_DECL. --- gcc/cp/decl2.c.jj 2018-07-02 18:01:29.300224096 +0200 +++ gcc/cp/decl2.c 2018-07-12 17:48:35.367278517 +0200 @@ -1490,11 +1490,11 @@ cplus_decl_attributes (tree *decl, tree && DECL_CLASS_SCOPE_P (*decl)) error ("%q+D static data member inside of declare target directive", *decl); - else if (!processing_template_decl - && VAR_P (*decl) - && !cp_omp_mappable_type (TREE_TYPE (*decl))) - error ("%q+D in declare target directive does not have mappable type", - *decl); + else if (VAR_P (*decl) + && (processing_template_decl + || !cp_omp_mappable_type (TREE_TYPE (*decl)))) + attributes = tree_cons (get_identifier ("omp declare target implicit"), + NULL_TREE, attributes); else attributes = tree_cons (get_identifier ("omp declare target"), NULL_TREE, attributes); --- gcc/cp/decl.c.jj 2018-07-09 12:30:07.980161309 +0200 +++ gcc/cp/decl.c 2018-07-12 18:00:17.534803989 +0200 @@ -7222,6 +7222,27 @@ cp_finish_decl (tree decl, tree init, bo if (was_readonly) TREE_READONLY (decl) = 1; + if (flag_openmp + && VAR_P (decl) + && lookup_attribute ("omp declare target implicit", + DECL_ATTRIBUTES (decl))) + { + DECL_ATTRIBUTES (decl) + = remove_attribute ("omp declare target implicit", + DECL_ATTRIBUTES (decl)); + complete_type (TREE_TYPE (decl)); + if (!cp_omp_mappable_type (TREE_TYPE (decl))) + error ("%q+D in declare target directive does not have mappable type", + decl); + else if (!lookup_attribute ("omp declare target", + DECL_ATTRIBUTES (decl)) + && !lookup_attribute ("omp declare target link", + DECL_ATTRIBUTES (decl))) + DECL_ATTRIBUTES (decl) + = tree_cons (get_identifier ("omp declare target"), + NULL_TREE, DECL_ATTRIBUTES (decl)); + } + invoke_plugin_callbacks (PLUGIN_FINISH_DECL, decl); } --- gcc/testsuite/c-c++-common/gomp/declare-target-3.c.jj 2018-07-12 17:36:39.568731653 +0200 +++ gcc/testsuite/c-c++-common/gomp/declare-target-3.c 2018-07-12 17:36:29.606723571 +0200 @@ -0,0 +1,53 @@ +/* { dg-do compile } */ +/* { dg-options "-fopenmp" } */ + +#pragma omp declare target +int a[] = { 1, 2, 3 }; +extern int b[]; /* { dg-error "'b' in declare target directive does not have mappable type" } */ +extern int c[]; /* { dg-error "'c' in declare target directive does not have mappable type" } */ +extern int d[]; /* { dg-error "'d' in declare target directive does not have mappable type" } */ +int d[3]; +#pragma omp end declare target +int c[3]; +int e[] = { 1, 2, 3 }; +#pragma omp declare target to (e) +extern int f[]; +#pragma omp declare target to (f) /* { dg-error "'f' does not have a mappable type in 'to' clause" } */ +extern int g[]; +#pragma omp declare target to (g) /* { dg-error "'g' does not have a mappable type in 'to' clause" } */ +int g[3]; +extern int h[]; +int h[3]; +#pragma omp declare target to (h) + +int i[] = { 1, 2, 3 }; +int j[] = { 1, 2, 3 }; +extern int k[]; +extern int l[]; +extern int m[]; +extern int n[]; +extern int o[]; +extern int p[]; +int k[3]; +int l[3]; +int q; + +void +foo (void) +{ + #pragma omp target update to (q) to (i) + #pragma omp target map (tofrom: j) + ; + #pragma omp target update from (q) from (k) + #pragma omp target map (to: l) + ; + #pragma omp target update from (q) from (m) /* { dg-error "'m' does not have a mappable type in 'from' clause" } */ + #pragma omp target map (from: n) /* { dg-error "'n' does not have a mappable type in 'map' clause" } */ + ; + #pragma omp target update to (q) to (o) /* { dg-error "'o' does not have a mappable type in 'to' clause" } */ + #pragma omp target map (from: p) /* { dg-error "'p' does not have a mappable type in 'map' clause" } */ + ; +} + +int o[3]; +int p[3]; --- gcc/testsuite/g++.dg/gomp/declare-target-2.C.jj 2018-07-12 18:07:28.602121859 +0200 +++ gcc/testsuite/g++.dg/gomp/declare-target-2.C 2018-07-12 18:07:07.354106204 +0200 @@ -0,0 +1,18 @@ +// { dg-do compile } +// { dg-options "-fopenmp" } + +#pragma omp declare target +template <typename T> +struct S { T a; }; +template <typename T> +struct U { T a; }; +template <typename T> +struct V { T a; }; +template <typename T> +struct W { T a; }; + +S<int> d; +U<long> e[10]; +extern V<char> f[5]; +extern W<short> g[]; // { dg-error "'g' in declare target directive does not have mappable type" } +#pragma omp end declare target Jakub