result = 202003;
else if (is_attribute_p ("maybe_unused", attr_name))
result = 202106;
+ else if (is_attribute_p ("noreturn", attr_name)
+ || is_attribute_p ("_Noreturn", attr_name))
+ result = 202202;
}
if (result)
attr_name = NULL_TREE;
}
return NULL_TREE;
}
+
+/* Handle the standard [[noreturn]] attribute. */
+
+static tree
+handle_std_noreturn_attribute (tree *node, tree name, tree args,
+ int flags, bool *no_add_attrs)
+{
+ /* Unlike GNU __attribute__ ((noreturn)), the standard [[noreturn]]
+ only applies to functions, not function pointers. */
+ if (TREE_CODE (*node) == FUNCTION_DECL)
+ return handle_noreturn_attribute (node, name, args, flags, no_add_attrs);
+ else
+ {
+ pedwarn (input_location, OPT_Wattributes,
+ "standard %qE attribute can only be applied to functions",
+ name);
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+}
+
/* Table of supported standard (C2x) attributes. */
const struct attribute_spec std_attribute_table[] =
{
/* { name, min_len, max_len, decl_req, type_req, fn_type_req,
affects_type_identity, handler, exclude } */
+ { "_Noreturn", 0, 0, false, false, false, false,
+ handle_std_noreturn_attribute, NULL },
{ "deprecated", 0, 1, false, false, false, false,
handle_deprecated_attribute, NULL },
{ "fallthrough", 0, 0, false, false, false, false,
handle_unused_attribute, NULL },
{ "nodiscard", 0, 1, false, false, false, false,
handle_nodiscard_attribute, NULL },
+ { "noreturn", 0, 0, false, false, false, false,
+ handle_std_noreturn_attribute, NULL },
{ NULL, 0, 0, false, false, false, false, NULL, NULL }
};
--- /dev/null
+/* Test C2x noreturn attribute: valid uses. */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+[[noreturn]] void exit (int);
+
+[[__noreturn__]] int f1 (void);
+
+[[_Noreturn]] void f2 (void);
+
+[[___Noreturn__]] static void f3 (void) { exit (0); }
+
+/* Returning from a noreturn function is undefined at runtime, not a
+ constraint violation, but recommended practice is to diagnose if
+ such a return appears possible. */
+
+[[noreturn]] int
+f4 (void)
+{
+ return 1; /* { dg-warning "has a 'return' statement" } */
+ /* { dg-warning "does return" "second warning" { target *-*-* } .-1 } */
+}
+
+[[__noreturn__]] void
+f5 (void)
+{
+ return; /* { dg-warning "has a 'return' statement" } */
+ /* { dg-warning "does return" "second warning" { target *-*-* } .-1 } */
+}
+
+[[_Noreturn]] void
+f6 (void)
+{
+} /* { dg-warning "does return" } */
+
+[[___Noreturn__]] void
+f7 (int a)
+{
+ if (a)
+ exit (0);
+} /* { dg-warning "does return" } */
+
+/* Declarations need not all have the attribute (buf if the first does not,
+ there is undefined behavior). */
+
+void f2 (void);
+
+/* Duplicate attribute, and use with _Noreturn, is OK. */
+[[noreturn]] [[noreturn]] [[noreturn, __noreturn__]] void _Noreturn f9 (void);
+
+/* The attribute does not affect type compatibility. */
+
+void (*fp) (void) = f5;
+
+/* Unlike the function specifier, the attribute may be used on main. */
+[[noreturn]] int main ();
--- /dev/null
+/* Test C2x noreturn attribute: invalid contexts. */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+[[noreturn]]; /* { dg-error "ignored" } */
+
+int [[noreturn]] var; /* { dg-error "ignored" } */
+
+int array_with_dep_type[2] [[noreturn]]; /* { dg-error "ignored" } */
+
+void fn_with_dep_type () [[noreturn]]; /* { dg-error "ignored" } */
+
+int z = sizeof (int [[__noreturn__]]); /* { dg-error "ignored" } */
+
+[[noreturn]] int x1; /* { dg-error "can only be applied to functions" } */
+int x2 [[__noreturn__]]; /* { dg-error "can only be applied to functions" } */
+
+[[_Noreturn]] void (*fp) (); /* { dg-error "can only be applied to functions" } */
+
+void
+f (void)
+{
+ int a;
+ [[_Noreturn]]; /* { dg-error "ignored" } */
+ [[___Noreturn__]] a = 1; /* { dg-error "ignored" } */
+}
+
+int
+g ([[noreturn]] int x, int y) /* { dg-error "can only be applied to functions" } */
+{
+ [[noreturn]] typedef float F; /* { dg-error "can only be applied to functions" } */
+ [[noreturn]] int a; /* { dg-error "can only be applied to functions" } */
+ int b [[__noreturn__]]; /* { dg-error "can only be applied to functions" } */
+ int c [[noreturn]]; /* { dg-error "can only be applied to functions" } */
+ [[__noreturn__]] label1: ; /* { dg-error "can only be applied to functions" } */
+ c = y;
+ [[noreturn]] label2: ; /* { dg-error "can only be applied to functions" } */
+ return y;
+}
+
+struct [[_Noreturn]] s { double d; }; /* { dg-error "can only be applied to functions" } */
+
+struct s2
+{
+ [[___Noreturn__]] int a; /* { dg-error "can only be applied to functions" } */
+ int b [[noreturn]]; /* { dg-error "can only be applied to functions" } */
+} x;
+
+enum e { E1 [[noreturn]] }; /* { dg-error "can only be applied to functions" } */
+
+union [[_Noreturn]] u { int x; }; /* { dg-error "can only be applied to functions" } */
+
+enum [[noreturn]] eu { E2 }; /* { dg-error "can only be applied to functions" } */
+
+void fx ([[noreturn]] int p); /* { dg-error "can only be applied" } */
+
+union u2
+{
+ [[noreturn]] int a; /* { dg-error "can only be applied to functions" } */
+ int b [[noreturn]]; /* { dg-error "can only be applied to functions" } */
+} y;
+
+void
+g2 (int x)
+{
+ switch (x)
+ {
+ [[noreturn]] case 1: ; /* { dg-error "can only be applied to functions" } */
+ [[__noreturn__]] case 2: ; /* { dg-error "can only be applied to functions" } */
+ [[noreturn]] default: ; /* { dg-error "can only be applied to functions" } */
+ }
+}
--- /dev/null
+/* Test C2x noreturn attribute: invalid syntax. */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+[[noreturn()]] void a(); /* { dg-error "does not take any arguments" } */
+
+[[__noreturn__(0)]] void b(); /* { dg-error "does not take any arguments|expected" } */
+
+[[_Noreturn("", 123)]] void c(); /* { dg-error "does not take any arguments|expected" } */
+
+[[___Noreturn__("")]] void d(); /* { dg-error "does not take any arguments|expected" } */
#error "bad result for __fallthrough__"
#endif
+#if __has_c_attribute (noreturn) != 202202L
+#error "bad result for noreturn"
+#endif
+
+#if __has_c_attribute (__noreturn__) != 202202L
+#error "bad result for __noreturn__"
+#endif
+
+#if __has_c_attribute (_Noreturn) != 202202L
+#error "bad result for _Noreturn"
+#endif
+
+#if __has_c_attribute (___Noreturn__) != 202202L
+#error "bad result for ___Noreturn__"
+#endif
+
/* Macros in the attribute name are expanded. */
#define foo deprecated
#if __has_c_attribute (foo) != 201904L