+2019-01-14 Tom Honermann <tom@honermann.net>
+
+ * defaults.h: Define CHAR8_TYPE.
+
2019-01-14 Martin Sebor <msebor@redhat.com>
PR target/88638
+2019-01-14 Tom Honermann <tom@honermann.net>
+
+ Implement P0482R5, char8_t: A type for UTF-8 characters and strings
+ * c-common.c (c_common_reswords): Add char8_t.
+ (fix_string_type): Use char8_t for the type of u8 string literals.
+ (c_common_get_alias_set): char8_t doesn't alias.
+ (c_common_nodes_and_builtins): Define char8_t as a builtin type in
+ C++.
+ (c_stddef_cpp_builtins): Add __CHAR8_TYPE__.
+ (keyword_begins_type_specifier): Add RID_CHAR8.
+ * c-common.h (rid): Add RID_CHAR8.
+ (c_tree_index): Add CTI_CHAR8_TYPE and CTI_CHAR8_ARRAY_TYPE.
+ Define D_CXX_CHAR8_T and D_CXX_CHAR8_T_FLAGS.
+ Define char8_type_node and char8_array_type_node.
+ * c-cppbuiltin.c (cpp_atomic_builtins): Predefine
+ __GCC_ATOMIC_CHAR8_T_LOCK_FREE.
+ (c_cpp_builtins): Predefine __cpp_char8_t.
+ * c-lex.c (lex_string): Use char8_array_type_node as the type of
+ CPP_UTF8STRING.
+ (lex_charconst): Use char8_type_node as the type of CPP_UTF8CHAR.
+ * c-opts.c: If not otherwise specified, enable -fchar8_t when
+ targeting C++2a.
+ * c.opt: Add the -fchar8_t command line option.
+
2019-01-14 Martin Sebor <msebor@redhat.com>
PR target/88638
tree signed_char_type_node;
tree wchar_type_node;
+ tree char8_type_node;
tree char16_type_node;
tree char32_type_node;
tree wchar_array_type_node;
+ Type `char8_t[SOMENUMBER]' or something like it.
+ Used when a UTF-8 string literal is created.
+
+ tree char8_array_type_node;
+
Type `char16_t[SOMENUMBER]' or something like it.
Used when a UTF-16 string literal is created.
{ "case", RID_CASE, 0 },
{ "catch", RID_CATCH, D_CXX_OBJC | D_CXXWARN },
{ "char", RID_CHAR, 0 },
+ { "char8_t", RID_CHAR8, D_CXX_CHAR8_T_FLAGS | D_CXXWARN },
{ "char16_t", RID_CHAR16, D_CXXONLY | D_CXX11 | D_CXXWARN },
{ "char32_t", RID_CHAR32, D_CXXONLY | D_CXX11 | D_CXXWARN },
{ "class", RID_CLASS, D_CXX_OBJC | D_CXXWARN },
charsz = 1;
e_type = char_type_node;
}
+ else if (flag_char8_t && TREE_TYPE (value) == char8_array_type_node)
+ {
+ charsz = TYPE_PRECISION (char8_type_node) / BITS_PER_UNIT;
+ e_type = char8_type_node;
+ }
else if (TREE_TYPE (value) == char16_array_type_node)
{
charsz = TYPE_PRECISION (char16_type_node) / BITS_PER_UNIT;
CPP_STRING16, or CPP_STRING32. Return CPP_OTHER in case of error.
This may not be exactly the string token type that initially created
the string, since CPP_WSTRING is indistinguishable from the 16/32 bit
- string type at this point.
+ string type, and CPP_UTF8STRING is indistinguishable from CPP_STRING
+ at this point.
This effectively reverses part of the logic in lex_string and
fix_string_type. */
if (!TYPE_P (t))
return -1;
+ /* Unlike char, char8_t doesn't alias. */
+ if (flag_char8_t && t == char8_type_node)
+ return -1;
+
/* The C standard guarantees that any object may be accessed via an
- lvalue that has character type. */
+ lvalue that has narrow character type (except char8_t). */
if (t == char_type_node
|| t == signed_char_type_node
|| t == unsigned_char_type_node)
void
c_common_nodes_and_builtins (void)
{
+ int char8_type_size;
int char16_type_size;
int char32_type_size;
int wchar_type_size;
wchar_array_type_node
= build_array_type (wchar_type_node, array_domain_type);
+ /* Define 'char8_t'. */
+ char8_type_node = get_identifier (CHAR8_TYPE);
+ char8_type_node = TREE_TYPE (identifier_global_value (char8_type_node));
+ char8_type_size = TYPE_PRECISION (char8_type_node);
+ if (c_dialect_cxx ())
+ {
+ char8_type_node = make_unsigned_type (char8_type_size);
+
+ if (flag_char8_t)
+ record_builtin_type (RID_CHAR8, "char8_t", char8_type_node);
+ }
+
+ /* This is for UTF-8 string constants. */
+ char8_array_type_node
+ = build_array_type (char8_type_node, array_domain_type);
+
/* Define 'char16_t'. */
char16_type_node = get_identifier (CHAR16_TYPE);
char16_type_node = TREE_TYPE (identifier_global_value (char16_type_node));
builtin_define_with_value ("__WINT_TYPE__", WINT_TYPE, 0);
builtin_define_with_value ("__INTMAX_TYPE__", INTMAX_TYPE, 0);
builtin_define_with_value ("__UINTMAX_TYPE__", UINTMAX_TYPE, 0);
+ if (flag_char8_t)
+ builtin_define_with_value ("__CHAR8_TYPE__", CHAR8_TYPE, 0);
builtin_define_with_value ("__CHAR16_TYPE__", CHAR16_TYPE, 0);
builtin_define_with_value ("__CHAR32_TYPE__", CHAR32_TYPE, 0);
if (SIG_ATOMIC_TYPE)
case RID_ACCUM:
case RID_BOOL:
case RID_WCHAR:
+ case RID_CHAR8:
case RID_CHAR16:
case RID_CHAR32:
case RID_SAT:
/* C++11 */
RID_CONSTEXPR, RID_DECLTYPE, RID_NOEXCEPT, RID_NULLPTR, RID_STATIC_ASSERT,
+ /* char8_t */
+ RID_CHAR8,
+
/* C++ concepts */
RID_CONCEPT, RID_REQUIRES,
enum c_tree_index
{
+ CTI_CHAR8_TYPE,
CTI_CHAR16_TYPE,
CTI_CHAR32_TYPE,
CTI_WCHAR_TYPE,
CTI_UINTPTR_TYPE,
CTI_CHAR_ARRAY_TYPE,
+ CTI_CHAR8_ARRAY_TYPE,
CTI_CHAR16_ARRAY_TYPE,
CTI_CHAR32_ARRAY_TYPE,
CTI_WCHAR_ARRAY_TYPE,
mask) is _true_. Thus for keywords which are present in all
languages the disable field is zero. */
-#define D_CONLY 0x001 /* C only (not in C++). */
-#define D_CXXONLY 0x002 /* C++ only (not in C). */
-#define D_C99 0x004 /* In C, C99 only. */
-#define D_CXX11 0x008 /* In C++, C++11 only. */
-#define D_EXT 0x010 /* GCC extension. */
-#define D_EXT89 0x020 /* GCC extension incorporated in C99. */
-#define D_ASM 0x040 /* Disabled by -fno-asm. */
-#define D_OBJC 0x080 /* In Objective C and neither C nor C++. */
-#define D_CXX_OBJC 0x100 /* In Objective C, and C++, but not C. */
-#define D_CXXWARN 0x200 /* In C warn with -Wcxx-compat. */
-#define D_CXX_CONCEPTS 0x400 /* In C++, only with concepts. */
-#define D_TRANSMEM 0X800 /* C++ transactional memory TS. */
+#define D_CONLY 0x0001 /* C only (not in C++). */
+#define D_CXXONLY 0x0002 /* C++ only (not in C). */
+#define D_C99 0x0004 /* In C, C99 only. */
+#define D_CXX11 0x0008 /* In C++, C++11 only. */
+#define D_EXT 0x0010 /* GCC extension. */
+#define D_EXT89 0x0020 /* GCC extension incorporated in C99. */
+#define D_ASM 0x0040 /* Disabled by -fno-asm. */
+#define D_OBJC 0x0080 /* In Objective C and neither C nor C++. */
+#define D_CXX_OBJC 0x0100 /* In Objective C, and C++, but not C. */
+#define D_CXXWARN 0x0200 /* In C warn with -Wcxx-compat. */
+#define D_CXX_CONCEPTS 0x0400 /* In C++, only with concepts. */
+#define D_TRANSMEM 0X0800 /* C++ transactional memory TS. */
+#define D_CXX_CHAR8_T 0X1000 /* In C++, only with -fchar8_t. */
#define D_CXX_CONCEPTS_FLAGS D_CXXONLY | D_CXX_CONCEPTS
+#define D_CXX_CHAR8_T_FLAGS D_CXXONLY | D_CXX_CHAR8_T
/* The reserved keyword table. */
extern const struct c_common_resword c_common_reswords[];
/* The number of items in the reserved keyword table. */
extern const unsigned int num_c_common_reswords;
+#define char8_type_node c_global_trees[CTI_CHAR8_TYPE]
#define char16_type_node c_global_trees[CTI_CHAR16_TYPE]
#define char32_type_node c_global_trees[CTI_CHAR32_TYPE]
#define wchar_type_node c_global_trees[CTI_WCHAR_TYPE]
#define truthvalue_false_node c_global_trees[CTI_TRUTHVALUE_FALSE]
#define char_array_type_node c_global_trees[CTI_CHAR_ARRAY_TYPE]
+#define char8_array_type_node c_global_trees[CTI_CHAR8_ARRAY_TYPE]
#define char16_array_type_node c_global_trees[CTI_CHAR16_ARRAY_TYPE]
#define char32_array_type_node c_global_trees[CTI_CHAR32_ARRAY_TYPE]
#define wchar_array_type_node c_global_trees[CTI_WCHAR_ARRAY_TYPE]
(have_swap[SWAP_INDEX (boolean_type_node)]? 2 : 1));
builtin_define_with_int_value ("__GCC_ATOMIC_CHAR_LOCK_FREE",
(have_swap[SWAP_INDEX (signed_char_type_node)]? 2 : 1));
+ if (flag_char8_t)
+ builtin_define_with_int_value ("__GCC_ATOMIC_CHAR8_T_LOCK_FREE",
+ (have_swap[SWAP_INDEX (char8_type_node)]? 2 : 1));
builtin_define_with_int_value ("__GCC_ATOMIC_CHAR16_T_LOCK_FREE",
(have_swap[SWAP_INDEX (char16_type_node)]? 2 : 1));
builtin_define_with_int_value ("__GCC_ATOMIC_CHAR32_T_LOCK_FREE",
cpp_define (pfile, "__cpp_template_template_args=201611");
if (flag_threadsafe_statics)
cpp_define (pfile, "__cpp_threadsafe_static_init=200806");
+ if (flag_char8_t)
+ cpp_define (pfile, "__cpp_char8_t=201811");
}
/* Note that we define this for C as well, so that we know if
__attribute__((cleanup)) will interface with EH. */
{
default:
case CPP_STRING:
- case CPP_UTF8STRING:
TREE_TYPE (value) = char_array_type_node;
break;
+ case CPP_UTF8STRING:
+ if (flag_char8_t)
+ TREE_TYPE (value) = char8_array_type_node;
+ else
+ TREE_TYPE (value) = char_array_type_node;
+ break;
case CPP_STRING16:
TREE_TYPE (value) = char16_array_type_node;
break;
else if (token->type == CPP_CHAR16)
type = char16_type_node;
else if (token->type == CPP_UTF8CHAR)
- type = char_type_node;
+ {
+ if (flag_char8_t)
+ type = char8_type_node;
+ else
+ type = char_type_node;
+ }
/* In C, a character constant has type 'int'.
In C++ 'char', but multi-char charconsts have type 'int'. */
else if (!c_dialect_cxx () || chars_seen > 1)
if (flag_sized_deallocation == -1)
flag_sized_deallocation = (cxx_dialect >= cxx14);
+ /* char8_t support is new in C++2A. */
+ if (flag_char8_t == -1)
+ flag_char8_t = (cxx_dialect >= cxx2a);
+
if (flag_extern_tls_init)
{
if (!TARGET_SUPPORTS_ALIASES || !SUPPORTS_WEAK)
C ObjC C++ ObjC++
Where shorter, use canonicalized paths to systems headers.
+fchar8_t
+C++ ObjC++ Var(flag_char8_t) Init(-1)
+Enable the char8_t fundamental type and use it as the type for UTF-8 string
+and character literals.
+
fcheck-pointer-bounds
C ObjC C++ ObjC++ LTO Deprecated
Deprecated in GCC 9. This switch has no effect.
+2019-01-14 Tom Honermann <tom@honermann.net>
+
+ Implement P0482R5, char8_t: A type for UTF-8 characters and strings
+ * cvt.c (type_promotes_to): Handle char8_t promotion.
+ * decl.c (grokdeclarator): Handle invalid type specifier
+ combinations involving char8_t.
+ * lex.c (init_reswords): Add char8_t as a reserved word.
+ * mangle.c (write_builtin_type): Add name mangling for char8_t (Du).
+ * parser.c (cp_keyword_starts_decl_specifier_p)
+ (cp_parser_simple_type_specifier): Recognize char8_t as a simple
+ type specifier.
+ (cp_parser_string_literal): Use char8_array_type_node for the type
+ of CPP_UTF8STRING.
+ (cp_parser_set_decl_spec_type): Tolerate char8_t typedefs in system
+ headers.
+ * rtti.c (emit_support_tinfos): type_info support for char8_t.
+ * tree.c (char_type_p): Recognize char8_t as a character type.
+ * typeck.c (string_conv_p): Handle conversions of u8 string
+ literals of char8_t type.
+ (check_literal_operator_args): Handle UDLs with u8 string literals
+ of char8_t type.
+ * typeck2.c (ordinary_char_type_p): New.
+ (digest_init_r): Disallow initializing a char array with a u8 string
+ literal.
+
2019-01-14 Martin Liska <mliska@suse.cz>
PR gcov-profile/88263
extern tree split_nonconstant_init (tree, tree);
extern bool check_narrowing (tree, tree, tsubst_flags_t,
bool = false);
+extern bool ordinary_char_type_p (tree);
extern tree digest_init (tree, tree, tsubst_flags_t);
extern tree digest_init_flags (tree, tree, int, tsubst_flags_t);
extern tree digest_nsdmi_init (tree, tree, tsubst_flags_t);
wider. Scoped enums don't promote, but pretend they do for backward
ABI bug compatibility wrt varargs. */
else if (TREE_CODE (type) == ENUMERAL_TYPE
+ || type == char8_type_node
|| type == char16_type_node
|| type == char32_type_node
|| type == wchar_type_node)
error_at (&richloc, "%<long%> and %<short%> specified together");
}
else if (TREE_CODE (type) != INTEGER_TYPE
- || type == char16_type_node || type == char32_type_node
+ || type == char8_type_node
+ || type == char16_type_node
+ || type == char32_type_node
|| ((long_p || short_p)
&& (explicit_char || explicit_intN)))
error_at (loc, "%qs specified with %qT", key, type);
mask |= D_CXX_CONCEPTS;
if (!flag_tm)
mask |= D_TRANSMEM;
+ if (!flag_char8_t)
+ mask |= D_CXX_CHAR8_T;
if (flag_no_asm)
mask |= D_ASM | D_EXT;
if (flag_no_gnu_keywords)
break;
case INTEGER_TYPE:
- /* TYPE may still be wchar_t, char16_t, or char32_t, since that
+ /* TYPE may still be wchar_t, char8_t, char16_t, or char32_t, since that
isn't in integer_type_nodes. */
if (type == wchar_type_node)
write_char ('w');
+ else if (type == char8_type_node)
+ write_string ("Du");
else if (type == char16_type_node)
write_string ("Ds");
else if (type == char32_type_node)
case RID_TYPENAME:
/* Simple type specifiers. */
case RID_CHAR:
+ case RID_CHAR8:
case RID_CHAR16:
case RID_CHAR32:
case RID_WCHAR:
{
default:
case CPP_STRING:
- case CPP_UTF8STRING:
TREE_TYPE (value) = char_array_type_node;
break;
+ case CPP_UTF8STRING:
+ if (flag_char8_t)
+ TREE_TYPE (value) = char8_array_type_node;
+ else
+ TREE_TYPE (value) = char_array_type_node;
+ break;
case CPP_STRING16:
TREE_TYPE (value) = char16_array_type_node;
break;
decl_specs->explicit_char_p = true;
type = char_type_node;
break;
+ case RID_CHAR8:
+ type = char8_type_node;
+ break;
case RID_CHAR16:
type = char16_type_node;
break;
{
decl_specs->any_specifiers_p = true;
- /* If the user tries to redeclare bool, char16_t, char32_t, or wchar_t
- (with, for example, in "typedef int wchar_t;") we remember that
+ /* If the user tries to redeclare bool, char8_t, char16_t, char32_t, or
+ wchar_t (with, for example, in "typedef int wchar_t;") we remember that
this is what happened. In system headers, we ignore these
declarations so that G++ can work with system headers that are not
C++-safe. */
if (decl_spec_seq_has_spec_p (decl_specs, ds_typedef)
&& !type_definition_p
&& (type_spec == boolean_type_node
+ || type_spec == char8_type_node
|| type_spec == char16_type_node
|| type_spec == char32_type_node
|| type_spec == wchar_type_node)
{
&void_type_node,
&boolean_type_node,
- &wchar_type_node, &char16_type_node, &char32_type_node,
+ &wchar_type_node, &char8_type_node, &char16_type_node, &char32_type_node,
&char_type_node, &signed_char_type_node, &unsigned_char_type_node,
&short_integer_type_node, &short_unsigned_type_node,
&integer_type_node, &unsigned_type_node,
return (same_type_p (type, char_type_node)
|| same_type_p (type, unsigned_char_type_node)
|| same_type_p (type, signed_char_type_node)
+ || same_type_p (type, char8_type_node)
|| same_type_p (type, char16_type_node)
|| same_type_p (type, char32_type_node)
|| same_type_p (type, wchar_type_node));
t = TREE_TYPE (totype);
if (!same_type_p (t, char_type_node)
+ && !same_type_p (t, char8_type_node)
&& !same_type_p (t, char16_type_node)
&& !same_type_p (t, char32_type_node)
&& !same_type_p (t, wchar_type_node))
t = TYPE_MAIN_VARIANT (t);
if ((maybe_raw_p = same_type_p (t, char_type_node))
|| same_type_p (t, wchar_type_node)
+ || same_type_p (t, char8_type_node)
|| same_type_p (t, char16_type_node)
|| same_type_p (t, char32_type_node))
{
max_arity = 1;
else if (same_type_p (t, wchar_type_node))
max_arity = 1;
+ else if (same_type_p (t, char8_type_node))
+ max_arity = 1;
else if (same_type_p (t, char16_type_node))
max_arity = 1;
else if (same_type_p (t, char32_type_node))
return ok;
}
+/* True iff TYPE is a C++2a "ordinary" character type. */
+
+bool
+ordinary_char_type_p (tree type)
+{
+ type = TYPE_MAIN_VARIANT (type);
+ return (type == char_type_node
+ || type == signed_char_type_node
+ || type == unsigned_char_type_node);
+}
+
/* Process the initializer INIT for a variable of type TYPE, emitting
diagnostics for invalid initializers and converting the initializer as
appropriate.
&& TREE_CODE (stripped_init) == STRING_CST)
{
tree char_type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (init)));
+ bool incompat_string_cst = false;
- if (TYPE_PRECISION (typ1) == BITS_PER_UNIT)
+ if (typ1 != char_type)
{
- if (char_type != char_type_node
- && char_type != signed_char_type_node
- && char_type != unsigned_char_type_node)
- {
- if (complain & tf_error)
- error_at (loc, "char-array initialized from wide string");
- return error_mark_node;
- }
+ /* The array element type does not match the initializing string
+ literal element type; this is only allowed when both types are
+ ordinary character type. There are no string literals of
+ signed or unsigned char type in the language, but we can get
+ them internally from converting braced-init-lists to
+ STRING_CST. */
+ if (ordinary_char_type_p (typ1)
+ && ordinary_char_type_p (char_type))
+ /* OK */;
+ else
+ incompat_string_cst = true;
}
- else
+
+ if (incompat_string_cst)
{
- if (char_type == char_type_node
- || char_type == signed_char_type_node
- || char_type == unsigned_char_type_node)
- {
- if (complain & tf_error)
- error_at (loc,
- "int-array initialized from non-wide string");
- return error_mark_node;
- }
- else if (char_type != typ1)
- {
- if (complain & tf_error)
- error_at (loc, "int-array initialized from incompatible "
- "wide string");
- return error_mark_node;
- }
+ if (complain & tf_error)
+ error_at (loc, "cannot initialize array of %qT from "
+ "a string literal with type array of %qT",
+ typ1, char_type);
+ return error_mark_node;
}
if (nested == 2 && !TYPE_DOMAIN (type))
affect C++ name mangling because in C++ these are distinct types
not typedefs. */
+#ifndef CHAR8_TYPE
+#define CHAR8_TYPE "unsigned char"
+#endif
+
#ifdef UINT_LEAST16_TYPE
#define CHAR16_TYPE UINT_LEAST16_TYPE
#else
@item C++ Language Options
@xref{C++ Dialect Options,,Options Controlling C++ Dialect}.
@gccoptlist{-fabi-version=@var{n} -fno-access-control @gol
--faligned-new=@var{n} -fargs-in-order=@var{n} -fcheck-new @gol
+-faligned-new=@var{n} -fargs-in-order=@var{n} -fchar8_t -fcheck-new @gol
-fconstexpr-depth=@var{n} -fconstexpr-loop-limit=@var{n} @gol
-fno-elide-constructors @gol
-fno-enforce-eh-specs @gol
This flag is enabled by default for @option{-std=c++17}.
+@item -fchar8_t
+@itemx -fno-char8_t
+@opindex fchar8_t
+@opindex fno-char8_t
+Enable support for @code{char8_t} as adopted for C++2a. This includes
+the addition of a new @code{char8_t} fundamental type, changes to the
+types of UTF-8 string and character literals, new signatures for
+user-defined literals, associated standard library updates, and new
+@code{__cpp_char8_t} and @code{__cpp_lib_char8_t} feature test macros.
+
+This option enables functions to be overloaded for ordinary and UTF-8
+strings:
+
+@smallexample
+int f(const char *); // #1
+int f(const char8_t *); // #2
+int v1 = f("text"); // Calls #1
+int v2 = f(u8"text"); // Calls #2
+@end smallexample
+
+@noindent
+and introduces new signatures for user-defined literals:
+
+@smallexample
+int operator""_udl1(char8_t);
+int v3 = u8'x'_udl1;
+int operator""_udl2(const char8_t*, std::size_t);
+int v4 = u8"text"_udl2;
+template<typename T, T...> int operator""_udl3();
+int v5 = u8"text"_udl3;
+@end smallexample
+
+@noindent
+The change to the types of UTF-8 string and character literals introduces
+incompatibilities with ISO C++11 and later standards. For example, the
+following code is well-formed under ISO C++11, but is ill-formed when
+@option{-fchar8_t} is specified.
+
+@smallexample
+char ca[] = u8"xx"; // error: char-array initialized from wide
+ // string
+const char *cp = u8"xx";// error: invalid conversion from
+ // `const char8_t*' to `const char*'
+int f(const char*);
+auto v = f(u8"xx"); // error: invalid conversion from
+ // `const char8_t*' to `const char*'
+std::string s@{u8"xx"@}; // error: no matching function for call to
+ // `std::basic_string<char>::basic_string()'
+using namespace std::literals;
+s = u8"xx"s; // error: conversion from
+ // `basic_string<char8_t>' to non-scalar
+ // type `basic_string<char>' requested
+@end smallexample
+
@item -fcheck-new
@opindex fcheck-new
Check that the pointer returned by @code{operator new} is non-null
const char s17[] = R"?(?)??)?";
const char s18[] = R"??(??)??)??)??";
+const char u800[] = u8R"??=??(??<??>??)??'??!??-\
+(a)#[{}]^|~";
+)??=??";
+const char u801[] = u8R"a(
+)\
+a"
+)a";
+const char u802[] = u8R"a(
+)a\
+"
+)a";
+const char u803[] = u8R"ab(
+)a\
+b"
+)ab";
+const char u804[] = u8R"a??/(x)a??/";
+const char u805[] = u8R"abcdefghijklmn??(abc)abcdefghijklmn??";
+const char u806[] = u8R"abcdefghijklm??/(abc)abcdefghijklm??/";
+const char u807[] = u8R"abc(??)\
+abc";)abc";
+const char u808[] = u8R"def(de)\
+def";)def";
+const char u809[] = u8R"a(??)\
+a"
+)a";
+const char u810[] = u8R"a(??)a\
+"
+)a";
+const char u811[] = u8R"ab(??)a\
+b"
+)ab";
+const char u812[] = u8R"a#(a#)a??=)a#";
+const char u813[] = u8R"a#(??)a??=??)a#";
+const char u814[] = u8R"??/(x)??/
+";)??/";
+const char u815[] = u8R"??/(??)??/
+";)??/";
+const char u816[] = u8R"??(??)??";
+const char u817[] = u8R"?(?)??)?";
+const char u818[] = u8R"??(??)??)??)??";
+
const char16_t u00[] = uR"??=??(??<??>??)??'??!??-\
(a)#[{}]^|~";
)??=??";
TEST (s16, "??");
TEST (s17, "?)??");
TEST (s18, "??"")??"")??");
+ TEST (u800, u8"??""<??"">??"")??""'??""!??""-\\\n(a)#[{}]^|~\";\n");
+ TEST (u801, u8"\n)\\\na\"\n");
+ TEST (u802, u8"\n)a\\\n\"\n");
+ TEST (u803, u8"\n)a\\\nb\"\n");
+ TEST (u804, u8"x");
+ TEST (u805, u8"abc");
+ TEST (u806, u8"abc");
+ TEST (u807, u8"??"")\\\nabc\";");
+ TEST (u808, u8"de)\\\ndef\";");
+ TEST (u809, u8"??"")\\\na\"\n");
+ TEST (u810, u8"??"")a\\\n\"\n");
+ TEST (u811, u8"??"")a\\\nb\"\n");
+ TEST (u812, u8"a#)a??""=");
+ TEST (u813, u8"??"")a??""=??");
+ TEST (u814, u8"x)??""/\n\";");
+ TEST (u815, u8"??"")??""/\n\";");
+ TEST (u816, u8"??");
+ TEST (u817, u8"?)??");
+ TEST (u818, u8"??"")??"")??");
TEST (u00, u"??""<??"">??"")??""'??""!??""-\\\n(a)#[{}]^|~\";\n");
TEST (u01, u"\n)\\\na\"\n");
TEST (u02, u"\n)a\\\n\"\n");
const char s17[] = R"?(?)??)?";
const char s18[] = R"??(??)??)??)??";
+const char u800[] = u8R"??=??(??<??>??)??'??!??-\
+(a)#[{}]^|~";
+)??=??";
+const char u801[] = u8R"a(
+)\
+a"
+)a";
+const char u802[] = u8R"a(
+)a\
+"
+)a";
+const char u803[] = u8R"ab(
+)a\
+b"
+)ab";
+const char u804[] = u8R"a??/(x)a??/";
+const char u805[] = u8R"abcdefghijklmn??(abc)abcdefghijklmn??";
+const char u806[] = u8R"abcdefghijklm??/(abc)abcdefghijklm??/";
+const char u807[] = u8R"abc(??)\
+abc";)abc";
+const char u808[] = u8R"def(de)\
+def";)def";
+const char u809[] = u8R"a(??)\
+a"
+)a";
+const char u810[] = u8R"a(??)a\
+"
+)a";
+const char u811[] = u8R"ab(??)a\
+b"
+)ab";
+const char u812[] = u8R"a#(a#)a??=)a#";
+const char u813[] = u8R"a#(??)a??=??)a#";
+const char u814[] = u8R"??/(x)??/
+";)??/";
+const char u815[] = u8R"??/(??)??/
+";)??/";
+const char u816[] = u8R"??(??)??";
+const char u817[] = u8R"?(?)??)?";
+const char u818[] = u8R"??(??)??)??)??";
+
const char16_t u00[] = uR"??=??(??<??>??)??'??!??-\
(a)#[{}]^|~";
)??=??";
TEST (s16, "??");
TEST (s17, "?)??");
TEST (s18, "??"")??"")??");
+ TEST (u800, u8"??""<??"">??"")??""'??""!??""-\\\n(a)#[{}]^|~\";\n");
+ TEST (u801, u8"\n)\\\na\"\n");
+ TEST (u802, u8"\n)a\\\n\"\n");
+ TEST (u803, u8"\n)a\\\nb\"\n");
+ TEST (u804, u8"x");
+ TEST (u805, u8"abc");
+ TEST (u806, u8"abc");
+ TEST (u807, u8"??"")\\\nabc\";");
+ TEST (u808, u8"de)\\\ndef\";");
+ TEST (u809, u8"??"")\\\na\"\n");
+ TEST (u810, u8"??"")a\\\n\"\n");
+ TEST (u811, u8"??"")a\\\nb\"\n");
+ TEST (u812, u8"a#)a??""=");
+ TEST (u813, u8"??"")a??""=??");
+ TEST (u814, u8"x)??""/\n\";");
+ TEST (u815, u8"??"")??""/\n\";");
+ TEST (u816, u8"??");
+ TEST (u817, u8"?)??");
+ TEST (u818, u8"??"")??"")??");
TEST (u00, u"??""<??"">??"")??""'??""!??""-\\\n(a)#[{}]^|~\";\n");
TEST (u01, u"\n)\\\na\"\n");
TEST (u02, u"\n)a\\\n\"\n");
constexpr wchar_t c1 = L"hi"[3]; // { dg-error "array subscript" }
constexpr char16_t c2 = u"hi"[3]; // { dg-error "array subscript" }
constexpr char32_t c3 = U"hi"[3]; // { dg-error "array subscript" }
+constexpr char c4 = u8"hi"[3]; // { dg-error "array subscript" }
--- /dev/null
+// { dg-options "-std=c++17 -fchar8_t" }
+
+#include <cstdint>
+
+int operator"" _bar (long double);
+
+double operator"" _foo (long long unsigned);
+
+int i = 12_bar; // { dg-error "unable to find numeric literal operator|with|argument" }
+
+double d = 1.2_foo; // { dg-error "unable to find numeric literal operator|with|argument" }
+
+int operator"" _char(char);
+
+int operator"" _char8_t(char8_t);
+
+int operator"" _wchar_t(wchar_t);
+
+int operator"" _char16_t(char16_t);
+
+int operator"" _char32_t(char32_t);
+
+int cwcx = 'c'_wchar_t; // { dg-error "unable to find character literal operator|with|argument" }
+int cc8 = 'c'_char8_t; // { dg-error "unable to find character literal operator|with|argument" }
+int cc16 = 'c'_char16_t; // { dg-error "unable to find character literal operator|with|argument" }
+int cc32 = 'c'_char32_t; // { dg-error "unable to find character literal operator|with|argument" }
+
+int wccx = L'c'_char; // { dg-error "unable to find character literal operator|with|argument" }
+int wcc8 = L'c'_char8_t; // { dg-error "unable to find character literal operator|with|argument" }
+int wcc16 = L'c'_char16_t; // { dg-error "unable to find character literal operator|with|argument" }
+int wcc32 = L'c'_char32_t; // { dg-error "unable to find character literal operator|with|argument" }
+
+int c8c = u8'c'_char; // { dg-error "unable to find character literal operator|with|argument" }
+int c8wc = u8'c'_wchar_t; // { dg-error "unable to find character literal operator|with|argument" }
+int c8c16 = u8'c'_char16_t; // { dg-error "unable to find character literal operator|with|argument" }
+int c8c32 = u8'c'_char32_t; // { dg-error "unable to find character literal operator|with|argument" }
+
+int c16c = u'c'_char; // { dg-error "unable to find character literal operator|with|argument" }
+int c16c8 = u'c'_char8_t; // { dg-error "unable to find character literal operator|with|argument" }
+int c16wc = u'c'_wchar_t; // { dg-error "unable to find character literal operator|with|argument" }
+int c16c32 = u'c'_char32_t; // { dg-error "unable to find character literal operator|with|argument" }
+
+int c32c = U'c'_char; // { dg-error "unable to find character literal operator|with|argument" }
+int c32c8 = U'c'_char8_t; // { dg-error "unable to find character literal operator|with|argument" }
+int c32wc = U'c'_wchar_t; // { dg-error "unable to find character literal operator|with|argument" }
+int c32c16 = U'c'_char16_t; // { dg-error "unable to find character literal operator|with|argument" }
+
+int operator"" _char_str(const char*, std::size_t);
+
+int operator"" _wchar_t_str(const wchar_t*, std::size_t);
+
+int operator"" _char8_t_str(const char8_t*, std::size_t);
+
+int operator"" _char16_t_str(const char16_t*, std::size_t);
+
+int operator"" _char32_t_str(const char32_t*, std::size_t);
+
+int strwstr = "str"_wchar_t_str; // { dg-error "unable to find string literal operator|with|arguments" }
+int strstr8 = "str"_char8_t_str; // { dg-error "unable to find string literal operator|with|arguments" }
+int strstr16 = "str"_char16_t_str; // { dg-error "unable to find string literal operator|with|arguments" }
+int strstr32 = "str"_char32_t_str; // { dg-error "unable to find string literal operator|with|arguments" }
+
+int str8str = u8"str"_char_str; // { dg-error "unable to find string literal operator|with|arguments" }
+int str8wstr = u8"str"_wchar_t_str; // { dg-error "unable to find string literal operator|with|arguments" }
+int str8str16 = u8"str"_char16_t_str; // { dg-error "unable to find string literal operator|with|arguments" }
+int str8str32 = u8"str"_char32_t_str; // { dg-error "unable to find string literal operator|with|arguments" }
+
+int wstrstr = L"str"_char_str; // { dg-error "unable to find string literal operator|with|arguments" }
+int wstrstr8 = L"str"_char8_t_str; // { dg-error "unable to find string literal operator|with|arguments" }
+int wstrstr16 = L"str"_char16_t_str; // { dg-error "unable to find string literal operator|with|arguments" }
+int wstrstr32 = L"str"_char32_t_str; // { dg-error "unable to find string literal operator|with|arguments" }
+
+int str16str = u"str"_char_str; // { dg-error "unable to find string literal operator|with|arguments" }
+int str16wstr = u"str"_wchar_t_str; // { dg-error "unable to find string literal operator|with|arguments" }
+int str16str8 = u"str"_char8_t_str; // { dg-error "unable to find string literal operator|with|arguments" }
+int str16str32 = u"str"_char32_t_str; // { dg-error "unable to find string literal operator|with|arguments" }
+
+int str32str = U"str"_char_str; // { dg-error "unable to find string literal operator|with|arguments" }
+int str32wstr = U"str"_wchar_t_str; // { dg-error "unable to find string literal operator|with|arguments" }
+int str32str8 = U"str"_char8_t_str; // { dg-error "unable to find string literal operator string operator|with|arguments" }
+int str32str16 = U"str"_char16_t_str; // { dg-error "unable to find string literal operator string operator|with|arguments" }
--- /dev/null
+// { dg-options "-std=c++17 -fchar8_t" }
+
+#include <cstdint>
+#include <cassert>
+
+int operator"" _foo(const char*) { return 0; }
+int operator"" _foo(unsigned long long int) { return 1; }
+int operator"" _foo(long double) { return 2; }
+int operator"" _foo(char) { return 3; }
+int operator"" _foo(wchar_t) { return 4; }
+int operator"" _foo(char8_t) { return 5; }
+int operator"" _foo(char16_t) { return 6; }
+int operator"" _foo(char32_t) { return 7; }
+int operator"" _foo(const char*, std::size_t) { return 8; }
+int operator"" _foo(const wchar_t*, std::size_t) { return 9; }
+int operator"" _foo(const char8_t*, std::size_t) { return 10; }
+int operator"" _foo(const char16_t*, std::size_t) { return 11; }
+int operator"" _foo(const char32_t*, std::size_t) { return 12; }
+template<char...> int operator"" _foo2() { return 20; }
+int operator"" _foo2(unsigned long long int) { return 21; }
+
+int
+main()
+{
+ assert(123_foo == 1);
+ assert(0.123_foo == 2);
+ assert('c'_foo == 3);
+ assert(L'c'_foo == 4);
+ assert(u8'c'_foo == 5);
+ assert(u'c'_foo == 6);
+ assert(U'c'_foo == 7);
+ assert("abc"_foo == 8);
+ assert(L"abc"_foo == 9);
+ assert(u8"abc"_foo == 10);
+ assert(u"abc"_foo == 11);
+ assert(U"abc"_foo == 12);
+ assert(123_foo2 == 21);
+}
return len;
}
+#if __cpp_char8_t
+constexpr size_type
+operator"" _len(const char8_t*, size_type len)
+{
+ return len;
+}
+#endif
+
constexpr size_type
operator"" _len(const wchar_t*, size_type len)
{
using namespace my_string_literals;
decltype("Hello, World!"s) s;
+#if !__cpp_char8_t == !__cpp_lib_char8_t
decltype(u8"Hello, World!"s) s8;
+#endif
decltype(L"Hello, World!"s) ws;
decltype(u"Hello, World!"s) s16;
decltype(U"Hello, World!"s) s32;
operator"" s(const char* str, std::size_t len)
{ return std::string{str, len}; }
+#if __cpp_lib_char8_t
+ std::u8string
+ operator"" s(const char8_t* str, std::size_t len)
+ { return std::u8string{str, len}; }
+#endif
+
std::wstring
operator"" s(const wchar_t* str, std::size_t len)
{ return std::wstring{str, len}; }
// { dg-do compile { target c++17 } }
+typedef decltype(u8'c') u8_char_t;
+
constexpr int
-operator""_foo(char c)
+operator""_foo(u8_char_t c)
{ return c * 100; }
auto cc = u8'8'_foo;
auto c = 'c';
auto u8c = u8'c';
+#if __cpp_char8_t
+static_assert(!std::experimental::is_same_v<decltype(u8c), decltype(c)>, "");
+#else
static_assert(std::experimental::is_same_v<decltype(u8c), decltype(c)>, "");
+#endif
auto u8s = u8"c";
auto x = u8s[0];
--- /dev/null
+// P0482R6
+// { dg-do compile }
+// { dg-options "-std=c++2a" }
+
+char8_t c8;
--- /dev/null
+// P0482R6
+// { dg-do compile }
+// { dg-options "-std=c++2a -fno-char8_t" }
+
+char8_t c8; // { dg-error "does not name a type" }
#else
# error "__has_cpp_attribute"
#endif
+
+// C++2A features:
+
+#ifndef __cpp_char8_t
+# error "__cpp_char8_t"
+#elif __cpp_char8_t != 201811
+# error "__cpp_char8_t != 201811"
+#endif
--- /dev/null
+// Test that char8_t does not alias with other types when -fchar8_t is enabled.
+// { dg-do compile }
+// { dg-options "-fstrict-aliasing -Wstrict-aliasing=1 -fchar8_t" }
+
+extern long l;
+char8_t* f() {
+ return (char8_t*)&l; // { dg-warning "dereferencing type-punned pointer might break strict-aliasing rules" "char8_t" }
+}
--- /dev/null
+// Test that UTF-8 character literals have type char if -fchar8_t is not enabled.
+// { dg-do compile }
+// { dg-options "-std=c++17 -fno-char8_t" }
+
+template<typename T1, typename T2>
+ struct is_same
+ { static const bool value = false; };
+template<typename T>
+ struct is_same<T, T>
+ { static const bool value = true; };
+
+static_assert(is_same<decltype(u8'x'), char>::value, "Error");
--- /dev/null
+// Test that UTF-8 character literals have type char8_t if -fchar8_t is enabled.
+// { dg-do compile }
+// { dg-options "-std=c++17 -fchar8_t" }
+
+template<typename T1, typename T2>
+ struct is_same
+ { static const bool value = false; };
+template<typename T>
+ struct is_same<T, T>
+ { static const bool value = true; };
+
+static_assert(is_same<decltype(u8'x'), char8_t>::value, "Error");
--- /dev/null
+// Test that char is deduced for UTF-8 character and string literals when
+// -fchar8_t is not in effect.
+// { dg-do compile }
+// { dg-options "-std=c++17 -fno-char8_t" }
+
+template<typename T1, typename T2>
+ struct is_same
+ { static const bool value = false; };
+
+template<typename T>
+ struct is_same<T, T>
+ { static const bool value = true; };
+
+template<typename T1, typename T2, typename T3>
+void ft(T1, T2, T3 &) {
+ static_assert(is_same<T1, char>::value, "Error");
+ static_assert(is_same<T2, const char*>::value, "Error");
+ static_assert(is_same<T3, const char[2]>::value, "Error");
+}
+
+auto x = (ft(u8'x', u8"x", u8"x"),0);
+
+auto c8 = u8'x';
+static_assert(is_same<decltype(c8), char>::value, "Error");
+
+auto c8p = u8"x";
+static_assert(is_same<decltype(c8p), const char*>::value, "Error");
+
+auto &c8a = u8"x";
+static_assert(is_same<decltype(c8a), const char(&)[2]>::value, "Error");
--- /dev/null
+// Test that char8_t is deduced for UTF-8 character and string literals when
+// -fchar8_t is in effect.
+// { dg-do compile }
+// { dg-options "-std=c++17 -fchar8_t" }
+
+template<typename T1, typename T2>
+ struct is_same
+ { static const bool value = false; };
+
+template<typename T>
+ struct is_same<T, T>
+ { static const bool value = true; };
+
+template<typename T1, typename T2, typename T3>
+void ft(T1, T2, T3 &) {
+ static_assert(is_same<T1, char8_t>::value, "Error");
+ static_assert(is_same<T2, const char8_t*>::value, "Error");
+ static_assert(is_same<T3, const char8_t[2]>::value, "Error");
+}
+
+auto x = (ft(u8'x', u8"x", u8"x"),0);
+
+auto c8 = u8'x';
+static_assert(is_same<decltype(c8), char8_t>::value, "Error");
+
+auto c8p = u8"x";
+static_assert(is_same<decltype(c8p), const char8_t*>::value, "Error");
+
+auto &c8a = u8"x";
+static_assert(is_same<decltype(c8a), const char8_t(&)[2]>::value, "Error");
--- /dev/null
+// Test that predefined feature test macros are not present when -fchar8_t is
+// not enabled.
+// { dg-do compile }
+// { dg-options "-fno-char8_t" }
+
+#if defined(__cpp_char8_t)
+#error __cpp_char8_t is defined!
+#endif
--- /dev/null
+// Test that predefined feature test macros are present when -fchar8_t is
+// enabled.
+// { dg-do compile }
+// { dg-options "-fchar8_t" }
+
+#if !defined(__cpp_char8_t)
+# error __cpp_char8_t is not defined!
+#elif __cpp_char8_t != 201811
+# error __cpp_char8_t != 201811
+#endif
--- /dev/null
+// Test initialization from UTF-8 literals when -fchar8_t is not enabled.
+// { dg-do compile }
+// { dg-options "-std=c++17 -fno-char8_t" }
+
+char c1 = 'x';
+char c2 = u8'x';
+
+const char *pc1 = "x";
+const char *pc2 = u8"x";
+
+const char (&rca1)[2] = "x";
+const char (&rca2)[2] = u8"x";
+
+char ca1[] = "x";
+char ca2[] = u8"x";
+
+signed char sca1[] = "x";
+signed char sca2[] = u8"x";
+
+unsigned char uca1[] = "x";
+unsigned char uca2[] = u8"x";
--- /dev/null
+// Test initialization from UTF-8 literals when -fchar8_t is enabled.
+// { dg-do compile }
+// { dg-options "-std=c++17 -fchar8_t" }
+
+char c1 = 'x';
+char c2 = u8'x';
+char8_t c3 = 'x';
+char8_t c4 = u8'x';
+char8_t c5 = u'x';
+
+const char *pc1 = "x";
+const char *pc2 = u8"x"; // { dg-error "invalid conversion from .const char8_t.. to .const char.." "char8_t" }
+const char8_t *pc3 = "x"; // { dg-error "invalid conversion from .const char.. to .const char8_t.." "char8_t" }
+const char8_t *pc4 = u8"x";
+const char8_t *pc5 = u"x"; // { dg-error "cannot convert .const char16_t.. to .const char8_t.. in initialization" "char8_t" }
+
+const char (&rca1)[2] = "x";
+const char (&rca2)[2] = u8"x"; // { dg-error "invalid initialization of reference of type .const char ....... from expression of type .const char8_t ...." "char8_t" }
+const char8_t (&rca3)[2] = "x"; // { dg-error "invalid initialization of reference of type .const char8_t ....... from expression of type .const char ...." "char8_t" }
+const char8_t (&rca4)[2] = u8"x";
+const char8_t (&rca5)[2] = u"x"; // { dg-error "invalid initialization of reference of type .const char8_t ....... from expression of type .const char16_t ...." "char8_t" }
+
+char ca1[] = "x";
+char ca2[] = u8"x"; // { dg-error "from a string literal with type array of .char8_t." "char8_t" }
+char8_t ca3[] = "x"; // { dg-error "from a string literal with type array of .char." "char8_t" }
+char8_t ca4[] = u8"x";
+char8_t ca5[] = u"x"; // { dg-error "from a string literal with type array of .char16_t." "char8_t" }
+
+signed char sca1[] = "x";
+signed char sca2[] = u8"x"; // { dg-error "from a string literal with type array of .char8_t." "char8_t" }
+
+unsigned char uca1[] = "x";
+unsigned char uca2[] = u8"x"; // { dg-error "from a string literal with type array of .char8_t." "char8_t" }
--- /dev/null
+// Test that char8_t is not a keyword if -fchar8_t is not enabled.
+// { dg-do compile }
+// { dg-options "-fno-char8_t" }
+
+int char8_t;
--- /dev/null
+// Test that char8_t is recognized as a keyword if -fchar8_t is enabled.
+// { dg-do compile }
+// { dg-options "-fchar8_t" }
+
+int char8_t; /* { dg-error "multiple types in one declaration|declaration does not declare anything" "char8_t" } */
--- /dev/null
+// Test for unsignedness and that the max limit of char8_t is at least 0xFF
+// when -fchar8_t is enabled.
+// { dg-do compile }
+// { dg-options "-std=c++17 -fchar8_t" }
+
+static_assert(u8'\xFF' == 0xFF, "Error");
+static_assert(u8"\xFF"[0] == 0xFF, "Error");
+static_assert(char8_t(-1) >= 0, "Error");
+static_assert(char8_t{-1} >= 0, "Error"); // { dg-error "narrowing conversion of .-1. from .int. to .char8_t." "char8_t" }
--- /dev/null
+// Test overloading for UTF-8 literals when -fchar8_t is not in effect.
+// { dg-do compile }
+// { dg-options "-std=c++17 -fno-char8_t" }
+
+template<typename T1, typename T2>
+ struct is_same
+ { static const bool value = false; };
+
+template<typename T>
+ struct is_same<T, T>
+ { static const bool value = true; };
+
+int fc(char);
+long fc(unsigned char);
+static_assert(is_same<decltype(fc('x')), int>::value, "Error");
+static_assert(is_same<decltype(fc(u8'x')), int>::value, "Error");
+
+int fs(const char*);
+long fs(const unsigned char*);
+static_assert(is_same<decltype(fs("x")), int>::value, "Error");
+static_assert(is_same<decltype(fs(u8"x")), int>::value, "Error");
+
+int fr(const char(&)[2]);
+long fr(const unsigned char(&)[2]);
+static_assert(is_same<decltype(fr("x")), int>::value, "Error");
+static_assert(is_same<decltype(fr(u8"x")), int>::value, "Error");
--- /dev/null
+// Test overloading for UTF-8 literals when -fchar8_t is in effect.
+// { dg-do compile }
+// { dg-options "-std=c++17 -fchar8_t" }
+
+template<typename T1, typename T2>
+ struct is_same
+ { static const bool value = false; };
+
+template<typename T>
+ struct is_same<T, T>
+ { static const bool value = true; };
+
+int fc(char);
+long fc(char8_t);
+static_assert(is_same<decltype(fc('x')), int>::value, "Error");
+static_assert(is_same<decltype(fc(u8'x')), long>::value, "Error");
+
+int fs(const char*);
+long fs(const char8_t*);
+static_assert(is_same<decltype(fs("x")), int>::value, "Error");
+static_assert(is_same<decltype(fs(u8"x")), long>::value, "Error");
+
+int fr(const char(&)[2]);
+long fr(const char8_t(&)[2]);
+static_assert(is_same<decltype(fr("x")), int>::value, "Error");
+static_assert(is_same<decltype(fr(u8"x")), long>::value, "Error");
--- /dev/null
+// Test that char8_t related predefined macros are not present when -fchar8_t is
+// not enabled.
+// { dg-do compile }
+// { dg-options "-fno-char8_t" }
+
+#if defined(__CHAR8_TYPE__)
+#error __CHAR8_TYPE__ is defined!
+#endif
+
+#if defined(__GCC_ATOMIC_CHAR8_T_LOCK_FREE)
+#error __GCC_ATOMIC_CHAR8_T_LOCK_FREE is defined!
+#endif
--- /dev/null
+// Test that char8_t related predefined macros are present when -fchar8_t is
+// enabled.
+// { dg-do compile }
+// { dg-options "-fchar8_t" }
+
+#if !defined(__CHAR8_TYPE__)
+#error __CHAR8_TYPE__ is not defined!
+#endif
+
+#if !defined(__GCC_ATOMIC_CHAR8_T_LOCK_FREE)
+#error __GCC_ATOMIC_CHAR8_T_LOCK_FREE is not defined!
+#endif
--- /dev/null
+// Test sizeof for char8_t.
+// { dg-do compile }
+// { dg-options "-std=c++17 -fchar8_t" }
+
+static_assert(sizeof(u8'x') == 1);
+static_assert(sizeof(char8_t) == 1);
+static_assert(sizeof(__CHAR8_TYPE__) == 1);
--- /dev/null
+// Test specialization for UTF-8 literals when -fchar8_t is not enabled.
+// { dg-do compile }
+// { dg-options "-std=c++17 -fno-char8_t" }
+
+template<auto> struct ct { static constexpr int dm = 1; };
+template<> struct ct<'x'> { static constexpr int dm = 2; };
+static_assert(ct<'x'>::dm == 2, "Error");
+static_assert(ct<u8'x'>::dm == 2, "Error");
--- /dev/null
+// Test specialization for UTF-8 literals when -fchar8_t is enabled.
+// { dg-do compile }
+// { dg-options "-std=c++17 -fchar8_t" }
+
+template<auto> struct ct { static constexpr int dm = 1; };
+template<> struct ct<'x'> { static constexpr int dm = 2; };
+template<> struct ct<u8'x'> { static constexpr int dm = 3; };
+static_assert(ct<'x'>::dm == 2, "Error");
+static_assert(ct<u8'x'>::dm == 3, "Error");
+
+template<typename T, const T *> struct ct2 { static constexpr int dm = 4; };
+template<const char *P> struct ct2<char,P> { static constexpr int dm = 5; };
+template<const char8_t *P> struct ct2<char8_t,P> { static constexpr int dm = 6; };
+constexpr const char s[] = "x";
+constexpr const char8_t s8[] = u8"x";
+static_assert(ct2<char,s>::dm == 5, "Error");
+static_assert(ct2<char8_t,s8>::dm == 6, "Error");
--- /dev/null
+// Test that UTF-8 string literals have type const char[] if -fchar8_t is not enabled.
+// { dg-do compile { target c++11 } }
+// { dg-options "-fno-char8_t" }
+
+template<typename T1, typename T2>
+ struct is_same
+ { static const bool value = false; };
+template<typename T>
+ struct is_same<T, T>
+ { static const bool value = true; };
+
+static_assert(is_same<decltype(u8""), const char(&)[1]>::value, "Error");
--- /dev/null
+// Test that UTF-8 string literals have type const char8_t[] if -fchar8_t is enabled.
+// { dg-do compile { target c++11 } }
+// { dg-options "-fchar8_t" }
+
+template<typename T1, typename T2>
+ struct is_same
+ { static const bool value = false; };
+template<typename T>
+ struct is_same<T, T>
+ { static const bool value = true; };
+
+static_assert(is_same<decltype(u8""), const char8_t(&)[1]>::value, "Error");
--- /dev/null
+// Test that char8_t is not a type specifier if -fchar8_t is not enabled.
+// { dg-do compile }
+// { dg-options "-fno-char8_t" }
+
+char8_t c8; /* { dg-error ".char8_t. does not name a type" "no-char8_t" } */
--- /dev/null
+// Test that char8_t is recognized as a type specifier if -fchar8_t is enabled.
+// { dg-do compile }
+// { dg-options "-fchar8_t" }
+
+char8_t c8;
+
+signed char8_t sc8; /* { dg-error "signed" } */
+unsigned char8_t uc8; /* { dg-error "unsigned" } */
+
+short char8_t shc8; /* { dg-error "short" } */
+long char8_t lgc8; /* { dg-error "long" } */
+
+signed short char8_t ssc8; /* { dg-error "signed" } */
+signed long char8_t slc8; /* { dg-error "signed" } */
+unsigned short char8_t usc8; /* { dg-error "unsigned" } */
+unsigned long char8_t ulc8; /* { dg-error "unsigned" } */
--- /dev/null
+// Test that no error is issued for attempted char8_t typedef declarations
+// when -fchar8_t is not enabled.
+// { dg-do compile }
+// { dg-options "-fno-char8_t" }
+
+typedef unsigned char char8_t;
--- /dev/null
+// Test that an error is issued for attempted char8_t typedef declarations
+// when -fchar8_t is enabled.
+// { dg-do compile }
+// { dg-options "-fchar8_t" }
+
+typedef unsigned char char8_t; // { dg-error "redeclaration" }
--- /dev/null
+// Test overloading for UTF-8 user defined literals when -fchar8_t is not in effect.
+// { dg-do compile }
+// { dg-options "-std=c++17 -fno-char8_t" }
+
+template<typename T1, typename T2>
+ struct is_same
+ { static const bool value = false; };
+
+template<typename T>
+ struct is_same<T, T>
+ { static const bool value = true; };
+
+int operator "" _udcl(char);
+static_assert(is_same<decltype('x'_udcl), int>::value, "Error");
+static_assert(is_same<decltype(u8'x'_udcl), int>::value, "Error");
+
+int operator "" _udsl(const char*, __SIZE_TYPE__);
+static_assert(is_same<decltype("x"_udsl), int>::value, "Error");
+static_assert(is_same<decltype(u8"x"_udsl), int>::value, "Error");
--- /dev/null
+// Test overloading for UTF-8 user defined literals when -fchar8_t is in effect.
+// { dg-do compile }
+// { dg-options "-std=c++17 -fchar8_t" }
+
+template<typename T1, typename T2>
+ struct is_same
+ { static const bool value = false; };
+
+template<typename T>
+ struct is_same<T, T>
+ { static const bool value = true; };
+
+int operator "" _udcl(char);
+long operator "" _udcl(char8_t);
+static_assert(is_same<decltype('x'_udcl), int>::value, "Error");
+static_assert(is_same<decltype(u8'x'_udcl), long>::value, "Error");
+
+int operator "" _udsl(const char*, __SIZE_TYPE__);
+long operator "" _udsl(const char8_t*, __SIZE_TYPE__);
+static_assert(is_same<decltype("x"_udsl), int>::value, "Error");
+static_assert(is_same<decltype(u8"x"_udsl), long>::value, "Error");
/* { dg-do compile { target c++11 } } */
/* { dg-options "-fshort-wchar" } */
+#if __cpp_char8_t
+typedef char8_t u8_char_t;
+#else
+typedef char u8_char_t;
+#endif
+
const char s_0[] = "ab";
-const char s_1[] = u"ab"; /* { dg-error "from wide string" } */
-const char s_2[] = U"ab"; /* { dg-error "from wide string" } */
-const char s_3[] = L"ab"; /* { dg-error "from wide string" } */
+const char s_1[] = u"ab"; /* { dg-error "from a string literal with type array of .char16_t." } */
+const char s_2[] = U"ab"; /* { dg-error "from a string literal with type array of .char32_t." } */
+const char s_3[] = L"ab"; /* { dg-error "from a string literal with type array of .wchar_t." } */
+const u8_char_t s_4[] = u8"ab";
-const char16_t s16_0[] = "ab"; /* { dg-error "from non-wide" } */
+const char16_t s16_0[] = "ab"; /* { dg-error "from a string literal with type array of .char." } */
const char16_t s16_1[] = u"ab";
-const char16_t s16_2[] = U"ab"; /* { dg-error "from incompatible" } */
-const char16_t s16_3[] = L"ab"; /* { dg-error "from incompatible" } */
+const char16_t s16_2[] = U"ab"; /* { dg-error "from a string literal with type array of .char32_t." } */
+const char16_t s16_3[] = L"ab"; /* { dg-error "from a string literal with type array of .wchar_t." } */
+const char16_t s16_4[] = u8"ab"; /* { dg-error "from a string literal with type array of .char." } */
-const char16_t s16_4[0] = u"ab"; /* { dg-error "chars is too long" } */
-const char16_t s16_5[1] = u"ab"; /* { dg-error "chars is too long" } */
-const char16_t s16_6[2] = u"ab"; /* { dg-error "chars is too long" } */
-const char16_t s16_7[3] = u"ab";
-const char16_t s16_8[4] = u"ab";
+const char16_t s16_5[0] = u"ab"; /* { dg-error "chars is too long" } */
+const char16_t s16_6[1] = u"ab"; /* { dg-error "chars is too long" } */
+const char16_t s16_7[2] = u"ab"; /* { dg-error "chars is too long" } */
+const char16_t s16_8[3] = u"ab";
+const char16_t s16_9[4] = u"ab";
-const char32_t s32_0[] = "ab"; /* { dg-error "from non-wide" } */
-const char32_t s32_1[] = u"ab"; /* { dg-error "from incompatible" } */
+const char32_t s32_0[] = "ab"; /* { dg-error "from a string literal with type array of .char." } */
+const char32_t s32_1[] = u"ab"; /* { dg-error "from a string literal with type array of .char16_t." } */
const char32_t s32_2[] = U"ab";
-const char32_t s32_3[] = L"ab"; /* { dg-error "from incompatible" } */
+const char32_t s32_3[] = L"ab"; /* { dg-error "from a string literal with type array of .wchar_t." } */
+const char32_t s32_4[] = u8"ab"; /* { dg-error "from a string literal with type array of .char." } */
-const char32_t s32_4[0] = U"ab"; /* { dg-error "chars is too long" } */
-const char32_t s32_5[1] = U"ab"; /* { dg-error "chars is too long" } */
-const char32_t s32_6[2] = U"ab"; /* { dg-error "chars is too long" } */
-const char32_t s32_7[3] = U"ab";
-const char32_t s32_8[4] = U"ab";
+const char32_t s32_5[0] = U"ab"; /* { dg-error "chars is too long" } */
+const char32_t s32_6[1] = U"ab"; /* { dg-error "chars is too long" } */
+const char32_t s32_7[2] = U"ab"; /* { dg-error "chars is too long" } */
+const char32_t s32_8[3] = U"ab";
+const char32_t s32_9[4] = U"ab";
-const wchar_t sw_0[] = "ab"; /* { dg-error "from non-wide" } */
-const wchar_t sw_1[] = u"ab"; /* { dg-error "from incompatible" } */
-const wchar_t sw_2[] = U"ab"; /* { dg-error "from incompatible" } */
+const wchar_t sw_0[] = "ab"; /* { dg-error "from a string literal with type array of .char." } */
+const wchar_t sw_1[] = u"ab"; /* { dg-error "from a string literal with type array of .char16_t." } */
+const wchar_t sw_2[] = U"ab"; /* { dg-error "from a string literal with type array of .char32_t." } */
const wchar_t sw_3[] = L"ab";
+const wchar_t sw_4[] = u8"ab"; /* { dg-error "from a string literal with type array of .char." } */
/* { dg-do compile { target c++11 } } */
// { dg-options "" }
+#if __cpp_char8_t
+typedef char8_t u8_char_t;
+#else
+typedef char u8_char_t;
+#endif
+
const char s_0[] = "ab";
-const char s_1[] = u"ab"; /* { dg-error "from wide string" } */
-const char s_2[] = U"ab"; /* { dg-error "from wide string" } */
-const char s_3[] = L"ab"; /* { dg-error "from wide string" } */
+const char s_1[] = u"ab"; /* { dg-error "from a string literal with type array of .char16_t." } */
+const char s_2[] = U"ab"; /* { dg-error "from a string literal with type array of .char32_t." } */
+const char s_3[] = L"ab"; /* { dg-error "from a string literal with type array of .wchar_t." } */
+const u8_char_t s_4[] = u8"ab";
-const char16_t s16_0[] = "ab"; /* { dg-error "from non-wide" } */
+const char16_t s16_0[] = "ab"; /* { dg-error "from a string literal with type array of .char." } */
const char16_t s16_1[] = u"ab";
-const char16_t s16_2[] = U"ab"; /* { dg-error "from incompatible" } */
-const char16_t s16_3[] = L"ab"; /* { dg-error "from incompatible" } */
+const char16_t s16_2[] = U"ab"; /* { dg-error "from a string literal with type array of .char32_t." } */
+const char16_t s16_3[] = L"ab"; /* { dg-error "from a string literal with type array of .wchar_t." } */
+const char16_t s16_4[] = u8"ab"; /* { dg-error "from a string literal with type array of .char." } */
-const char16_t s16_4[0] = u"ab"; /* { dg-error "chars is too long" } */
-const char16_t s16_5[1] = u"ab"; /* { dg-error "chars is too long" } */
-const char16_t s16_6[2] = u"ab"; /* { dg-error "chars is too long" } */
-const char16_t s16_7[3] = u"ab";
-const char16_t s16_8[4] = u"ab";
+const char16_t s16_5[0] = u"ab"; /* { dg-error "chars is too long" } */
+const char16_t s16_6[1] = u"ab"; /* { dg-error "chars is too long" } */
+const char16_t s16_7[2] = u"ab"; /* { dg-error "chars is too long" } */
+const char16_t s16_8[3] = u"ab";
+const char16_t s16_9[4] = u"ab";
-const char32_t s32_0[] = "ab"; /* { dg-error "from non-wide" } */
-const char32_t s32_1[] = u"ab"; /* { dg-error "from incompatible" } */
+const char32_t s32_0[] = "ab"; /* { dg-error "from a string literal with type array of .char." } */
+const char32_t s32_1[] = u"ab"; /* { dg-error "from a string literal with type array of .char16_t." } */
const char32_t s32_2[] = U"ab";
-const char32_t s32_3[] = L"ab"; /* { dg-error "from incompatible" } */
+const char32_t s32_3[] = L"ab"; /* { dg-error "from a string literal with type array of .wchar_t." } */
+const char32_t s32_4[] = u8"ab"; /* { dg-error "from a string literal with type array of .char." } */
-const char32_t s32_4[0] = U"ab"; /* { dg-error "chars is too long" } */
-const char32_t s32_5[1] = U"ab"; /* { dg-error "chars is too long" } */
-const char32_t s32_6[2] = U"ab"; /* { dg-error "chars is too long" } */
-const char32_t s32_7[3] = U"ab";
-const char32_t s32_8[4] = U"ab";
+const char32_t s32_5[0] = U"ab"; /* { dg-error "chars is too long" } */
+const char32_t s32_6[1] = U"ab"; /* { dg-error "chars is too long" } */
+const char32_t s32_7[2] = U"ab"; /* { dg-error "chars is too long" } */
+const char32_t s32_8[3] = U"ab";
+const char32_t s32_9[4] = U"ab";
-const wchar_t sw_0[] = "ab"; /* { dg-error "from non-wide" } */
-const wchar_t sw_1[] = u"ab"; /* { dg-error "from incompatible" } */
-const wchar_t sw_2[] = U"ab"; /* { dg-error "from incompatible" } */
+const wchar_t sw_0[] = "ab"; /* { dg-error "from a string literal with type array of .char." } */
+const wchar_t sw_1[] = u"ab"; /* { dg-error "from a string literal with type array of .char16_t." } */
+const wchar_t sw_2[] = U"ab"; /* { dg-error "from a string literal with type array of .char32_t." } */
const wchar_t sw_3[] = L"ab";
+const wchar_t sw_4[] = u8"ab"; /* { dg-error "from a string literal with type array of .char." } */
--- /dev/null
+/* Contributed by Kris Van Hees <kris.van.hees@oracle.com> */
+/* Test the char8_t promotion rules. */
+/* { dg-do compile { target c++11 } } */
+/* { dg-options "-fchar8_t -Wall -Wconversion -Wsign-conversion -Wsign-promo" } */
+
+extern void f_c (char);
+extern void fsc (signed char);
+extern void fuc (unsigned char);
+extern void f_s (short);
+extern void fss (signed short);
+extern void fus (unsigned short);
+extern void f_i (int);
+extern void fsi (signed int);
+extern void fui (unsigned int);
+extern void f_l (long);
+extern void fsl (signed long);
+extern void ful (unsigned long);
+extern void f_ll (long long);
+extern void fsll (signed long long);
+extern void full (unsigned long long);
+
+void m(char8_t c)
+{
+ f_c (c); /* { dg-warning "change the sign" } */
+ fsc (c); /* { dg-warning "change the sign" } */
+ fuc (c);
+ f_s (c);
+ fss (c);
+ fus (c);
+ f_i (c);
+ fsi (c);
+ fui (c);
+ f_l (c);
+ fsl (c);
+ ful (c);
+ f_ll (c);
+ fsll (c);
+ full (c);
+}
/* Contributed by Kris Van Hees <kris.van.hees@oracle.com> */
/* Expected errors for char16_t/char32_t in c++98. */
-/* Ensure u and U prefixes are parsed as separate tokens in c++98. */
+/* Ensure u8, u and U prefixes are parsed as separate tokens in c++98. */
/* { dg-do compile } */
/* { dg-options "-std=c++98" } */
const static char16_t c0 = 'a'; /* { dg-error "not name a type" } */
const static char32_t c1 = 'a'; /* { dg-error "not name a type" } */
-const unsigned short c2 = u'a'; /* { dg-error "not declared" } */
-const unsigned long c3 = U'a'; /* { dg-error "not declared" } */
+const unsigned short c2 = u'a'; /* { dg-error "not declared" } */
+const unsigned long c3 = U'a'; /* { dg-error "not declared" } */
+const unsigned char c4 = u8'a'; /* { dg-error "not declared" } */
#define u 1 +
#define U 2 +
+#define u8 3 +
const unsigned short c5 = u'a';
const unsigned long c6 = U'a';
+const unsigned char c7 = u8'a';
#undef u
#undef U
+#undef u8
#define u "a"
#define U "b"
+#define u8 "c"
const void *s0 = u"a";
const void *s1 = U"a";
+const void *s2 = u8"a";
int main () {}
/* Contributed by Kris Van Hees <kris.van.hees@oracle.com> */
/* Expected errors for char16_t/char32_t in default std. */
-/* Ensure u and U prefixes are parsed as separate tokens in default std. */
+/* Ensure u8, u and U prefixes are parsed as separate tokens in default std. */
/* { dg-do compile } */
/* { dg-options "-std=c++98" } */
const static char16_t c0 = 'a'; /* { dg-error "not name a type" } */
const static char32_t c1 = 'a'; /* { dg-error "not name a type" } */
-const unsigned short c2 = u'a'; /* { dg-error "not declared" } */
-const unsigned long c3 = U'a'; /* { dg-error "not declared" } */
+const unsigned short c2 = u'a'; /* { dg-error "not declared" } */
+const unsigned long c3 = U'a'; /* { dg-error "not declared" } */
+const unsigned char c4 = u8'a'; /* { dg-error "not declared" } */
#define u 1 +
#define U 2 +
+#define u8 3 +
-const unsigned short c4 = u'a';
-const unsigned long c5 = U'a';
+const unsigned short c5 = u'a';
+const unsigned long c6 = U'a';
+const unsigned char c7 = u8'a';
#undef u
#undef U
+#undef u8
#define u "a"
#define U "b"
+#define u8 "c"
const void *s0 = u"a";
const void *s1 = U"a";
+const void *s2 = u8"a";
int main () {}
/* Contributed by Kris Van Hees <kris.van.hees@oracle.com> */
/* Expected errors for char16_t/char32_t in gnu++98. */
-/* Ensure u and U prefixes are parsed as separate tokens in gnu++98. */
+/* Ensure u8, u and U prefixes are parsed as separate tokens in gnu++98. */
/* { dg-do compile } */
/* { dg-options "-std=gnu++98" } */
const static char16_t c0 = 'a'; /* { dg-error "not name a type" } */
const static char32_t c1 = 'a'; /* { dg-error "not name a type" } */
-const unsigned short c2 = u'a'; /* { dg-error "not declared" } */
-const unsigned long c3 = U'a'; /* { dg-error "not declared" } */
+const unsigned short c2 = u'a'; /* { dg-error "not declared" } */
+const unsigned long c3 = U'a'; /* { dg-error "not declared" } */
+const unsigned char c4 = u8'a'; /* { dg-error "not declared" } */
#define u 1 +
#define U 2 +
+#define u8 3 +
const unsigned short c5 = u'a';
const unsigned long c6 = U'a';
+const unsigned char c7 = u8'a';
#undef u
#undef U
+#undef u8
#define u "a"
#define U "b"
+#define u8 "c"
const void *s0 = u"a";
const void *s1 = U"a";
+const void *s2 = u8"a";
int main () {}
--- /dev/null
+/* Ensure that __CHAR8_TYPE__ exists and matches the underlying type. */
+/* { dg-do run { target c++11 } } */
+/* { dg-options "-fchar8_t -Wall -Werror" } */
+
+extern "C" void abort (void);
+
+int main ()
+{
+ if (sizeof (__CHAR8_TYPE__) != sizeof (char8_t))
+ abort();
+}
// { dg-require-iconv "ISO-8859-2" }
// { dg-options "-fexec-charset=ISO-8859-2" }
+#if __cpp_char8_t
+typedef char8_t u8_char_t;
+#else
+typedef char u8_char_t;
+#endif
+
const char *str1 = "h\u00e1\U0000010Dky ";
const char *str2 = "\u010d\u00E1rky\n";
-const char *str3 = u8"h\u00e1\U0000010Dky ";
-const char *str4 = u8"\u010d\u00E1rky\n";
+const u8_char_t *str3 = u8"h\u00e1\U0000010Dky ";
+const u8_char_t *str4 = u8"\u010d\u00E1rky\n";
const char *str5 = "h\u00e1\U0000010Dky " "\u010d\u00E1rky\n";
-const char *str6 = u8"h\u00e1\U0000010Dky " "\u010d\u00E1rky\n";
-const char *str7 = "h\u00e1\U0000010Dky " u8"\u010d\u00E1rky\n";
-#define u8
-const char *str8 = u8"h\u00e1\U0000010Dky " u8"\u010d\u00E1rky\n";
+const u8_char_t *str6 = u8"h\u00e1\U0000010Dky " "\u010d\u00E1rky\n";
+const u8_char_t *str7 = "h\u00e1\U0000010Dky " u8"\u010d\u00E1rky\n";
+const u8_char_t *str8 = u8"h\u00e1\U0000010Dky " u8"\u010d\u00E1rky\n";
const char latin2_1[] = "\x68\xe1\xe8\x6b\x79\x20";
const char latin2_2[] = "\xe8\xe1\x72\x6b\x79\n";
{
if (__builtin_strcmp (str1, latin2_1) != 0
|| __builtin_strcmp (str2, latin2_2) != 0
- || __builtin_strcmp (str3, utf8_1) != 0
- || __builtin_strcmp (str4, utf8_2) != 0
+ || __builtin_memcmp (str3, utf8_1, sizeof (utf8_1) - 1) != 0
+ || __builtin_memcmp (str4, utf8_2, sizeof (utf8_2) - 1) != 0
|| __builtin_strncmp (str5, latin2_1, sizeof (latin2_1) - 1) != 0
|| __builtin_strcmp (str5 + sizeof (latin2_1) - 1, latin2_2) != 0
- || __builtin_strncmp (str6, utf8_1, sizeof (utf8_1) - 1) != 0
- || __builtin_strcmp (str6 + sizeof (utf8_1) - 1, utf8_2) != 0
- || __builtin_strncmp (str7, utf8_1, sizeof (utf8_1) - 1) != 0
- || __builtin_strcmp (str7 + sizeof (utf8_1) - 1, utf8_2) != 0
- || __builtin_strncmp (str8, utf8_1, sizeof (utf8_1) - 1) != 0
- || __builtin_strcmp (str8 + sizeof (utf8_1) - 1, utf8_2) != 0)
+ || __builtin_memcmp (str6, utf8_1, sizeof (utf8_1) - 1) != 0
+ || __builtin_memcmp (str6 + sizeof (utf8_1) - 1, utf8_2, sizeof (utf8_2) - 1) != 0
+ || __builtin_memcmp (str7, utf8_1, sizeof (utf8_1) - 1) != 0
+ || __builtin_memcmp (str7 + sizeof (utf8_1) - 1, utf8_2, sizeof (utf8_2) - 1) != 0
+ || __builtin_memcmp (str8, utf8_1, sizeof (utf8_1) - 1) != 0
+ || __builtin_memcmp (str8 + sizeof (utf8_1) - 1, utf8_2, sizeof (utf8_2) - 1) != 0)
__builtin_abort ();
if (sizeof ("a" u8"b"[0]) != 1
|| sizeof (u8"a" "b"[0]) != 1
// { dg-do compile { target c++11 } }
// { dg-options "" }
-const char s0[] = u8"ab";
-const char16_t s1[] = u8"ab"; // { dg-error "from non-wide" }
-const char32_t s2[] = u8"ab"; // { dg-error "from non-wide" }
-const wchar_t s3[] = u8"ab"; // { dg-error "from non-wide" }
+#if __cpp_char8_t
+typedef char8_t u8_char_t;
+#else
+typedef char u8_char_t;
+#endif
-const char t0[0] = u8"ab"; // { dg-error "chars is too long" }
-const char t1[1] = u8"ab"; // { dg-error "chars is too long" }
-const char t2[2] = u8"ab"; // { dg-error "chars is too long" }
-const char t3[3] = u8"ab";
-const char t4[4] = u8"ab";
+const u8_char_t s0[] = u8"ab";
+const char16_t s1[] = u8"ab"; // { dg-error "from a string literal with type array of .char." }
+const char32_t s2[] = u8"ab"; // { dg-error "from a string literal with type array of .char." }
+const wchar_t s3[] = u8"ab"; // { dg-error "from a string literal with type array of .char." }
-const char u0[0] = u8"\u2160."; // { dg-error "chars is too long" }
-const char u1[1] = u8"\u2160."; // { dg-error "chars is too long" }
-const char u2[2] = u8"\u2160."; // { dg-error "chars is too long" }
-const char u3[3] = u8"\u2160."; // { dg-error "chars is too long" }
-const char u4[4] = u8"\u2160."; // { dg-error "chars is too long" }
-const char u5[5] = u8"\u2160.";
-const char u6[6] = u8"\u2160.";
+const u8_char_t t0[0] = u8"ab"; // { dg-error "chars is too long" }
+const u8_char_t t1[1] = u8"ab"; // { dg-error "chars is too long" }
+const u8_char_t t2[2] = u8"ab"; // { dg-error "chars is too long" }
+const u8_char_t t3[3] = u8"ab";
+const u8_char_t t4[4] = u8"ab";
+
+const u8_char_t u0[0] = u8"\u2160."; // { dg-error "chars is too long" }
+const u8_char_t u1[1] = u8"\u2160."; // { dg-error "chars is too long" }
+const u8_char_t u2[2] = u8"\u2160."; // { dg-error "chars is too long" }
+const u8_char_t u3[3] = u8"\u2160."; // { dg-error "chars is too long" }
+const u8_char_t u4[4] = u8"\u2160."; // { dg-error "chars is too long" }
+const u8_char_t u5[5] = u8"\u2160.";
+const u8_char_t u6[6] = u8"\u2160.";
// { dg-do compile { target c++11 } }
+// { dg-skip-if "char8_t" { c++2a } }
/* { dg-options "-Wformat -fdiagnostics-show-caret" } */
/* C++11-specific format tests. */
+2019-01-14 Tom Honermann <tom@honermann.net>
+
+ * cp-demangle.c (cplus_demangle_builtin_types)
+ (cplus_demangle_type): Add name demangling for char8_t (Du).
+ * cp-demangle.h: Increase D_BUILTIN_TYPE_COUNT to accommodate the
+ new char8_t type.
+
2019-01-09 Sandra Loosemore <sandra@codesourcery.com>
PR other/16615
/* 27 */ { NL ("decimal64"), NL ("decimal64"), D_PRINT_DEFAULT },
/* 28 */ { NL ("decimal128"), NL ("decimal128"), D_PRINT_DEFAULT },
/* 29 */ { NL ("half"), NL ("half"), D_PRINT_FLOAT },
- /* 30 */ { NL ("char16_t"), NL ("char16_t"), D_PRINT_DEFAULT },
- /* 31 */ { NL ("char32_t"), NL ("char32_t"), D_PRINT_DEFAULT },
- /* 32 */ { NL ("decltype(nullptr)"), NL ("decltype(nullptr)"),
+ /* 30 */ { NL ("char8_t"), NL ("char8_t"), D_PRINT_DEFAULT },
+ /* 31 */ { NL ("char16_t"), NL ("char16_t"), D_PRINT_DEFAULT },
+ /* 32 */ { NL ("char32_t"), NL ("char32_t"), D_PRINT_DEFAULT },
+ /* 33 */ { NL ("decltype(nullptr)"), NL ("decltype(nullptr)"),
D_PRINT_DEFAULT },
};
ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[29]);
di->expansion += ret->u.s_builtin.type->len;
break;
+ case 'u':
+ /* char8_t */
+ ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[30]);
+ di->expansion += ret->u.s_builtin.type->len;
+ break;
case 's':
/* char16_t */
- ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[30]);
+ ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[31]);
di->expansion += ret->u.s_builtin.type->len;
break;
case 'i':
/* char32_t */
- ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[31]);
+ ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[32]);
di->expansion += ret->u.s_builtin.type->len;
break;
case 'n':
/* decltype(nullptr) */
- ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[32]);
+ ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[33]);
di->expansion += ret->u.s_builtin.type->len;
break;
extern const struct demangle_operator_info cplus_demangle_operators[];
#endif
-#define D_BUILTIN_TYPE_COUNT (33)
+#define D_BUILTIN_TYPE_COUNT (34)
CP_STATIC_IF_GLIBCPP_V3
const struct demangle_builtin_type_info