public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
From: Tobias Burnus <burnus@gcc.gnu.org>
To: gcc-cvs@gcc.gnu.org
Subject: [gcc/devel/omp/gcc-12] openmp: Add begin declare target support
Date: Tue,  4 Oct 2022 09:40:39 +0000 (GMT)	[thread overview]
Message-ID: <20221004094039.E050E3858413@sourceware.org> (raw)

https://gcc.gnu.org/g:65d065bbad94e07a709be8d49a92de50f9e454dd

commit 65d065bbad94e07a709be8d49a92de50f9e454dd
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Tue Oct 4 10:58:28 2022 +0200

    openmp: Add begin declare target support
    
    The following patch adds support for the begin declare target construct,
    which is another spelling for declare target construct without clauses
    (where it needs paired end declare target), but unlike that one accepts
    clauses.
    
    This is an OpenMP 5.1 feature, implemented with 5.2 clarification because
    in 5.1 we had a restriction in the declare target chapter shared by
    declare target and begin declare target that if there are any clauses
    specified at least one of them needs to be to or link.  But that
    was of course meant just for declare target and not begin declare target,
    because begin declare target doesn't even allow to/link/enter clauses.
    In addition to that, the patch also makes device_type clause duplication
    an error (as stated in 5.1) and similarly makes declare target with
    just device_type clause an error rather than warning.
    
    What this patch doesn't do is:
    1) OpenMP 5.1 also added an indirect clause, we don't support that
       neither on declare target nor begin declare target
       and I couldn't find it in our features pages (neither libgomp.texi
       nor web)
    2) I think device_type(nohost)/device_type(host) support can't work for
       variables (in 5.0 it only talked about procedures so this could be
       also thought as 5.1 feature that we should just add to the list
       and implement)
    3) I don't see any use of the "omp declare target nohost" attribute, so
       I'm not sure if device_type(nohost) works at all
    
    2022-10-04  Jakub Jelinek  <jakub@redhat.com>
    
    gcc/c-family/
            * c-omp.cc (c_omp_directives): Uncomment begin declare target
            entry.
    gcc/c/
            * c-lang.h (struct c_omp_declare_target_attr): New type.
            (current_omp_declare_target_attribute): Change type from
            int to vec<c_omp_declare_target_attr, va_gc> *.
            * c-parser.cc (c_parser_translation_unit): Adjust for that change.
            If last pushed directive was begin declare target, use different
            wording and simplify format strings for easier translations.
            (c_parser_omp_clause_device_type): Uncomment
            check_no_duplicate_clause call.
            (c_parser_omp_declare_target): Adjust for the
            current_omp_declare_target_attribute type change, push { -1 }.
            Use error_at rather than warning_at for declare target with
            only device_type clauses.
            (OMP_BEGIN_DECLARE_TARGET_CLAUSE_MASK): Define.
            (c_parser_omp_begin): Add begin declare target support.
            (c_parser_omp_end): Adjust for the
            current_omp_declare_target_attribute type change, adjust
            diagnostics wording and simplify format strings for easier
            translations.
            * c-decl.cc (current_omp_declare_target_attribute): Change type from
            int to vec<c_omp_declare_target_attr, va_gc> *.
            (c_decl_attributes): Adjust for the
            current_omp_declare_target_attribute type change.  If device_type
            was present on begin declare target, add "omp declare target host"
            and/or "omp declare target nohost" attributes.
    gcc/cp/
            * cp-tree.h (struct omp_declare_target_attr): Rename to ...
            (cp_omp_declare_target_attr): ... this.  Add device_type member.
            (omp_begin_assumes_data): Rename to ...
            (cp_omp_begin_assumes_data): ... this.
            (struct saved_scope): Change types of omp_declare_target_attribute
            and omp_begin_assumes.
            * parser.cc (cp_parser_omp_clause_device_type): Uncomment
            check_no_duplicate_clause call.
            (cp_parser_omp_all_clauses): Fix up pasto, c_name for OMP_CLAUSE_LINK
            should be "link" rather than "to".
            (cp_parser_omp_declare_target): Adjust for omp_declare_target_attr
            to cp_omp_declare_target_attr changes, push -1 as device_type.  Use
            error_at rather than warning_at for declare target with only
            device_type clauses.
            (OMP_BEGIN_DECLARE_TARGET_CLAUSE_MASK): Define.
            (cp_parser_omp_begin): Add begin declare target support.  Adjust
            for omp_begin_assumes_data to cp_omp_begin_assumes_data change.
            (cp_parser_omp_end): Adjust for the
            omp_declare_target_attr to cp_omp_declare_target_attr and
            omp_begin_assumes_data to cp_omp_begin_assumes_data type changes,
            adjust diagnostics wording and simplify format strings for easier
            translations.
            * semantics.cc (finish_translation_unit): Likewise.
            * decl2.cc (cplus_decl_attributes): If device_type was present on
            begin declare target, add "omp declare target host" and/or
            "omp declare target nohost" attributes.
    gcc/testsuite/
            * c-c++-common/gomp/declare-target-4.c: Move tests that are now
            rejected into declare-target-7.c.
            * c-c++-common/gomp/declare-target-6.c: Adjust expected diagnostics.
            * c-c++-common/gomp/declare-target-7.c: New test.
            * c-c++-common/gomp/begin-declare-target-1.c: New test.
            * c-c++-common/gomp/begin-declare-target-2.c: New test.
            * c-c++-common/gomp/begin-declare-target-3.c: New test.
            * c-c++-common/gomp/begin-declare-target-4.c: New test.
            * g++.dg/gomp/attrs-9.C: Add begin declare target tests.
            * g++.dg/gomp/attrs-18.C: New test.
    libgomp/
            * libgomp.texi (Support begin/end declare target syntax in C/C++):
            Mark as implemented.
    
    (cherry picked from commit b6d5d72bd0b71ac96a8b2ee537367c46107dcb73)

Diff:
---
 gcc/c-family/ChangeLog.omp                         |  8 ++
 gcc/c-family/c-omp.cc                              |  4 +-
 gcc/c/ChangeLog.omp                                | 30 +++++++
 gcc/c/c-decl.cc                                    | 24 +++++-
 gcc/c/c-lang.h                                     |  7 +-
 gcc/c/c-parser.cc                                  | 75 ++++++++++++-----
 gcc/cp/ChangeLog.omp                               | 32 ++++++++
 gcc/cp/cp-tree.h                                   |  9 ++-
 gcc/cp/decl2.cc                                    | 41 +++++++---
 gcc/cp/parser.cc                                   | 93 ++++++++++++++++------
 gcc/cp/semantics.cc                                | 12 ++-
 gcc/testsuite/ChangeLog.omp                        | 23 ++++++
 .../c-c++-common/gomp/begin-declare-target-1.c     | 25 ++++++
 .../c-c++-common/gomp/begin-declare-target-2.c     | 18 +++++
 .../c-c++-common/gomp/begin-declare-target-3.c     | 19 +++++
 .../c-c++-common/gomp/begin-declare-target-4.c     |  2 +
 gcc/testsuite/c-c++-common/gomp/declare-target-4.c |  6 --
 gcc/testsuite/c-c++-common/gomp/declare-target-6.c |  2 +-
 gcc/testsuite/c-c++-common/gomp/declare-target-7.c |  8 ++
 gcc/testsuite/g++.dg/gomp/attrs-18.C               | 41 ++++++++++
 gcc/testsuite/g++.dg/gomp/attrs-9.C                | 15 ++++
 libgomp/ChangeLog.omp                              |  8 ++
 libgomp/libgomp.texi                               |  2 +-
 23 files changed, 429 insertions(+), 75 deletions(-)

diff --git a/gcc/c-family/ChangeLog.omp b/gcc/c-family/ChangeLog.omp
index 72c2e506844..5d2c8afbccc 100644
--- a/gcc/c-family/ChangeLog.omp
+++ b/gcc/c-family/ChangeLog.omp
@@ -1,3 +1,11 @@
+2022-10-04  Tobias Burnus  <tobias@codesourcery.com>
+
+	Backport from mainline:
+	2022-10-04  Jakub Jelinek  <jakub@redhat.com>
+
+	* c-omp.cc (c_omp_directives): Uncomment begin declare target
+	entry.
+
 2022-09-27  Tobias Burnus  <tobias@codesourcery.com>
 
 	Backport from mainline:
diff --git a/gcc/c-family/c-omp.cc b/gcc/c-family/c-omp.cc
index c8573953e41..3e95e77d487 100644
--- a/gcc/c-family/c-omp.cc
+++ b/gcc/c-family/c-omp.cc
@@ -3911,8 +3911,8 @@ const struct c_omp_directive c_omp_directives[] = {
     C_OMP_DIR_STANDALONE, false },
   { "begin", "assumes", nullptr, PRAGMA_OMP_BEGIN,
     C_OMP_DIR_INFORMATIONAL, false },
-  /* { "begin", "declare", "target", PRAGMA_OMP_BEGIN,
-    C_OMP_DIR_DECLARATIVE, false }, */
+  { "begin", "declare", "target", PRAGMA_OMP_BEGIN,
+    C_OMP_DIR_DECLARATIVE, false },
   /* { "begin", "declare", "variant", PRAGMA_OMP_BEGIN,
     C_OMP_DIR_DECLARATIVE, false }, */
   /* { "begin", "metadirective", nullptr, PRAGMA_OMP_BEGIN,
diff --git a/gcc/c/ChangeLog.omp b/gcc/c/ChangeLog.omp
index 1601b22cf63..33fec846593 100644
--- a/gcc/c/ChangeLog.omp
+++ b/gcc/c/ChangeLog.omp
@@ -1,3 +1,33 @@
+2022-10-04  Tobias Burnus  <tobias@codesourcery.com>
+
+	Backport from mainline:
+	2022-10-04  Jakub Jelinek  <jakub@redhat.com>
+
+	* c-lang.h (struct c_omp_declare_target_attr): New type.
+	(current_omp_declare_target_attribute): Change type from
+	int to vec<c_omp_declare_target_attr, va_gc> *.
+	* c-parser.cc (c_parser_translation_unit): Adjust for that change.
+	If last pushed directive was begin declare target, use different
+	wording and simplify format strings for easier translations.
+	(c_parser_omp_clause_device_type): Uncomment
+	check_no_duplicate_clause call.
+	(c_parser_omp_declare_target): Adjust for the
+	current_omp_declare_target_attribute type change, push { -1 }.
+	Use error_at rather than warning_at for declare target with
+	only device_type clauses.
+	(OMP_BEGIN_DECLARE_TARGET_CLAUSE_MASK): Define.
+	(c_parser_omp_begin): Add begin declare target support.
+	(c_parser_omp_end): Adjust for the
+	current_omp_declare_target_attribute type change, adjust
+	diagnostics wording and simplify format strings for easier
+	translations.
+	* c-decl.cc (current_omp_declare_target_attribute): Change type from
+	int to vec<c_omp_declare_target_attr, va_gc> *.
+	(c_decl_attributes): Adjust for the
+	current_omp_declare_target_attribute type change.  If device_type
+	was present on begin declare target, add "omp declare target host"
+	and/or "omp declare target nohost" attributes.
+
 2022-09-27  Tobias Burnus  <tobias@codesourcery.com>
 
 	Backport from mainline:
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 4de04f25b67..9641d6356b2 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -153,9 +153,9 @@ static int warn_about_return_type;
 
 static bool undef_nested_function;
 
-/* If non-zero, implicit "omp declare target" attribute is added into the
-   attribute lists.  */
-int current_omp_declare_target_attribute;
+/* Vector of implicit "omp declare target" attributes to be added into
+   the attribute lists.  */
+vec<c_omp_declare_target_attr, va_gc> *current_omp_declare_target_attribute;
 
 /* If non-zero, we are inside of
    #pragma omp begin assumes ... #pragma omp end assumes region.  */
@@ -5054,7 +5054,7 @@ static tree
 c_decl_attributes (tree *node, tree attributes, int flags)
 {
   /* Add implicit "omp declare target" attribute if requested.  */
-  if (current_omp_declare_target_attribute
+  if (vec_safe_length (current_omp_declare_target_attribute)
       && ((VAR_P (*node) && is_global_var (*node))
 	  || TREE_CODE (*node) == FUNCTION_DECL))
     {
@@ -5068,6 +5068,22 @@ c_decl_attributes (tree *node, tree attributes, int flags)
 	  attributes = tree_cons (get_identifier ("omp declare target block"),
 				  NULL_TREE, attributes);
 	}
+      if (TREE_CODE (*node) == FUNCTION_DECL)
+	{
+	  int device_type
+	    = current_omp_declare_target_attribute->last ().device_type;
+	  device_type = MAX (device_type, 0);
+	  if ((device_type & OMP_CLAUSE_DEVICE_TYPE_HOST) != 0
+	      && !lookup_attribute ("omp declare target host", attributes))
+	    attributes
+	      = tree_cons (get_identifier ("omp declare target host"),
+			   NULL_TREE, attributes);
+	  if ((device_type & OMP_CLAUSE_DEVICE_TYPE_NOHOST) != 0
+	      && !lookup_attribute ("omp declare target nohost", attributes))
+	    attributes
+	      = tree_cons (get_identifier ("omp declare target nohost"),
+			   NULL_TREE, attributes);
+	}
     }
 
   /* Look up the current declaration with all the attributes merged
diff --git a/gcc/c/c-lang.h b/gcc/c/c-lang.h
index 861abe8377a..49a5ec3d048 100644
--- a/gcc/c/c-lang.h
+++ b/gcc/c/c-lang.h
@@ -60,9 +60,14 @@ struct GTY(()) language_function {
   int warn_about_return_type;
 };
 
+struct GTY(()) c_omp_declare_target_attr {
+  int device_type;
+};
+
 /* If non-zero, implicit "omp declare target" attribute is added into the
    attribute lists.  */
-extern GTY(()) int current_omp_declare_target_attribute;
+extern GTY(()) vec<c_omp_declare_target_attr, va_gc>
+  *current_omp_declare_target_attribute;
 /* Similarly whether we are in between #pragma omp begin assumes and
    #pragma omp end assumes (and how many times when nested).  */
 extern GTY(()) int current_omp_begin_assumes;
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 0c520a44fff..9258ce57401 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -1688,18 +1688,22 @@ c_parser_translation_unit (c_parser *parser)
     if (DECL_SIZE (decl) == NULL_TREE && TREE_TYPE (decl) != error_mark_node)
       error ("storage size of %q+D isn%'t known", decl);
 
-  if (current_omp_declare_target_attribute)
+  if (vec_safe_length (current_omp_declare_target_attribute))
     {
+      c_omp_declare_target_attr
+	a = current_omp_declare_target_attribute->pop ();
       if (!errorcount)
-        error ("%<#pragma omp declare target%> without corresponding "
-	       "%<#pragma omp end declare target%>");
-      current_omp_declare_target_attribute = 0;
+	error ("%qs without corresponding %qs",
+	       a.device_type >= 0 ? "#pragma omp begin declare target"
+				  : "#pragma omp declare target",
+	       "#pragma omp end declare target");
+      vec_safe_truncate (current_omp_declare_target_attribute, 0);
     }
   if (current_omp_begin_assumes)
     {
       if (!errorcount)
-	error ("%<#pragma omp begin assumes%> without corresponding "
-	       "%<#pragma omp end assumes%>");
+	error ("%qs without corresponding %qs",
+	       "#pragma omp begin assumes", "#pragma omp end assumes");
       current_omp_begin_assumes = 0;
     }
 }
@@ -16970,8 +16974,8 @@ c_parser_omp_clause_device_type (c_parser *parser, tree list)
   else
     goto invalid_kind;
 
-  /* check_no_duplicate_clause (list, OMP_CLAUSE_DEVICE_TYPE,
-				"device_type");  */
+  check_no_duplicate_clause (list, OMP_CLAUSE_DEVICE_TYPE,
+			     "device_type");
   c_parser_consume_token (parser);
   parens.skip_until_found_close (parser);
   c = build_omp_clause (clause_loc, OMP_CLAUSE_DEVICE_TYPE);
@@ -22548,7 +22552,8 @@ c_parser_omp_declare_target (c_parser *parser)
   else
     {
       c_parser_skip_to_pragma_eol (parser);
-      current_omp_declare_target_attribute++;
+      c_omp_declare_target_attr attr = { -1 };
+      vec_safe_push (current_omp_declare_target_attribute, attr);
       return;
     }
   for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
@@ -22626,12 +22631,17 @@ c_parser_omp_declare_target (c_parser *parser)
 	}
     }
   if (device_type && only_device_type)
-    warning_at (OMP_CLAUSE_LOCATION (clauses), 0,
-		"directive with only %<device_type%> clauses ignored");
+    error_at (OMP_CLAUSE_LOCATION (clauses),
+	      "directive with only %<device_type%> clause");
 }
 
 /* OpenMP 5.1
-   #pragma omp begin assumes clauses[optseq] new-line  */
+   #pragma omp begin assumes clauses[optseq] new-line
+
+   #pragma omp begin declare target clauses[optseq] new-line  */
+
+#define OMP_BEGIN_DECLARE_TARGET_CLAUSE_MASK			\
+	(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE_TYPE)
 
 static void
 c_parser_omp_begin (c_parser *parser)
@@ -22640,7 +22650,33 @@ c_parser_omp_begin (c_parser *parser)
   c_parser_consume_pragma (parser);
   if (c_parser_next_token_is (parser, CPP_NAME))
     p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
-  if (strcmp (p, "assumes") == 0)
+  if (strcmp (p, "declare") == 0)
+    {
+      c_parser_consume_token (parser);
+      p = "";
+      if (c_parser_next_token_is (parser, CPP_NAME))
+	p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+      if (strcmp (p, "target") == 0)
+	{
+	  c_parser_consume_token (parser);
+	  tree clauses
+	    = c_parser_omp_all_clauses (parser,
+					OMP_BEGIN_DECLARE_TARGET_CLAUSE_MASK,
+					"#pragma omp begin declare target");
+	  int device_type = 0;
+	  for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
+	    if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE)
+	      device_type |= OMP_CLAUSE_DEVICE_TYPE_KIND (c);
+	  c_omp_declare_target_attr attr = { device_type };
+	  vec_safe_push (current_omp_declare_target_attribute, attr);
+	}
+      else
+	{
+	  c_parser_error (parser, "expected %<target%>");
+	  c_parser_skip_to_pragma_eol (parser);
+	}
+    }
+  else if (strcmp (p, "assumes") == 0)
     {
       c_parser_consume_token (parser);
       c_parser_omp_assumption_clauses (parser, false);
@@ -22648,7 +22684,7 @@ c_parser_omp_begin (c_parser *parser)
     }
   else
     {
-      c_parser_error (parser, "expected %<assumes%>");
+      c_parser_error (parser, "expected %<declare target%> or %<assumes%>");
       c_parser_skip_to_pragma_eol (parser);
     }
 }
@@ -22681,19 +22717,20 @@ c_parser_omp_end (c_parser *parser)
 	  return;
 	}
       c_parser_skip_to_pragma_eol (parser);
-      if (!current_omp_declare_target_attribute)
+      if (!vec_safe_length (current_omp_declare_target_attribute))
 	error_at (loc, "%<#pragma omp end declare target%> without "
-		       "corresponding %<#pragma omp declare target%>");
+		       "corresponding %<#pragma omp declare target%> or "
+		       "%<#pragma omp begin declare target%>");
       else
-	current_omp_declare_target_attribute--;
+	current_omp_declare_target_attribute->pop ();
     }
   else if (strcmp (p, "assumes") == 0)
     {
       c_parser_consume_token (parser);
       c_parser_skip_to_pragma_eol (parser);
       if (!current_omp_begin_assumes)
-	error_at (loc, "%<#pragma omp end assumes%> without "
-		       "corresponding %<#pragma omp begin assumes%>");
+	error_at (loc, "%qs without corresponding %qs",
+		  "#pragma omp end assumes", "#pragma omp begin assumes");
       else
 	current_omp_begin_assumes--;
     }
diff --git a/gcc/cp/ChangeLog.omp b/gcc/cp/ChangeLog.omp
index ff9f62d6cd1..f0668ab3063 100644
--- a/gcc/cp/ChangeLog.omp
+++ b/gcc/cp/ChangeLog.omp
@@ -1,3 +1,35 @@
+2022-10-04  Tobias Burnus  <tobias@codesourcery.com>
+
+	Backport from mainline:
+	2022-10-04  Jakub Jelinek  <jakub@redhat.com>
+
+	* cp-tree.h (struct omp_declare_target_attr): Rename to ...
+	(cp_omp_declare_target_attr): ... this.  Add device_type member.
+	(omp_begin_assumes_data): Rename to ...
+	(cp_omp_begin_assumes_data): ... this.
+	(struct saved_scope): Change types of omp_declare_target_attribute
+	and omp_begin_assumes.
+	* parser.cc (cp_parser_omp_clause_device_type): Uncomment
+	check_no_duplicate_clause call.
+	(cp_parser_omp_all_clauses): Fix up pasto, c_name for OMP_CLAUSE_LINK
+	should be "link" rather than "to".
+	(cp_parser_omp_declare_target): Adjust for omp_declare_target_attr
+	to cp_omp_declare_target_attr changes, push -1 as device_type.  Use
+	error_at rather than warning_at for declare target with only
+	device_type clauses.
+	(OMP_BEGIN_DECLARE_TARGET_CLAUSE_MASK): Define.
+	(cp_parser_omp_begin): Add begin declare target support.  Adjust
+	for omp_begin_assumes_data to cp_omp_begin_assumes_data change.
+	(cp_parser_omp_end): Adjust for the
+	omp_declare_target_attr to cp_omp_declare_target_attr and
+	omp_begin_assumes_data to cp_omp_begin_assumes_data type changes,
+	adjust diagnostics wording and simplify format strings for easier
+	translations.
+	* semantics.cc (finish_translation_unit): Likewise.
+	* decl2.cc (cplus_decl_attributes): If device_type was present on
+	begin declare target, add "omp declare target host" and/or
+	"omp declare target nohost" attributes.
+
 2022-09-27  Tobias Burnus  <tobias@codesourcery.com>
 
 	Backport from mainline:
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 774a7e68311..ec913235005 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1812,11 +1812,12 @@ union GTY((desc ("cp_tree_node_structure (&%h)"),
 };
 
 \f
-struct GTY(()) omp_declare_target_attr {
+struct GTY(()) cp_omp_declare_target_attr {
   bool attr_syntax;
+  int device_type;
 };
 
-struct GTY(()) omp_begin_assumes_data {
+struct GTY(()) cp_omp_begin_assumes_data {
   bool attr_syntax;
 };
 
@@ -1866,8 +1867,8 @@ struct GTY(()) saved_scope {
   cp_binding_level *bindings;
 
   hash_map<tree, tree> *GTY((skip)) x_local_specializations;
-  vec<omp_declare_target_attr, va_gc> *omp_declare_target_attribute;
-  vec<omp_begin_assumes_data, va_gc> *omp_begin_assumes;
+  vec<cp_omp_declare_target_attr, va_gc> *omp_declare_target_attribute;
+  vec<cp_omp_begin_assumes_data, va_gc> *omp_begin_assumes;
 
   struct saved_scope *prev;
 };
diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index da32a9776fb..a216f72cfa6 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -1625,17 +1625,40 @@ cplus_decl_attributes (tree *decl, tree attributes, int flags)
 	  && DECL_CLASS_SCOPE_P (*decl))
 	error ("%q+D static data member inside of declare target directive",
 	       *decl);
-      else if (VAR_P (*decl)
-	       && (processing_template_decl
-		   || !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);
-	  attributes = tree_cons (get_identifier ("omp declare target block"),
-				  NULL_TREE, attributes);
+	  if (VAR_P (*decl)
+	      && (processing_template_decl
+		  || !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);
+	      attributes
+		= tree_cons (get_identifier ("omp declare target block"),
+			     NULL_TREE, attributes);
+	    }
+	  if (TREE_CODE (*decl) == FUNCTION_DECL)
+	    {
+	      cp_omp_declare_target_attr &last
+		= scope_chain->omp_declare_target_attribute->last ();
+	      int device_type = MAX (last.device_type, 0);
+	      if ((device_type & OMP_CLAUSE_DEVICE_TYPE_HOST) != 0
+		  && !lookup_attribute ("omp declare target host",
+					attributes))
+		attributes
+		  = tree_cons (get_identifier ("omp declare target host"),
+			       NULL_TREE, attributes);
+	      if ((device_type & OMP_CLAUSE_DEVICE_TYPE_NOHOST) != 0
+		  && !lookup_attribute ("omp declare target nohost",
+					attributes))
+		attributes
+		  = tree_cons (get_identifier ("omp declare target nohost"),
+			       NULL_TREE, attributes);
+	    }
 	}
     }
 
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index dda809e7d4f..06f089a2167 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -40215,8 +40215,8 @@ cp_parser_omp_clause_device_type (cp_parser *parser, tree list,
     goto resync_fail;
 
   c = build_omp_clause (location, OMP_CLAUSE_DEVICE_TYPE);
-  /* check_no_duplicate_clause (list, OMP_CLAUSE_DEVICE_TYPE, "device_type",
-				location);  */
+  check_no_duplicate_clause (list, OMP_CLAUSE_DEVICE_TYPE, "device_type",
+			     location);
   OMP_CLAUSE_DEVICE_TYPE_KIND (c) = kind;
   OMP_CLAUSE_CHAIN (c) = list;
   return c;
@@ -40740,7 +40740,7 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
 	  break;
 	case PRAGMA_OMP_CLAUSE_LINK:
 	  clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_LINK, clauses);
-	  c_name = "to";
+	  c_name = "link";
 	  break;
 	case PRAGMA_OMP_CLAUSE_TO:
 	  if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINK)) != 0)
@@ -46678,8 +46678,8 @@ cp_parser_omp_declare_target (cp_parser *parser, cp_token *pragma_tok)
     }
   else
     {
-      struct omp_declare_target_attr a
-	= { parser->lexer->in_omp_attribute_pragma };
+      cp_omp_declare_target_attr a
+	= { parser->lexer->in_omp_attribute_pragma, -1 };
       vec_safe_push (scope_chain->omp_declare_target_attribute, a);
       cp_parser_require_pragma_eol (parser, pragma_tok);
       return;
@@ -46704,12 +46704,17 @@ cp_parser_omp_declare_target (cp_parser *parser, cp_token *pragma_tok)
 					  device_type);
     }
   if (device_type && only_device_type)
-    warning_at (OMP_CLAUSE_LOCATION (clauses), 0,
-		"directive with only %<device_type%> clauses ignored");
+    error_at (OMP_CLAUSE_LOCATION (clauses),
+	      "directive with only %<device_type%> clause");
 }
 
 /* OpenMP 5.1
-   #pragma omp begin assumes clauses[optseq] new-line  */
+   # pragma omp begin assumes clauses[optseq] new-line
+
+   # pragma omp begin declare target clauses[optseq] new-line  */
+
+#define OMP_BEGIN_DECLARE_TARGET_CLAUSE_MASK			\
+	(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE_TYPE)
 
 static void
 cp_parser_omp_begin (cp_parser *parser, cp_token *pragma_tok)
@@ -46721,16 +46726,47 @@ cp_parser_omp_begin (cp_parser *parser, cp_token *pragma_tok)
       tree id = cp_lexer_peek_token (parser->lexer)->u.value;
       p = IDENTIFIER_POINTER (id);
     }
-  if (strcmp (p, "assumes") == 0)
+  if (strcmp (p, "declare") == 0)
+    {
+      cp_lexer_consume_token (parser->lexer);
+      p = "";
+      if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+	{
+	  tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+	  p = IDENTIFIER_POINTER (id);
+	}
+      if (strcmp (p, "target") == 0)
+	{
+	  cp_lexer_consume_token (parser->lexer);
+	  tree clauses
+	    = cp_parser_omp_all_clauses (parser,
+					 OMP_BEGIN_DECLARE_TARGET_CLAUSE_MASK,
+					 "#pragma omp begin declare target",
+					 pragma_tok);
+	  int device_type = 0;
+	  for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
+	    if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE)
+	      device_type |= OMP_CLAUSE_DEVICE_TYPE_KIND (c);
+	  cp_omp_declare_target_attr a
+	    = { in_omp_attribute_pragma, device_type };
+	  vec_safe_push (scope_chain->omp_declare_target_attribute, a);
+	}
+      else
+	{
+	  cp_parser_error (parser, "expected %<target%>");
+	  cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+	}
+    }
+  else if (strcmp (p, "assumes") == 0)
     {
       cp_lexer_consume_token (parser->lexer);
       cp_parser_omp_assumption_clauses (parser, pragma_tok, false);
-      struct omp_begin_assumes_data a = { in_omp_attribute_pragma };
+      cp_omp_begin_assumes_data a = { in_omp_attribute_pragma };
       vec_safe_push (scope_chain->omp_begin_assumes, a);
     }
   else
     {
-      cp_parser_error (parser, "expected %<assumes%>");
+      cp_parser_error (parser, "expected %<declare target%> or %<assumes%>");
       cp_parser_skip_to_pragma_eol (parser, pragma_tok);
     }
 }
@@ -46772,21 +46808,28 @@ cp_parser_omp_end (cp_parser *parser, cp_token *pragma_tok)
       if (!vec_safe_length (scope_chain->omp_declare_target_attribute))
 	error_at (pragma_tok->location,
 		  "%<#pragma omp end declare target%> without corresponding "
-		  "%<#pragma omp declare target%>");
+		  "%<#pragma omp declare target%> or "
+		  "%<#pragma omp begin declare target%>");
       else
 	{
-	  omp_declare_target_attr
+	  cp_omp_declare_target_attr
 	    a = scope_chain->omp_declare_target_attribute->pop ();
 	  if (a.attr_syntax != in_omp_attribute_pragma)
 	    {
 	      if (a.attr_syntax)
 		error_at (pragma_tok->location,
-			  "%<declare target%> in attribute syntax terminated "
-			  "with %<end declare target%> in pragma syntax");
+			  "%qs in attribute syntax terminated "
+			  "with %qs in pragma syntax",
+			  a.device_type >= 0 ? "begin declare target"
+					     : "declare target",
+			  "end declare target");
 	      else
 		error_at (pragma_tok->location,
-			  "%<declare target%> in pragma syntax terminated "
-			  "with %<end declare target%> in attribute syntax");
+			  "%qs in pragma syntax terminated "
+			  "with %qs in attribute syntax",
+			  a.device_type >= 0 ? "begin declare target"
+					     : "declare target",
+			  "end declare target");
 	    }
 	}
     }
@@ -46796,22 +46839,24 @@ cp_parser_omp_end (cp_parser *parser, cp_token *pragma_tok)
       cp_parser_require_pragma_eol (parser, pragma_tok);
       if (!vec_safe_length (scope_chain->omp_begin_assumes))
 	error_at (pragma_tok->location,
-		  "%<#pragma omp end assumes%> without corresponding "
-		  "%<#pragma omp begin assumes%>");
+		  "%qs without corresponding %qs",
+		  "#pragma omp end assumes", "#pragma omp begin assumes");
       else
 	{
-	  omp_begin_assumes_data
+	  cp_omp_begin_assumes_data
 	    a = scope_chain->omp_begin_assumes->pop ();
 	  if (a.attr_syntax != in_omp_attribute_pragma)
 	    {
 	      if (a.attr_syntax)
 		error_at (pragma_tok->location,
-			  "%<begin assumes%> in attribute syntax terminated "
-			  "with %<end assumes%> in pragma syntax");
+			  "%qs in attribute syntax terminated "
+			  "with %qs in pragma syntax",
+			  "begin assumes", "end assumes");
 	      else
 		error_at (pragma_tok->location,
-			  "%<begin assumes%> in pragma syntax terminated "
-			  "with %<end assumes%> in attribute syntax");
+			  "%qs in pragma syntax terminated "
+			  "with %qs in attribute syntax",
+			  "begin assumes", "end assumes");
 	    }
 	}
     }
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index ac2f5d79e59..81368b4faaa 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -3340,16 +3340,20 @@ finish_translation_unit (void)
 
   if (vec_safe_length (scope_chain->omp_declare_target_attribute))
     {
+      cp_omp_declare_target_attr
+	a = scope_chain->omp_declare_target_attribute->pop ();
       if (!errorcount)
-	error ("%<#pragma omp declare target%> without corresponding "
-	       "%<#pragma omp end declare target%>");
+	error ("%qs without corresponding %qs",
+	       a.device_type >= 0 ? "#pragma omp begin declare target"
+				  : "#pragma omp declare target",
+	       "#pragma omp end declare target");
       vec_safe_truncate (scope_chain->omp_declare_target_attribute, 0);
     }
   if (vec_safe_length (scope_chain->omp_begin_assumes))
     {
       if (!errorcount)
-	error ("%<#pragma omp begin assumes%> without corresponding "
-	       "%<#pragma omp end assumes%>");
+	error ("%qs without corresponding %qs",
+	       "#pragma omp begin assumes", "#pragma omp end assumes");
       vec_safe_truncate (scope_chain->omp_begin_assumes, 0);
     }
 }
diff --git a/gcc/testsuite/ChangeLog.omp b/gcc/testsuite/ChangeLog.omp
index 043d2e6f946..9dc42e62822 100644
--- a/gcc/testsuite/ChangeLog.omp
+++ b/gcc/testsuite/ChangeLog.omp
@@ -1,3 +1,26 @@
+2022-10-04  Tobias Burnus  <tobias@codesourcery.com>
+
+	Backport from mainline:
+	2022-10-04  Jakub Jelinek  <jakub@redhat.com>
+
+	* c-c++-common/gomp/declare-target-4.c: Move tests that are now
+	rejected into declare-target-7.c.
+	* c-c++-common/gomp/declare-target-6.c: Adjust expected diagnostics.
+	* c-c++-common/gomp/declare-target-7.c: New test.
+	* c-c++-common/gomp/begin-declare-target-1.c: New test.
+	* c-c++-common/gomp/begin-declare-target-2.c: New test.
+	* c-c++-common/gomp/begin-declare-target-3.c: New test.
+	* c-c++-common/gomp/begin-declare-target-4.c: New test.
+	* g++.dg/gomp/attrs-9.C: Add begin declare target tests.
+	* g++.dg/gomp/attrs-18.C: New test.
+
+2022-10-04  Tobias Burnus  <tobias@codesourcery.com>
+
+	Backport from mainline:
+	2022-10-04  Jakub Jelinek  <jakub@redhat.com>
+
+	* libgomp.texi (Support begin/end declare target syntax in C/C++):
+	Mark as implemented.
 2022-09-30  Tobias Burnus  <tobias@codesourcery.com>
 
 	Backport from mainline:
diff --git a/gcc/testsuite/c-c++-common/gomp/begin-declare-target-1.c b/gcc/testsuite/c-c++-common/gomp/begin-declare-target-1.c
new file mode 100644
index 00000000000..fd8cabaef0a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/begin-declare-target-1.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+
+extern int a;
+#pragma omp begin declare target device_type (host)
+int b;
+#pragma omp begin declare target device_type (any)
+char d;
+#pragma omp end declare target
+#pragma omp end declare target
+#pragma omp begin declare target
+long c;
+#pragma omp end declare target
+#pragma omp declare target
+int foo (void) { return 0; }
+#pragma omp begin declare target device_type (any)
+int bar (void) { return 0; }
+#pragma omp end declare target
+#pragma omp end declare target
+#pragma omp begin declare target device_type (any)
+int baz (void) { return 0; }
+#pragma omp declare target
+int qux (void) { return 0; }
+#pragma omp end declare target
+#pragma omp end declare target
diff --git a/gcc/testsuite/c-c++-common/gomp/begin-declare-target-2.c b/gcc/testsuite/c-c++-common/gomp/begin-declare-target-2.c
new file mode 100644
index 00000000000..2bc72cf4621
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/begin-declare-target-2.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+
+extern int a;
+#pragma omp begin declare target
+#pragma omp declare target to (a)
+#pragma omp end declare target
+int b;
+#pragma omp begin declare target to (b)		/* { dg-error "'to' is not valid for '#pragma omp begin declare target'" } */
+#pragma omp end declare target
+int c;
+#pragma omp begin declare target link (c)	/* { dg-error "'link' is not valid for '#pragma omp begin declare target'" } */
+#pragma omp end declare target
+int m;
+#pragma omp begin declare target device_type (host) device_type (any)	/* { dg-error "too many 'device_type' clauses" } */
+#pragma omp end declare target
+#pragma omp begin declare target
+#pragma omp end declare target to (p)		/* { dg-error "expected end of line before .to." } */
diff --git a/gcc/testsuite/c-c++-common/gomp/begin-declare-target-3.c b/gcc/testsuite/c-c++-common/gomp/begin-declare-target-3.c
new file mode 100644
index 00000000000..ac4d4d9e98e
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/begin-declare-target-3.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+
+#pragma omp begin 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];
+#pragma omp begin declare target device_type (host)
+int e[] = { 1, 2, 3 };
+extern int f[];			/* { dg-error "'f' in declare target directive does not have mappable type" } */
+extern int g[];			/* { dg-error "'g' in declare target directive does not have mappable type" } */
+extern int h[];			/* { dg-error "'h' in declare target directive does not have mappable type" } */
+int h[3];
+#pragma omp end declare target
+int g[3];
diff --git a/gcc/testsuite/c-c++-common/gomp/begin-declare-target-4.c b/gcc/testsuite/c-c++-common/gomp/begin-declare-target-4.c
new file mode 100644
index 00000000000..d275f730748
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/begin-declare-target-4.c
@@ -0,0 +1,2 @@
+#pragma omp begin declare target
+void foo (void);	/* { dg-error "'#pragma omp begin declare target' without corresponding '#pragma omp end declare target'" } */
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-target-4.c b/gcc/testsuite/c-c++-common/gomp/declare-target-4.c
index 887a815e84a..a6bd1286ef1 100644
--- a/gcc/testsuite/c-c++-common/gomp/declare-target-4.c
+++ b/gcc/testsuite/c-c++-common/gomp/declare-target-4.c
@@ -1,8 +1,6 @@
 /* { dg-do compile } */
 /* { dg-options "-fopenmp" } */
 
-#pragma omp declare target device_type (any)		/* { dg-warning "directive with only 'device_type' clauses ignored" } */
-
 void f1 (void) {}
 void f2 (void);
 #pragma omp declare target to (f1) device_type (any) to (f2)
@@ -38,7 +36,3 @@ void f13 (void) {}
 void f14 (void) {}
 #pragma omp declare target device_type (nohost) to (f14)
 #pragma omp declare target device_type (any) to (f14)
-void f15 (void) {}
-#pragma omp declare target device_type (host) to (f15) device_type (nohost)
-void f16 (void) {}
-#pragma omp declare target device_type (any) to (f15) device_type (any)
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-target-6.c b/gcc/testsuite/c-c++-common/gomp/declare-target-6.c
index 586eb50f801..ba323e2a6f6 100644
--- a/gcc/testsuite/c-c++-common/gomp/declare-target-6.c
+++ b/gcc/testsuite/c-c++-common/gomp/declare-target-6.c
@@ -1,2 +1,2 @@
-#pragma omp end declare target	/* { dg-error "'#pragma omp end declare target' without corresponding '#pragma omp declare target'" } */
+#pragma omp end declare target	/* { dg-error "'#pragma omp end declare target' without corresponding '#pragma omp declare target' or '#pragma omp begin declare target'" } */
 void foo (void);
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-target-7.c b/gcc/testsuite/c-c++-common/gomp/declare-target-7.c
new file mode 100644
index 00000000000..747000a74b9
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/declare-target-7.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+
+#pragma omp declare target device_type (any)		/* { dg-error "directive with only 'device_type' clause" } */
+
+void f1 (void) {}
+#pragma omp declare target device_type (host) to (f1) device_type (nohost)	/* { dg-error "too many 'device_type' clauses" } */
+#pragma omp declare target device_type (any) to (f1) device_type (any)		/* { dg-error "too many 'device_type' clauses" } */
diff --git a/gcc/testsuite/g++.dg/gomp/attrs-18.C b/gcc/testsuite/g++.dg/gomp/attrs-18.C
new file mode 100644
index 00000000000..6858f3f359f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/attrs-18.C
@@ -0,0 +1,41 @@
+// { dg-do compile { target c++11 } }
+
+#pragma omp begin declare target
+#pragma omp begin declare target device_type (any)
+[[omp::directive (begin declare target, device_type (host))]];
+int a;
+[[omp::directive (end declare target)]];
+#pragma omp end declare target
+#pragma omp end declare target
+[[omp::directive (begin declare target device_type (nohost))]];
+int b;
+#pragma omp end declare target		// { dg-error "'begin declare target' in attribute syntax terminated with 'end declare target' in pragma syntax" }
+#pragma omp begin declare target
+int c;
+[[omp::directive (end declare target)]];// { dg-error "'begin declare target' in pragma syntax terminated with 'end declare target' in attribute syntax" }
+#pragma omp begin declare target device_type (host)
+[[omp::directive (begin declare target)]];
+int d;
+#pragma omp end declare target		// { dg-error "'begin declare target' in attribute syntax terminated with 'end declare target' in pragma syntax" }
+#pragma omp begin declare target
+int e;
+[[omp::directive (end declare target)]];// { dg-error "'begin declare target' in pragma syntax terminated with 'end declare target' in attribute syntax" }
+#pragma omp end declare target
+[[omp::directive (begin declare target device_type (any))]];
+[[omp::directive (begin declare target)]];
+int f;
+#pragma omp end declare target		// { dg-error "'begin declare target' in attribute syntax terminated with 'end declare target' in pragma syntax" }
+#pragma omp begin declare target
+int g;
+[[omp::directive (end declare target)]];// { dg-error "'begin declare target' in pragma syntax terminated with 'end declare target' in attribute syntax" }
+[[omp::directive (end declare target)]];
+[[omp::directive (begin declare target)]];
+#pragma omp begin declare target
+int h;
+#pragma omp end declare target
+#pragma omp end declare target		// { dg-error "'begin declare target' in attribute syntax terminated with 'end declare target' in pragma syntax" }
+#pragma omp begin declare target
+[[omp::directive (begin declare target)]];
+int i;
+[[omp::directive (end declare target)]];
+[[omp::directive (end declare target)]];// { dg-error "'begin declare target' in pragma syntax terminated with 'end declare target' in attribute syntax" }
diff --git a/gcc/testsuite/g++.dg/gomp/attrs-9.C b/gcc/testsuite/g++.dg/gomp/attrs-9.C
index fa02299bcaf..cf7cef46b70 100644
--- a/gcc/testsuite/g++.dg/gomp/attrs-9.C
+++ b/gcc/testsuite/g++.dg/gomp/attrs-9.C
@@ -14,6 +14,21 @@ int b, c, e;
 int d;
 [[omp::directive (end declare target)]];
 [[omp::directive (end declare target)]];
+[[omp::directive (begin declare target, device_type (any))]];
+[[omp::directive (begin declare target)]];
+int f;
+[[omp::directive (end declare target)]];
+[[omp::directive (end declare target)]];
+[[omp::directive (begin declare target device_type (host))]];
+[[omp::directive (declare target)]];
+int g;
+[[omp::directive (end declare target)]];
+[[omp::directive (end declare target)]];
+[[omp::directive (declare target)]];
+[[omp::directive (begin declare target, device_type (nohost))]];
+int h;
+[[omp::directive (end declare target)]];
+[[omp::directive (end declare target)]];
 [[omp::directive (nothing)]];
 [[omp::directive (begin assumes no_openmp no_openmp_routines no_parallelism
 				absent (atomic, barrier, cancel, cancellation point)
diff --git a/libgomp/ChangeLog.omp b/libgomp/ChangeLog.omp
index 86969c5a5c2..4c90a4ad97b 100644
--- a/libgomp/ChangeLog.omp
+++ b/libgomp/ChangeLog.omp
@@ -1,3 +1,11 @@
+2022-10-04  Tobias Burnus  <tobias@codesourcery.com>
+
+	Backport from mainline:
+	2022-10-04  Jakub Jelinek  <jakub@redhat.com>
+
+	* libgomp.texi (Support begin/end declare target syntax in C/C++):
+	Mark as implemented.
+
 2022-09-30  Tobias Burnus  <tobias@codesourcery.com>
 
 	Backport from mainline:
diff --git a/libgomp/libgomp.texi b/libgomp/libgomp.texi
index cff4074cf84..7dbd54374da 100644
--- a/libgomp/libgomp.texi
+++ b/libgomp/libgomp.texi
@@ -345,7 +345,7 @@ The OpenMP 4.5 specification is fully supported.
 @item Support of structured block sequences in C/C++ @tab Y @tab
 @item @code{unconstrained} and @code{reproducible} modifiers on @code{order}
       clause @tab Y @tab
-@item Support @code{begin/end declare target} syntax in C/C++ @tab N @tab
+@item Support @code{begin/end declare target} syntax in C/C++ @tab Y @tab
 @item Pointer predetermined firstprivate getting initialized
 to address of matching mapped list item per 5.1, Sect. 2.21.7.2 @tab N @tab
 @item For Fortran, diagnose placing declarative before/between @code{USE},

                 reply	other threads:[~2022-10-04  9:40 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221004094039.E050E3858413@sourceware.org \
    --to=burnus@gcc.gnu.org \
    --cc=gcc-cvs@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).