diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 193e268f04e..a7571cc7542 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -6048,11 +6048,13 @@ mark_forward_parm_decls (void)
    literal.  NON_CONST is true if the initializers contain something
    that cannot occur in a constant expression.  If ALIGNAS_ALIGN is nonzero,
    it is the (valid) alignment for this compound literal, as specified
-   with _Alignas.  */
+   with _Alignas.  SCSPECS are the storage class specifiers (C2x) from the
+   compound literal.  */
 
 tree
 build_compound_literal (location_t loc, tree type, tree init, bool non_const,
-			unsigned int alignas_align)
+			unsigned int alignas_align,
+			struct c_declspecs *scspecs)
 {
   /* We do not use start_decl here because we have a type, not a declarator;
      and do not use finish_decl because the decl should be stored inside
@@ -6060,15 +6062,33 @@ build_compound_literal (location_t loc, tree type, tree init, bool non_const,
   tree decl;
   tree complit;
   tree stmt;
+  bool threadp = scspecs ? scspecs->thread_p : false;
+  enum c_storage_class storage_class = (scspecs
+					? scspecs->storage_class
+					: csc_none);
 
   if (type == error_mark_node
       || init == error_mark_node)
     return error_mark_node;
 
+  if (current_scope == file_scope && storage_class == csc_register)
+    {
+      error_at (loc, "file-scope compound literal specifies %<register%>");
+      storage_class = csc_none;
+    }
+
+  if (current_scope != file_scope && threadp && storage_class == csc_none)
+    {
+      error_at (loc, "compound literal implicitly auto and declared %qs",
+		scspecs->thread_gnu_p ? "__thread" : "_Thread_local");
+      threadp = false;
+    }
+
   decl = build_decl (loc, VAR_DECL, NULL_TREE, type);
   DECL_EXTERNAL (decl) = 0;
   TREE_PUBLIC (decl) = 0;
-  TREE_STATIC (decl) = (current_scope == file_scope);
+  TREE_STATIC (decl) = (current_scope == file_scope
+			|| storage_class == csc_static);
   DECL_CONTEXT (decl) = current_function_decl;
   TREE_USED (decl) = 1;
   DECL_READ_P (decl) = 1;
@@ -6076,6 +6096,13 @@ build_compound_literal (location_t loc, tree type, tree init, bool non_const,
   DECL_IGNORED_P (decl) = 1;
   C_DECL_COMPOUND_LITERAL_P (decl) = 1;
   TREE_TYPE (decl) = type;
+  if (threadp)
+    set_decl_tls_model (decl, decl_default_tls_model (decl));
+  if (storage_class == csc_register)
+    {
+      C_DECL_REGISTER (decl) = 1;
+      DECL_REGISTER (decl) = 1;
+    }
   c_apply_type_quals_to_decl (TYPE_QUALS (strip_array_types (type)), decl);
   if (alignas_align)
     {
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 89e05870f47..602e0235f2d 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -666,6 +666,30 @@ c_parser_next_tokens_start_typename (c_parser *parser, enum c_lookahead_kind la)
   return false;
 }
 
+/* Return true if TOKEN, after an open parenthesis, can start a
+   compound literal (either a storage class specifier allowed in that
+   context, or a type name), false otherwise.  */
+static bool
+c_token_starts_compound_literal (c_token *token)
+{
+  switch (token->type)
+    {
+    case CPP_KEYWORD:
+      switch (token->keyword)
+	{
+	case RID_REGISTER:
+	case RID_STATIC:
+	case RID_THREAD:
+	  return true;
+	default:
+	  break;
+	}
+      /* Fall through.  */
+    default:
+      return c_token_starts_typename (token);
+    }
+}
+
 /* Return true if TOKEN is a type qualifier, false otherwise.  */
 static bool
 c_token_is_qualifier (c_token *token)
@@ -1563,6 +1587,7 @@ static struct c_expr c_parser_sizeof_expression (c_parser *);
 static struct c_expr c_parser_alignof_expression (c_parser *);
 static struct c_expr c_parser_postfix_expression (c_parser *);
 static struct c_expr c_parser_postfix_expression_after_paren_type (c_parser *,
+								   struct c_declspecs *,
 								   struct c_type_name *,
 								   location_t);
 static struct c_expr c_parser_postfix_expression_after_primary (c_parser *,
@@ -8237,6 +8262,34 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after,
 #undef POP
 }
 
+/* Parse any storage class specifiers after an open parenthesis in a
+   context where a compound literal is permitted.  */
+
+static struct c_declspecs *
+c_parser_compound_literal_scspecs (c_parser *parser)
+{
+  bool seen_scspec = false;
+  struct c_declspecs *specs = build_null_declspecs ();
+  while (c_parser_next_token_is (parser, CPP_KEYWORD))
+    {
+      switch (c_parser_peek_token (parser)->keyword)
+	{
+	case RID_REGISTER:
+	case RID_STATIC:
+	case RID_THREAD:
+	  seen_scspec = true;
+	  declspecs_add_scspec (c_parser_peek_token (parser)->location,
+				specs, c_parser_peek_token (parser)->value);
+	  c_parser_consume_token (parser);
+	  break;
+	default:
+	  goto out;
+	}
+    }
+ out:
+  return seen_scspec ? specs : NULL;
+}
+
 /* Parse a cast expression (C90 6.3.4, C99 6.5.4, C11 6.5.4).  If AFTER
    is not NULL then it is an Objective-C message expression which is the
    primary-expression starting the expression as an initializer.
@@ -8260,13 +8313,15 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after)
      an unary expression.  Full detection of unknown typenames here
      would require a 3-token lookahead.  */
   if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
-      && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
+      && c_token_starts_compound_literal (c_parser_peek_2nd_token (parser)))
     {
+      struct c_declspecs *scspecs;
       struct c_type_name *type_name;
       struct c_expr ret;
       struct c_expr expr;
       matching_parens parens;
       parens.consume_open (parser);
+      scspecs = c_parser_compound_literal_scspecs (parser);
       type_name = c_parser_type_name (parser, true);
       parens.skip_until_found_close (parser);
       if (type_name == NULL)
@@ -8281,8 +8336,11 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after)
       used_types_insert (type_name->specs->type);
 
       if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
-	return c_parser_postfix_expression_after_paren_type (parser, type_name,
+	return c_parser_postfix_expression_after_paren_type (parser, scspecs,
+							     type_name,
 							     cast_loc);
+      if (scspecs)
+	error_at (cast_loc, "storage class specifier in cast");
       if (type_name->specs->alignas_p)
 	error_at (type_name->specs->locations[cdw_alignas],
 		  "alignment specified for type name in cast");
@@ -8485,14 +8543,16 @@ c_parser_sizeof_expression (c_parser *parser)
   c_inhibit_evaluation_warnings++;
   in_sizeof++;
   if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
-      && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
+      && c_token_starts_compound_literal (c_parser_peek_2nd_token (parser)))
     {
       /* Either sizeof ( type-name ) or sizeof unary-expression
 	 starting with a compound literal.  */
+      struct c_declspecs *scspecs;
       struct c_type_name *type_name;
       matching_parens parens;
       parens.consume_open (parser);
       expr_loc = c_parser_peek_token (parser)->location;
+      scspecs = c_parser_compound_literal_scspecs (parser);
       type_name = c_parser_type_name (parser, true);
       parens.skip_until_found_close (parser);
       finish = parser->tokens_buf[0].location;
@@ -8508,13 +8568,15 @@ c_parser_sizeof_expression (c_parser *parser)
 	}
       if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
 	{
-	  expr = c_parser_postfix_expression_after_paren_type (parser,
+	  expr = c_parser_postfix_expression_after_paren_type (parser, scspecs,
 							       type_name,
 							       expr_loc);
 	  finish = expr.get_finish ();
 	  goto sizeof_expr;
 	}
       /* sizeof ( type-name ).  */
+      if (scspecs)
+	error_at (expr_loc, "storage class specifier in %<sizeof%>");
       if (type_name->specs->alignas_p)
 	error_at (type_name->specs->locations[cdw_alignas],
 		  "alignment specified for type name in %<sizeof%>");
@@ -8572,16 +8634,18 @@ c_parser_alignof_expression (c_parser *parser)
   c_inhibit_evaluation_warnings++;
   in_alignof++;
   if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
-      && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
+      && c_token_starts_compound_literal (c_parser_peek_2nd_token (parser)))
     {
       /* Either __alignof__ ( type-name ) or __alignof__
 	 unary-expression starting with a compound literal.  */
       location_t loc;
+      struct c_declspecs *scspecs;
       struct c_type_name *type_name;
       struct c_expr ret;
       matching_parens parens;
       parens.consume_open (parser);
       loc = c_parser_peek_token (parser)->location;
+      scspecs = c_parser_compound_literal_scspecs (parser);
       type_name = c_parser_type_name (parser, true);
       end_loc = c_parser_peek_token (parser)->location;
       parens.skip_until_found_close (parser);
@@ -8597,12 +8661,14 @@ c_parser_alignof_expression (c_parser *parser)
 	}
       if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
 	{
-	  expr = c_parser_postfix_expression_after_paren_type (parser,
+	  expr = c_parser_postfix_expression_after_paren_type (parser, scspecs,
 							       type_name,
 							       loc);
 	  goto alignof_expr;
 	}
       /* alignof ( type-name ).  */
+      if (scspecs)
+	error_at (loc, "storage class specifier in %qE", alignof_spelling);
       if (type_name->specs->alignas_p)
 	error_at (type_name->specs->locations[cdw_alignas],
 		  "alignment specified for type name in %qE",
@@ -9140,8 +9206,8 @@ c_parser_predefined_identifier (c_parser *parser)
      postfix-expression -> identifier
      postfix-expression ++
      postfix-expression --
-     ( type-name ) { initializer-list }
-     ( type-name ) { initializer-list , }
+     ( storage-class-specifiers[opt] type-name ) { initializer-list[opt] }
+     ( storage-class-specifiers[opt] type-name ) { initializer-list , }
 
    argument-expression-list:
      argument-expression
@@ -10483,6 +10549,7 @@ c_parser_postfix_expression (c_parser *parser)
 
 static struct c_expr
 c_parser_postfix_expression_after_paren_type (c_parser *parser,
+					      struct c_declspecs *scspecs,
 					      struct c_type_name *type_name,
 					      location_t type_loc)
 {
@@ -10515,7 +10582,11 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser,
       type = error_mark_node;
     }
 
-  pedwarn_c90 (start_loc, OPT_Wpedantic, "ISO C90 forbids compound literals");
+  if (!pedwarn_c90 (start_loc, OPT_Wpedantic,
+		    "ISO C90 forbids compound literals") && scspecs)
+    pedwarn_c11 (start_loc, OPT_Wpedantic,
+		 "ISO C forbids storage class specifiers in compound literals "
+		 "before C2X");
   non_const = ((init.value && TREE_CODE (init.value) == CONSTRUCTOR)
 	       ? CONSTRUCTOR_NON_CONST (init.value)
 	       : init.original_code == C_MAYBE_CONST_EXPR);
@@ -10534,7 +10605,7 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser,
 	}
     }
   expr.value = build_compound_literal (start_loc, type, init.value, non_const,
-				       alignas_align);
+				       alignas_align, scspecs);
   set_c_expr_source_range (&expr, init.src_range);
   expr.m_decimal = 0;
   expr.original_code = ERROR_MARK;
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index 46a3e8e9709..e7cdd2f11dc 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -734,7 +734,7 @@ extern void set_init_label (location_t, tree, location_t, struct obstack *);
 extern void process_init_element (location_t, struct c_expr, bool,
 				  struct obstack *);
 extern tree build_compound_literal (location_t, tree, tree, bool,
-				    unsigned int);
+				    unsigned int, struct c_declspecs *);
 extern void check_compound_literal_type (location_t, struct c_type_name *);
 extern tree c_start_switch (location_t, location_t, tree, bool);
 extern void c_finish_switch (tree, tree);
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index f9190680a3c..017658070f4 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -5114,6 +5114,11 @@ c_mark_addressable (tree exp, bool array_ref_p)
 	break;
 
       case COMPOUND_LITERAL_EXPR:
+	if (C_DECL_REGISTER (COMPOUND_LITERAL_EXPR_DECL (x)))
+	  {
+	    error ("address of register compound literal requested");
+	    return false;
+	  }
 	TREE_ADDRESSABLE (x) = 1;
 	TREE_ADDRESSABLE (COMPOUND_LITERAL_EXPR_DECL (x)) = 1;
 	return true;
diff --git a/gcc/testsuite/gcc.dg/c11-complit-1.c b/gcc/testsuite/gcc.dg/c11-complit-1.c
new file mode 100644
index 00000000000..e191cebbb6a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-complit-1.c
@@ -0,0 +1,7 @@
+/* Test C2x storage class specifiers in compound literals not permitted for
+   C11.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+int *ps = &(static int) { 1 }; /* { dg-error "forbids storage class specifiers in compound literals" } */
+int ss = sizeof (static int) { 1 }; /* { dg-error "forbids storage class specifiers in compound literals" } */
diff --git a/gcc/testsuite/gcc.dg/c11-complit-2.c b/gcc/testsuite/gcc.dg/c11-complit-2.c
new file mode 100644
index 00000000000..d4d1f16f62e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-complit-2.c
@@ -0,0 +1,7 @@
+/* Test C2x storage class specifiers in compound literals not permitted for
+   C11.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic" } */
+
+int *ps = &(static int) { 1 }; /* { dg-warning "forbids storage class specifiers in compound literals" } */
+int ss = sizeof (static int) { 1 }; /* { dg-warning "forbids storage class specifiers in compound literals" } */
diff --git a/gcc/testsuite/gcc.dg/c11-complit-3.c b/gcc/testsuite/gcc.dg/c11-complit-3.c
new file mode 100644
index 00000000000..a73a8ef8ae1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-complit-3.c
@@ -0,0 +1,7 @@
+/* Test C2x storage class specifiers in compound literals not permitted for
+   C11, but -Wno-c11-c2x-compat disables the -pedantic diagnostic for that.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors -Wno-c11-c2x-compat" } */
+
+int *ps = &(static int) { 1 };
+int ss = sizeof (static int) { 1 };
diff --git a/gcc/testsuite/gcc.dg/c2x-complit-2.c b/gcc/testsuite/gcc.dg/c2x-complit-2.c
new file mode 100644
index 00000000000..dcca5e8d348
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-complit-2.c
@@ -0,0 +1,48 @@
+/* Test C2x storage class specifiers in compound literals.  */
+/* { dg-do run } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+#include <stddef.h>
+
+extern void abort (void);
+extern void exit (int);
+
+/* static is OK (although redundant) at file scope.  */
+int *ps = &(static int) { 1 };
+size_t ss = sizeof (static int) { 1 };
+int *psa = (static int [3]) { 1, 2, 3 };
+
+int
+main ()
+{
+  if (ps[0] != 1)
+    abort ();
+  if (ss != sizeof (int))
+    abort ();
+  if (psa[0] != 1 || psa[1] != 2 || psa[2] != 3)
+    abort ();
+  if ((register int) { 3 } != 3)
+    abort ();
+  /* A static compound literal, like a static variable, is initialized once,
+     but an automatic compound literal is initialized every time it is reached
+     in the order of execution.  */
+  int i = 0;
+ lab:
+  int *p = &(static int) { 0 };
+  if (*p != i)
+    abort ();
+  i++;
+  *p = i;
+  if (i < 5)
+    goto lab;
+  i = 0;
+ lab2:
+  int *p2 = &(int) { 0 };
+  if (*p2 != 0)
+    abort ();
+  i++;
+  *p2 = i;
+  if (i < 5)
+    goto lab2;
+  exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/c2x-complit-3.c b/gcc/testsuite/gcc.dg/c2x-complit-3.c
new file mode 100644
index 00000000000..c672525ba6f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-complit-3.c
@@ -0,0 +1,24 @@
+/* Test C2x storage class specifiers in compound literals.  Thread-local
+   cases, compilation tests.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+/* { dg-require-effective-target tls } */
+
+#include <stddef.h>
+
+/* thread_local is OK at file scope, although of limited use since the
+   thread-local object and its address are not constant expressions.  */
+size_t st = sizeof (thread_local int) { 1 };
+size_t sst = sizeof (static thread_local int) { 1 };
+
+int *
+f ()
+{
+  return &(static thread_local int) { 2 };
+}
+
+int *
+g ()
+{
+  return &(thread_local static int) { 3 };
+}
diff --git a/gcc/testsuite/gcc.dg/c2x-complit-4.c b/gcc/testsuite/gcc.dg/c2x-complit-4.c
new file mode 100644
index 00000000000..31d741325d9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-complit-4.c
@@ -0,0 +1,60 @@
+/* Test C2x storage class specifiers in compound literals.  Thread-local
+   cases, execution tests.  */
+/* { dg-do run } */
+/* { dg-options "-pthread -std=gnu2x -pedantic-errors" } */
+/* { dg-require-effective-target pthread_h } */
+/* { dg-require-effective-target pthread } */
+/* { dg-require-effective-target tls_runtime } */
+/* { dg-add-options tls } */
+
+#include <pthread.h>
+
+extern void abort (void);
+extern void exit (int);
+
+int *
+thread_addr ()
+{
+  return (static thread_local int []) { 1, 2 };
+}
+
+int *volatile p, *volatile q, r;
+
+void *
+thread_fn (void *)
+{
+  q = thread_addr ();
+  if (q[0] != 1 || q[1] != 2)
+    return NULL;
+  q[0] = 5;
+  q[1] = 6;
+  return &r;
+}
+
+int
+main ()
+{
+  int i;
+  pthread_t tid;
+  void *ret;
+  p = thread_addr ();
+  if (p[0] != 1 || p[1] != 2)
+    abort ();
+  p[0] = 3;
+  p[1] = 4;
+  if (p != thread_addr ())
+    abort ();
+  i = pthread_create (&tid, NULL, thread_fn, NULL);
+  if (p != thread_addr ())
+    abort ();
+  i = pthread_join (tid, &ret);
+  if (i != 0)
+    abort ();
+  if (ret != &r)
+    abort ();
+  if (p != thread_addr ())
+    abort ();
+  if (p[0] != 3 || p[1] != 4)
+    abort ();
+  exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/c2x-complit-5.c b/gcc/testsuite/gcc.dg/c2x-complit-5.c
new file mode 100644
index 00000000000..1eb0f8dd760
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-complit-5.c
@@ -0,0 +1,52 @@
+/* Test C2x storage class specifiers in compound literals: invalid code.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+int *p = &(register int) { 0 }; /* { dg-error "file-scope compound literal specifies" } */
+
+int v;
+
+void
+f ()
+{
+  int *q = &(thread_local int) { 0 }; /* { dg-error "compound literal implicitly auto and declared" } */
+  int *pc = &(static int) { v }; /* { dg-error "not constant" } */
+  int *pt = &(static thread_local int) { v }; /* { dg-error "not constant" } */
+  &(register int) { 0 }; /* { dg-error "address of register compound literal requested" } */
+  struct s { int a, b; };
+  &((register struct s) { 1, 2 }.b); /* { dg-error "address of register compound literal requested" } */
+}
+
+int *s = &(static static int) { 0 }; /* { dg-error "duplicate" } */
+
+void
+g ()
+{
+  (void) (register register int) { 0 }; /* { dg-error "duplicate" } */
+  (void) (static static int) { 0 }; /* { dg-error "duplicate" } */
+  (void) (static thread_local thread_local int) { 0 }; /* { dg-error "duplicate" } */
+  (void) (static register int) { 0 }; /* { dg-error "multiple storage classes in declaration specifiers" } */
+  (void) (register static int) { 0 }; /* { dg-error "multiple storage classes in declaration specifiers" } */
+  (void) (register thread_local int) { 0 }; /* { dg-error "used with" } */
+  (void) (thread_local register int) { 0 }; /* { dg-error "used with" } */
+}
+
+void
+h ()
+{
+  /* The following cases are not part of the C2x syntax, but are detected
+     specially by the parser.  */
+  (static int) 0; /* { dg-error "storage class specifier in cast" } */
+  sizeof (static int); /* { dg-error "storage class specifier in" } */
+  alignof (static int); /* { dg-error "storage class specifier in" } */
+}
+
+void
+bad_scspec ()
+{
+  /* Storage class specifiers not permitted in compound literals result in a
+     syntax error.  */
+  (typedef int) { 0 }; /* { dg-error "expected" } */
+  (auto int) { 0 }; /* { dg-error "expected" } */
+  (extern int) { 0 }; /* { dg-error "expected" } */
+}
diff --git a/gcc/testsuite/gcc.dg/c2x-complit-6.c b/gcc/testsuite/gcc.dg/c2x-complit-6.c
new file mode 100644
index 00000000000..23a0bb6420b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-complit-6.c
@@ -0,0 +1,7 @@
+/* Test C2x storage class specifiers in compound literals diagnosed with
+   -Wc11-c2x-compat.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -Wc11-c2x-compat" } */
+
+int *ps = &(static int) { 1 }; /* { dg-warning "forbids storage class specifiers in compound literals" } */
+int ss = sizeof (static int) { 1 }; /* { dg-warning "forbids storage class specifiers in compound literals" } */
diff --git a/gcc/testsuite/gcc.dg/c2x-complit-7.c b/gcc/testsuite/gcc.dg/c2x-complit-7.c
new file mode 100644
index 00000000000..0cd0b86c541
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-complit-7.c
@@ -0,0 +1,7 @@
+/* Test C2x storage class specifiers in compound literals diagnosed with
+   -Wc11-c2x-compat, but not errors with -pedantic-errors.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -Wc11-c2x-compat -pedantic-errors" } */
+
+int *ps = &(static int) { 1 }; /* { dg-warning "forbids storage class specifiers in compound literals" } */
+int ss = sizeof (static int) { 1 }; /* { dg-warning "forbids storage class specifiers in compound literals" } */
diff --git a/gcc/testsuite/gcc.dg/c90-complit-2.c b/gcc/testsuite/gcc.dg/c90-complit-2.c
new file mode 100644
index 00000000000..6fcf2a59c43
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c90-complit-2.c
@@ -0,0 +1,8 @@
+/* Test C2x storage class specifiers in compound literals not permitted for
+   C90, but without a duplicate diagnostic, just the diagnostic for compound
+   literals not being permitted in C90 at all.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c90 -pedantic-errors" } */
+
+int *ps = &(static int) { 1 }; /* { dg-error "ISO C90 forbids compound literals" } */
+int ss = sizeof (static int) { 1 }; /* { dg-error "ISO C90 forbids compound literals" } */
diff --git a/gcc/testsuite/gcc.dg/gnu2x-complit-1.c b/gcc/testsuite/gcc.dg/gnu2x-complit-1.c
new file mode 100644
index 00000000000..e9da5ad7958
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gnu2x-complit-1.c
@@ -0,0 +1,7 @@
+/* Test C2x storage class specifiers in compound literals: GNU use of alignof
+   on objects (tested separately since alignof parsing handles the type name of
+   compound literals).  */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu2x" } */
+
+int a = alignof (static int) { 0 };
diff --git a/gcc/testsuite/gcc.dg/gnu2x-complit-2.c b/gcc/testsuite/gcc.dg/gnu2x-complit-2.c
new file mode 100644
index 00000000000..20cb38fd94e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gnu2x-complit-2.c
@@ -0,0 +1,18 @@
+/* Test C2x storage class specifiers in compound literals.  Thread-local
+   cases, compilation tests, GNU __thread used.  */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu2x" } */
+/* { dg-require-effective-target tls } */
+
+#include <stddef.h>
+
+/* __thread is OK at file scope, although of limited use since the
+   thread-local object and its address are not constant expressions.  */
+size_t st = sizeof (__thread int) { 1 };
+size_t sst = sizeof (static __thread int) { 1 };
+
+int *
+f ()
+{
+  return &(static __thread int) { 2 };
+}
