diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c
index de49d2668314edcfbcd9cb35e5d385de7724149f..d4e98bfd76ba1d3cd2549aae3c57144298d2cb82 100644
--- a/gcc/c-family/c-omp.c
+++ b/gcc/c-family/c-omp.c
@@ -3007,8 +3007,8 @@ static const struct c_omp_directive omp_directives[] = {
     C_OMP_DIR_CONSTRUCT, true },
   /* { "metadirective", nullptr, nullptr, PRAGMA_OMP_METADIRECTIVE,
     C_OMP_DIR_???, ??? },  */
-  /* { "nothing", nullptr, nullptr, PRAGMA_OMP_NOTHING,
-    C_OMP_DIR_UTILITY, false },  */
+  { "nothing", nullptr, nullptr, PRAGMA_OMP_NOTHING,
+    C_OMP_DIR_UTILITY, false },
   /* ordered with depend clause is C_OMP_DIR_STANDALONE.  */
   { "ordered", nullptr, nullptr, PRAGMA_OMP_ORDERED,
     C_OMP_DIR_CONSTRUCT, true },
diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c
index 5f0096ffc70cf1f18e1f93153ebd3c232fd85e48..238309d4a775b858142909dbdc252c64698eabf1 100644
--- a/gcc/c-family/c-pragma.c
+++ b/gcc/c-family/c-pragma.c
@@ -1328,6 +1328,7 @@ static const struct omp_pragma_def omp_pragmas[] = {
   { "depobj", PRAGMA_OMP_DEPOBJ },
   { "end", PRAGMA_OMP_END_DECLARE_TARGET },
   { "flush", PRAGMA_OMP_FLUSH },
+  { "nothing", PRAGMA_OMP_NOTHING },
   { "requires", PRAGMA_OMP_REQUIRES },
   { "scope", PRAGMA_OMP_SCOPE },
   { "section", PRAGMA_OMP_SECTION },
diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h
index 2b9e5eac675a5af98f76f3dd996c5775a2e5ef94..dc9e8a6616df91d25645ea32d621a75c4e2bcdb4 100644
--- a/gcc/c-family/c-pragma.h
+++ b/gcc/c-family/c-pragma.h
@@ -57,6 +57,7 @@ enum pragma_kind {
   PRAGMA_OMP_FLUSH,
   PRAGMA_OMP_FOR,
   PRAGMA_OMP_LOOP,
+  PRAGMA_OMP_NOTHING,
   PRAGMA_OMP_MASKED,
   PRAGMA_OMP_MASTER,
   PRAGMA_OMP_ORDERED,
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 565efc4d2e96d0430c7735899ace3399941bd5a7..d5f51b11423113b517f7d20f79fae5c830979f9b 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -1578,6 +1578,7 @@ static tree c_parser_omp_for_loop (location_t, c_parser *, enum tree_code,
 static void c_parser_omp_taskwait (c_parser *);
 static void c_parser_omp_taskyield (c_parser *);
 static void c_parser_omp_cancel (c_parser *);
+static void c_parser_omp_nothing (c_parser *);
 
 enum pragma_context { pragma_external, pragma_struct, pragma_param,
 		      pragma_stmt, pragma_compound };
@@ -12480,6 +12481,10 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
       c_parser_omp_requires (parser);
       return false;
 
+    case PRAGMA_OMP_NOTHING:
+      c_parser_omp_nothing (parser);
+      return false;
+
     case PRAGMA_OMP_ORDERED:
       return c_parser_omp_ordered (parser, context, if_p);
 
@@ -21908,6 +21913,16 @@ c_parser_omp_taskloop (location_t loc, c_parser *parser,
   return ret;
 }
 
+/* OpenMP 5.1
+   #pragma omp nothing new-line  */
+
+static void
+c_parser_omp_nothing (c_parser *parser)
+{
+  c_parser_consume_pragma (parser);
+  c_parser_skip_to_pragma_eol (parser);
+}
+
 /* Main entry point to parsing most OpenMP pragmas.  */
 
 static void
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 8f2d0fce8071f8ca253ae88817fec6908edc6711..04116fbcef4a7e1c15c0bae5f315dc1dc2a2ebf3 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -45564,6 +45564,16 @@ cp_parser_omp_requires (cp_parser *parser, cp_token *pragma_tok)
 }
 
 
+/* OpenMP 5.1:
+   #pragma omp nothing new-line  */
+
+static void
+cp_parser_omp_nothing (cp_parser *parser, cp_token *pragma_tok)
+{
+  cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+}
+
+
 /* OpenMP 4.5:
    #pragma omp taskloop taskloop-clause[optseq] new-line
      for-loop
@@ -46673,6 +46683,10 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p)
 	}
       return cp_parser_omp_requires (parser, pragma_tok);
 
+    case PRAGMA_OMP_NOTHING:
+      cp_parser_omp_nothing (parser, pragma_tok);
+      return false;
+
     case PRAGMA_OMP_ORDERED:
       if (context != pragma_stmt && context != pragma_compound)
 	goto bad_stmt;
diff --git a/gcc/testsuite/c-c++-common/gomp/nothing-1.c b/gcc/testsuite/c-c++-common/gomp/nothing-1.c
new file mode 100644
index 0000000000000000000000000000000000000000..d50c92a67c313613e1f310411dfe4ffa94691268
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/nothing-1.c
@@ -0,0 +1,37 @@
+#pragma omp nothing
+
+struct S
+{
+  #pragma omp nothing
+  int s;
+};
+
+int
+foo (int i)
+{
+  #pragma omp nothing
+  if (0)
+    #pragma omp nothing
+    i++;
+  if (1)
+    ;
+  else
+    #pragma omp nothing
+    i++;
+  switch (0)
+    #pragma omp nothing
+    {
+    default:
+      break;
+    }
+  while (0)
+    #pragma omp nothing
+    i++;
+  for (; 0;)
+    #pragma omp nothing
+    i++;
+  lab:
+  #pragma omp nothing
+  i++;
+  return i;
+}
diff --git a/gcc/testsuite/g++.dg/gomp/attrs-1.C b/gcc/testsuite/g++.dg/gomp/attrs-1.C
index 686acf5042fe82d18db4ed077f148cfba2af6098..435d54fb762e1370eab273e2334d6d827cbe91bd 100644
--- a/gcc/testsuite/g++.dg/gomp/attrs-1.C
+++ b/gcc/testsuite/g++.dg/gomp/attrs-1.C
@@ -111,6 +111,7 @@ void
 bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s,
      int nte, int tl, int nth, int g, int nta, int fi, int pp, int *q, int *dd, int ntm)
 {
+  [[omp::directive (nothing)]];
   [[omp::directive (for simd
     private (p) firstprivate (f) lastprivate (l) linear (ll:1) reduction(+:r) schedule(static, 4) collapse(1) nowait
     safelen(8) simdlen(4) aligned(q: 32) nontemporal(ntm) if(i1) order(concurrent) allocate (f))]]
diff --git a/gcc/testsuite/g++.dg/gomp/attrs-2.C b/gcc/testsuite/g++.dg/gomp/attrs-2.C
index 2190457c877966e1af2bdaa09c9a6fb7e0bb25ae..bea657f02b9a80433867c81b2fb2ad42da710397 100644
--- a/gcc/testsuite/g++.dg/gomp/attrs-2.C
+++ b/gcc/testsuite/g++.dg/gomp/attrs-2.C
@@ -111,6 +111,7 @@ void
 bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s,
      int nte, int tl, int nth, int g, int nta, int fi, int pp, int *q, int *dd, int ntm)
 {
+  [[omp::directive (nothing)]];
   [[omp::directive (for simd,
     private (p),firstprivate (f),lastprivate (l),linear (ll:1),reduction(+:r),schedule(static, 4),collapse(1),nowait,
     safelen(8),simdlen(4),aligned(q: 32),nontemporal(ntm),if(i1),order(concurrent),allocate (f))]]
diff --git a/gcc/testsuite/g++.dg/gomp/attrs-9.C b/gcc/testsuite/g++.dg/gomp/attrs-9.C
index 0af556c728423429deb6cb5877af90dd5b09362f..08cd2b1dfd94e4efede5b674c86258e0fce38487 100644
--- a/gcc/testsuite/g++.dg/gomp/attrs-9.C
+++ b/gcc/testsuite/g++.dg/gomp/attrs-9.C
@@ -13,3 +13,4 @@ int b, c;
 int d;
 [[omp::directive (end declare target)]];
 [[omp::directive (end declare target)]];
+[[omp::directive (nothing)]];
diff --git a/libgomp/testsuite/libgomp.c-c++-common/nothing-1.c b/libgomp/testsuite/libgomp.c-c++-common/nothing-1.c
new file mode 100644
index 0000000000000000000000000000000000000000..69716b18d98cb272425d8cb4e63a97568b0f57b9
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/nothing-1.c
@@ -0,0 +1,47 @@
+#include <stdlib.h>
+
+#pragma omp nothing
+
+struct S
+{
+  #pragma omp nothing
+  int s;
+};
+
+int
+foo (int i)
+{
+  #pragma omp nothing
+  if (0)
+    #pragma omp nothing
+    i++;
+  if (1)
+    ;
+  else
+    #pragma omp nothing
+    i++;
+  switch (0)
+    #pragma omp nothing
+    {
+    default:
+      break;
+    }
+  while (0)
+    #pragma omp nothing
+    i++;
+  for (; 0;)
+    #pragma omp nothing
+    i++;
+  lab:
+  #pragma omp nothing
+  i++;
+  return i;
+}
+
+int
+main ()
+{
+  if (foo (5) != 6 || foo (-2) != -1)
+    abort ();
+  return 0;
+}