Implement P0482R5, char8_t: A type for UTF-8 characters and strings

gcc/cp/
	* 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.
gcc/c-family/
	* 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.
libiberty/
	* 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.

From-SVN: r267923
This commit is contained in:
Tom Honermann 2019-01-14 19:55:51 +00:00 committed by Jason Merrill
parent 23db6ced33
commit 2d91f79dc9
74 changed files with 1132 additions and 142 deletions

View file

@ -1,3 +1,7 @@
2019-01-14 Tom Honermann <tom@honermann.net>
* defaults.h: Define CHAR8_TYPE.
2019-01-14 Martin Sebor <msebor@redhat.com>
PR target/88638

View file

@ -1,3 +1,27 @@
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

View file

@ -79,6 +79,7 @@ machine_mode c_default_pointer_mode = VOIDmode;
tree signed_char_type_node;
tree wchar_type_node;
tree char8_type_node;
tree char16_type_node;
tree char32_type_node;
@ -128,6 +129,11 @@ machine_mode c_default_pointer_mode = VOIDmode;
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.
@ -452,6 +458,7 @@ const struct c_common_resword c_common_reswords[] =
{ "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 },
@ -748,6 +755,11 @@ fix_string_type (tree value)
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;
@ -828,7 +840,8 @@ fix_string_type (tree value)
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. */
@ -3640,8 +3653,12 @@ c_common_get_alias_set (tree t)
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)
@ -4050,6 +4067,7 @@ c_get_ident (const char *id)
void
c_common_nodes_and_builtins (void)
{
int char8_type_size;
int char16_type_size;
int char32_type_size;
int wchar_type_size;
@ -4341,6 +4359,22 @@ c_common_nodes_and_builtins (void)
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));
@ -5138,6 +5172,8 @@ c_stddef_cpp_builtins(void)
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)
@ -7856,6 +7892,7 @@ keyword_begins_type_specifier (enum rid keyword)
case RID_ACCUM:
case RID_BOOL:
case RID_WCHAR:
case RID_CHAR8:
case RID_CHAR16:
case RID_CHAR32:
case RID_SAT:

View file

@ -180,6 +180,9 @@ enum rid
/* C++11 */
RID_CONSTEXPR, RID_DECLTYPE, RID_NOEXCEPT, RID_NULLPTR, RID_STATIC_ASSERT,
/* char8_t */
RID_CHAR8,
/* C++ concepts */
RID_CONCEPT, RID_REQUIRES,
@ -287,6 +290,7 @@ extern GTY ((length ("(int) RID_MAX"))) tree *ridpointers;
enum c_tree_index
{
CTI_CHAR8_TYPE,
CTI_CHAR16_TYPE,
CTI_CHAR32_TYPE,
CTI_WCHAR_TYPE,
@ -330,6 +334,7 @@ enum c_tree_index
CTI_UINTPTR_TYPE,
CTI_CHAR_ARRAY_TYPE,
CTI_CHAR8_ARRAY_TYPE,
CTI_CHAR16_ARRAY_TYPE,
CTI_CHAR32_ARRAY_TYPE,
CTI_WCHAR_ARRAY_TYPE,
@ -409,20 +414,22 @@ extern machine_mode c_default_pointer_mode;
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[];
@ -430,6 +437,7 @@ 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]
@ -475,6 +483,7 @@ extern const unsigned int num_c_common_reswords;
#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]

View file

@ -702,6 +702,9 @@ cpp_atomic_builtins (cpp_reader *pfile)
(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",
@ -1000,6 +1003,8 @@ c_cpp_builtins (cpp_reader *pfile)
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. */

View file

@ -1281,9 +1281,14 @@ lex_string (const cpp_token *tok, tree *valp, bool objc_string, bool translate)
{
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;
@ -1323,7 +1328,12 @@ lex_charconst (const cpp_token *token)
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)

View file

@ -996,6 +996,10 @@ c_common_post_options (const char **pfilename)
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)

View file

@ -1300,6 +1300,11 @@ fcanonical-system-headers
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.

View file

@ -1,3 +1,28 @@
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

View file

@ -7488,6 +7488,7 @@ extern tree store_init_value (tree, tree, vec<tree, va_gc>**, int);
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);

View file

@ -1877,6 +1877,7 @@ type_promotes_to (tree type)
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)

View file

@ -10770,7 +10770,9 @@ grokdeclarator (const cp_declarator *declarator,
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);

View file

@ -233,6 +233,8 @@ init_reswords (void)
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)

View file

@ -2473,10 +2473,12 @@ write_builtin_type (tree type)
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)

View file

@ -948,6 +948,7 @@ cp_keyword_starts_decl_specifier_p (enum rid keyword)
case RID_TYPENAME:
/* Simple type specifiers. */
case RID_CHAR:
case RID_CHAR8:
case RID_CHAR16:
case RID_CHAR32:
case RID_WCHAR:
@ -4235,9 +4236,14 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok,
{
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;
@ -17504,6 +17510,9 @@ cp_parser_simple_type_specifier (cp_parser* parser,
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;
@ -28919,14 +28928,15 @@ cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs,
{
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)

View file

@ -1539,7 +1539,7 @@ emit_support_tinfos (void)
{
&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,

View file

@ -5022,6 +5022,7 @@ char_type_p (tree type)
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));

View file

@ -2216,6 +2216,7 @@ string_conv_p (const_tree totype, const_tree exp, int warn)
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))
@ -10288,6 +10289,7 @@ check_literal_operator_args (const_tree decl,
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))
{
@ -10320,6 +10322,8 @@ check_literal_operator_args (const_tree decl,
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))

View file

@ -1026,6 +1026,17 @@ check_narrowing (tree type, tree init, tsubst_flags_t complain, bool const_only)
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.
@ -1091,36 +1102,30 @@ digest_init_r (tree type, tree init, int nested, int flags,
&& 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))

View file

@ -583,6 +583,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
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

View file

@ -206,7 +206,7 @@ in the following sections.
@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
@ -2426,6 +2426,60 @@ but few users will need to override the default of
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

View file

@ -62,6 +62,47 @@ const char s16[] = R"??(??)??";
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)#[{}]^|~";
)??=??";
@ -211,6 +252,25 @@ main (void)
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");

View file

@ -62,6 +62,47 @@ const char s16[] = R"??(??)??";
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)#[{}]^|~";
)??=??";
@ -211,6 +252,25 @@ main (void)
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");

View file

@ -4,3 +4,4 @@
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" }

View file

@ -0,0 +1,81 @@
// { 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" }

View file

@ -0,0 +1,38 @@
// { 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);
}

View file

@ -9,6 +9,14 @@ operator"" _len(const char*, size_type len)
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)
{

View file

@ -7,7 +7,9 @@
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;

View file

@ -8,6 +8,12 @@ inline namespace my_string_literals
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}; }

View file

@ -1,7 +1,9 @@
// { 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;

View file

@ -6,7 +6,11 @@
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];

View file

@ -0,0 +1,5 @@
// P0482R6
// { dg-do compile }
// { dg-options "-std=c++2a" }
char8_t c8;

View file

@ -0,0 +1,5 @@
// P0482R6
// { dg-do compile }
// { dg-options "-std=c++2a -fno-char8_t" }
char8_t c8; // { dg-error "does not name a type" }

View file

@ -471,3 +471,11 @@
#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

View file

@ -0,0 +1,8 @@
// 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" }
}

View file

@ -0,0 +1,12 @@
// 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");

View file

@ -0,0 +1,12 @@
// 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");

View file

@ -0,0 +1,30 @@
// 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");

View file

@ -0,0 +1,30 @@
// 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");

View file

@ -0,0 +1,8 @@
// 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

View file

@ -0,0 +1,10 @@
// 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

View file

@ -0,0 +1,21 @@
// 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";

View file

@ -0,0 +1,33 @@
// 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" }

View file

@ -0,0 +1,5 @@
// 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;

View file

@ -0,0 +1,5 @@
// 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" } */

View file

@ -0,0 +1,9 @@
// 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" }

View file

@ -0,0 +1,26 @@
// 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");

View file

@ -0,0 +1,26 @@
// 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");

View file

@ -0,0 +1,12 @@
// 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

View file

@ -0,0 +1,12 @@
// 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

View file

@ -0,0 +1,7 @@
// 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);

View file

@ -0,0 +1,8 @@
// 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");

View file

@ -0,0 +1,17 @@
// 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");

View file

@ -0,0 +1,12 @@
// 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");

View file

@ -0,0 +1,12 @@
// 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");

View file

@ -0,0 +1,5 @@
// 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" } */

View file

@ -0,0 +1,16 @@
// 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" } */

View file

@ -0,0 +1,6 @@
// 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;

View file

@ -0,0 +1,6 @@
// 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" }

View file

@ -0,0 +1,19 @@
// 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");

View file

@ -0,0 +1,21 @@
// 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");

View file

@ -3,34 +3,44 @@
/* { 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." } */

View file

@ -3,34 +3,44 @@
/* { 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." } */

View file

@ -0,0 +1,39 @@
/* 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);
}

View file

@ -1,27 +1,33 @@
/* 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 () {}

View file

@ -1,27 +1,33 @@
/* 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 () {}

View file

@ -1,27 +1,33 @@
/* 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 () {}

View file

@ -0,0 +1,11 @@
/* 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();
}

View file

@ -2,15 +2,20 @@
// { 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";
@ -22,16 +27,16 @@ main (void)
{
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

View file

@ -1,21 +1,27 @@
// { 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.";

View file

@ -1,4 +1,5 @@
// { dg-do compile { target c++11 } }
// { dg-skip-if "char8_t" { c++2a } }
/* { dg-options "-Wformat -fdiagnostics-show-caret" } */
/* C++11-specific format tests. */

View file

@ -1,3 +1,10 @@
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

View file

@ -2364,9 +2364,10 @@ cplus_demangle_builtin_types[D_BUILTIN_TYPE_COUNT] =
/* 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 },
};
@ -2654,14 +2655,19 @@ cplus_demangle_type (struct d_info *di)
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;
@ -2687,7 +2693,7 @@ cplus_demangle_type (struct d_info *di)
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;

View file

@ -176,7 +176,7 @@ d_advance (struct d_info *di, int i)
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