aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorKris Van Hees <kris.van.hees@oracle.com>2008-04-18 13:58:08 +0000
committerJason Merrill <jason@gcc.gnu.org>2008-04-18 09:58:08 -0400
commitb6baa67d7947f7e4fc1481c87fcb55d54c56f0cf (patch)
tree7a2e1b1d5ba3460de2699e7cd1bc2b1739fc3119 /gcc
parent14a8726b8a54cf83654426302e4fe91877cad971 (diff)
downloadgcc-b6baa67d7947f7e4fc1481c87fcb55d54c56f0cf.zip
gcc-b6baa67d7947f7e4fc1481c87fcb55d54c56f0cf.tar.gz
gcc-b6baa67d7947f7e4fc1481c87fcb55d54c56f0cf.tar.bz2
cpp-id-data.h (UC): Was U, conflicts with U...
libcpp/ChangeLog: 2008-04-14 Kris Van Hees <kris.van.hees@oracle.com> * include/cpp-id-data.h (UC): Was U, conflicts with U... literal. * include/cpplib.h (CHAR16, CHAR32, STRING16, STRING32): New tokens. (struct cpp_options): Added uliterals. (cpp_interpret_string): Update prototype. (cpp_interpret_string_notranslate): Idem. * charset.c (init_iconv_desc): New width member in cset_converter. (cpp_init_iconv): Add support for char{16,32}_cset_desc. (convert_ucn): Idem. (emit_numeric_escape): Idem. (convert_hex): Idem. (convert_oct): Idem. (convert_escape): Idem. (converter_for_type): New function. (cpp_interpret_string): Use converter_for_type, support u and U prefix. (cpp_interpret_string_notranslate): Match changed prototype. (wide_str_to_charconst): Use converter_for_type. (cpp_interpret_charconst): Add support for CPP_CHAR{16,32}. * directives.c (linemarker_dir): Macro U changed to UC. (parse_include): Idem. (register_pragma_1): Idem. (restore_registered_pragmas): Idem. (get__Pragma_string): Support CPP_STRING{16,32}. * expr.c (eval_token): Support CPP_CHAR{16,32}. * init.c (struct lang_flags): Added uliterals. (lang_defaults): Idem. * internal.h (struct cset_converter) <width>: New field. (struct cpp_reader) <char16_cset_desc>: Idem. (struct cpp_reader) <char32_cset_desc>: Idem. * lex.c (digraph_spellings): Macro U changed to UC. (OP, TK): Idem. (lex_string): Add support for u'...', U'...', u... and U.... (_cpp_lex_direct): Idem. * macro.c (_cpp_builtin_macro_text): Macro U changed to UC. (stringify_arg): Support CPP_CHAR{16,32} and CPP_STRING{16,32}. gcc/ChangeLog: 2008-04-14 Kris Van Hees <kris.van.hees@oracle.com> * c-common.c (CHAR16_TYPE, CHAR32_TYPE): New macros. (fname_as_string): Match updated cpp_interpret_string prototype. (fix_string_type): Support char16_t* and char32_t*. (c_common_nodes_and_builtins): Add char16_t and char32_t (and derivative) nodes. Register as builtin if C++0x. (c_parse_error): Support CPP_CHAR{16,32}. * c-common.h (RID_CHAR16, RID_CHAR32): New elements. (enum c_tree_index) <CTI_CHAR16_TYPE, CTI_SIGNED_CHAR16_TYPE, CTI_UNSIGNED_CHAR16_TYPE, CTI_CHAR32_TYPE, CTI_SIGNED_CHAR32_TYPE, CTI_UNSIGNED_CHAR32_TYPE, CTI_CHAR16_ARRAY_TYPE, CTI_CHAR32_ARRAY_TYPE>: New elements. (char16_type_node, signed_char16_type_node, unsigned_char16_type_node, char32_type_node, signed_char32_type_node, char16_array_type_node, char32_array_type_node): New defines. * c-lex.c (cb_ident): Match updated cpp_interpret_string prototype. (c_lex_with_flags): Support CPP_CHAR{16,32} and CPP_STRING{16,32}. (lex_string): Support CPP_STRING{16,32}, match updated cpp_interpret_string and cpp_interpret_string_notranslate prototypes. (lex_charconst): Support CPP_CHAR{16,32}. * c-parser.c (c_parser_postfix_expression): Support CPP_CHAR{16,32} and CPP_STRING{16,32}. gcc/cp/ChangeLog: 2008-04-14 Kris Van Hees <kris.van.hees@oracle.com> * cvt.c (type_promotes_to): Support char16_t and char32_t. * decl.c (grokdeclarator): Disallow signed/unsigned/short/long on char16_t and char32_t. * lex.c (reswords): Add char16_t and char32_t (for c++0x). * mangle.c (write_builtin_type): Mangle char16_t/char32_t as vendor extended builtin type u8char32_t. * parser.c (cp_lexer_next_token_is_decl_specifier_keyword): Support RID_CHAR{16,32}. (cp_lexer_print_token): Support CPP_STRING{16,32}. (cp_parser_is_string_literal): Idem. (cp_parser_string_literal): Idem. (cp_parser_primary_expression): Support CPP_CHAR{16,32} and CPP_STRING{16,32}. (cp_parser_simple_type_specifier): Support RID_CHAR{16,32}. * tree.c (char_type_p): Support char16_t and char32_t as char types. * typeck.c (string_conv_p): Support char16_t and char32_t. gcc/testsuite/ChangeLog: 2008-04-14 Kris Van Hees <kris.van.hees@oracle.com> Tests for char16_t and char32_t support. * g++.dg/ext/utf-cvt.C: New * g++.dg/ext/utf-cxx0x.C: New * g++.dg/ext/utf-cxx98.C: New * g++.dg/ext/utf-dflt.C: New * g++.dg/ext/utf-gnuxx0x.C: New * g++.dg/ext/utf-gnuxx98.C: New * g++.dg/ext/utf-mangle.C: New * g++.dg/ext/utf-typedef-cxx0x.C: New * g++.dg/ext/utf-typedef- * g++.dg/ext/utf-typespec.C: New * g++.dg/ext/utf16-1.C: New * g++.dg/ext/utf16-2.C: New * g++.dg/ext/utf16-3.C: New * g++.dg/ext/utf16-4.C: New * g++.dg/ext/utf32-1.C: New * g++.dg/ext/utf32-2.C: New * g++.dg/ext/utf32-3.C: New * g++.dg/ext/utf32-4.C: New * gcc.dg/utf-cvt.c: New * gcc.dg/utf-dflt.c: New * gcc.dg/utf16-1.c: New * gcc.dg/utf16-2.c: New * gcc.dg/utf16-3.c: New * gcc.dg/utf16-4.c: New * gcc.dg/utf32-1.c: New * gcc.dg/utf32-2.c: New * gcc.dg/utf32-3.c: New * gcc.dg/utf32-4.c: New libiberty/ChangeLog: 2008-04-14 Kris Van Hees <kris.van.hees@oracle.com> * testsuite/demangle-expected: Added tests for char16_t and char32_t. From-SVN: r134438
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog24
-rw-r--r--gcc/c-common.c108
-rw-r--r--gcc/c-common.h10
-rw-r--r--gcc/c-lex.c88
-rw-r--r--gcc/c-parser.c4
-rw-r--r--gcc/cp/ChangeLog19
-rw-r--r--gcc/cp/cvt.c2
-rw-r--r--gcc/cp/decl.c7
-rw-r--r--gcc/cp/lex.c2
-rw-r--r--gcc/cp/mangle.c8
-rw-r--r--gcc/cp/parser.c72
-rw-r--r--gcc/cp/tree.c2
-rw-r--r--gcc/cp/typeck.c4
-rw-r--r--gcc/testsuite/ChangeLog32
-rw-r--r--gcc/testsuite/g++.dg/ext/utf-badconcat.C22
-rw-r--r--gcc/testsuite/g++.dg/ext/utf-cvt.C46
-rw-r--r--gcc/testsuite/g++.dg/ext/utf-cxx0x.C14
-rw-r--r--gcc/testsuite/g++.dg/ext/utf-cxx98.C29
-rw-r--r--gcc/testsuite/g++.dg/ext/utf-dflt.C29
-rw-r--r--gcc/testsuite/g++.dg/ext/utf-gnuxx0x.C14
-rw-r--r--gcc/testsuite/g++.dg/ext/utf-gnuxx98.C29
-rw-r--r--gcc/testsuite/g++.dg/ext/utf-mangle.C14
-rw-r--r--gcc/testsuite/g++.dg/ext/utf-typedef-cxx0x.C7
-rw-r--r--gcc/testsuite/g++.dg/ext/utf-typedef-cxx98.C7
-rw-r--r--gcc/testsuite/g++.dg/ext/utf-typespec.C25
-rw-r--r--gcc/testsuite/g++.dg/ext/utf16-1.C65
-rw-r--r--gcc/testsuite/g++.dg/ext/utf16-2.C30
-rw-r--r--gcc/testsuite/g++.dg/ext/utf16-3.C47
-rw-r--r--gcc/testsuite/g++.dg/ext/utf16-4.C18
-rw-r--r--gcc/testsuite/g++.dg/ext/utf32-1.C42
-rw-r--r--gcc/testsuite/g++.dg/ext/utf32-2.C29
-rw-r--r--gcc/testsuite/g++.dg/ext/utf32-3.C46
-rw-r--r--gcc/testsuite/g++.dg/ext/utf32-4.C18
-rw-r--r--gcc/testsuite/gcc.dg/utf-badconcat.c22
-rw-r--r--gcc/testsuite/gcc.dg/utf-cvt.c49
-rw-r--r--gcc/testsuite/gcc.dg/utf-dflt.c25
-rw-r--r--gcc/testsuite/gcc.dg/utf16-1.c67
-rw-r--r--gcc/testsuite/gcc.dg/utf16-2.c32
-rw-r--r--gcc/testsuite/gcc.dg/utf16-3.c49
-rw-r--r--gcc/testsuite/gcc.dg/utf16-4.c20
-rw-r--r--gcc/testsuite/gcc.dg/utf32-1.c44
-rw-r--r--gcc/testsuite/gcc.dg/utf32-2.c31
-rw-r--r--gcc/testsuite/gcc.dg/utf32-3.c48
-rw-r--r--gcc/testsuite/gcc.dg/utf32-4.c20
44 files changed, 1271 insertions, 49 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index cb7fe4e..a053bf4 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,27 @@
+2008-04-18 Kris Van Hees <kris.van.hees@oracle.com>
+
+ * c-common.c (CHAR16_TYPE, CHAR32_TYPE): New macros.
+ (fname_as_string): Match updated cpp_interpret_string prototype.
+ (fix_string_type): Support char16_t* and char32_t*.
+ (c_common_nodes_and_builtins): Add char16_t and char32_t (and
+ derivative) nodes. Register as builtin if C++0x.
+ (c_parse_error): Support CPP_CHAR{16,32}.
+ * c-common.h (RID_CHAR16, RID_CHAR32): New elements.
+ (enum c_tree_index) <CTI_CHAR16_TYPE, CTI_SIGNED_CHAR16_TYPE,
+ CTI_UNSIGNED_CHAR16_TYPE, CTI_CHAR32_TYPE, CTI_SIGNED_CHAR32_TYPE,
+ CTI_UNSIGNED_CHAR32_TYPE, CTI_CHAR16_ARRAY_TYPE,
+ CTI_CHAR32_ARRAY_TYPE>: New elements.
+ (char16_type_node, signed_char16_type_node, unsigned_char16_type_node,
+ char32_type_node, signed_char32_type_node, char16_array_type_node,
+ char32_array_type_node): New defines.
+ * c-lex.c (cb_ident): Match updated cpp_interpret_string prototype.
+ (c_lex_with_flags): Support CPP_CHAR{16,32} and CPP_STRING{16,32}.
+ (lex_string): Support CPP_STRING{16,32}, match updated
+ cpp_interpret_string and cpp_interpret_string_notranslate prototypes.
+ (lex_charconst): Support CPP_CHAR{16,32}.
+ * c-parser.c (c_parser_postfix_expression): Support CPP_CHAR{16,32}
+ and CPP_STRING{16,32}.
+
2008-04-18 Paolo Bonzini <bonzini@gnu.org>
PR bootstrap/35457
diff --git a/gcc/c-common.c b/gcc/c-common.c
index ceb2f06..351c628 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -66,6 +66,14 @@ cpp_reader *parse_in; /* Declared in c-pragma.h. */
#define PID_TYPE "int"
#endif
+#ifndef CHAR16_TYPE
+#define CHAR16_TYPE "short unsigned int"
+#endif
+
+#ifndef CHAR32_TYPE
+#define CHAR32_TYPE "unsigned int"
+#endif
+
#ifndef WCHAR_TYPE
#define WCHAR_TYPE "int"
#endif
@@ -123,6 +131,9 @@ cpp_reader *parse_in; /* Declared in c-pragma.h. */
tree signed_wchar_type_node;
tree unsigned_wchar_type_node;
+ tree char16_type_node;
+ tree char32_type_node;
+
tree float_type_node;
tree double_type_node;
tree long_double_type_node;
@@ -174,6 +185,16 @@ cpp_reader *parse_in; /* Declared in c-pragma.h. */
tree wchar_array_type_node;
+ Type `char16_t[SOMENUMBER]' or something like it.
+ Used when a UTF-16 string literal is created.
+
+ tree char16_array_type_node;
+
+ Type `char32_t[SOMENUMBER]' or something like it.
+ Used when a UTF-32 string literal is created.
+
+ tree char32_array_type_node;
+
Type `int ()' -- used for implicit declaration of functions.
tree default_function_type;
@@ -777,7 +798,7 @@ fname_as_string (int pretty_p)
strname.text = (unsigned char *) namep;
strname.len = len - 1;
- if (cpp_interpret_string (parse_in, &strname, 1, &cstr, false))
+ if (cpp_interpret_string (parse_in, &strname, 1, &cstr, CPP_STRING))
{
XDELETEVEC (namep);
return (const char *) cstr.text;
@@ -857,14 +878,31 @@ fname_decl (unsigned int rid, tree id)
tree
fix_string_type (tree value)
{
- const int wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT;
- const int wide_flag = TREE_TYPE (value) == wchar_array_type_node;
int length = TREE_STRING_LENGTH (value);
int nchars;
tree e_type, i_type, a_type;
/* Compute the number of elements, for the array type. */
- nchars = wide_flag ? length / wchar_bytes : length;
+ if (TREE_TYPE (value) == char_array_type_node || !TREE_TYPE (value))
+ {
+ nchars = length;
+ e_type = char_type_node;
+ }
+ else if (TREE_TYPE (value) == char16_array_type_node)
+ {
+ nchars = length / (TYPE_PRECISION (char16_type_node) / BITS_PER_UNIT);
+ e_type = char16_type_node;
+ }
+ else if (TREE_TYPE (value) == char32_array_type_node)
+ {
+ nchars = length / (TYPE_PRECISION (char32_type_node) / BITS_PER_UNIT);
+ e_type = char32_type_node;
+ }
+ else
+ {
+ nchars = length / (TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT);
+ e_type = wchar_type_node;
+ }
/* C89 2.2.4.1, C99 5.2.4.1 (Translation limits). The analogous
limit in C++98 Annex B is very large (65536) and is not normative,
@@ -899,7 +937,6 @@ fix_string_type (tree value)
construct the matching unqualified array type first. The C front
end does not require this, but it does no harm, so we do it
unconditionally. */
- e_type = wide_flag ? wchar_type_node : char_type_node;
i_type = build_index_type (build_int_cst (NULL_TREE, nchars - 1));
a_type = build_array_type (e_type, i_type);
if (c_dialect_cxx() || warn_write_strings)
@@ -3629,6 +3666,8 @@ c_define_builtins (tree va_list_ref_type_node, tree va_list_arg_type_node)
void
c_common_nodes_and_builtins (void)
{
+ int char16_type_size;
+ int char32_type_size;
int wchar_type_size;
tree array_domain_type;
tree va_list_ref_type_node;
@@ -3878,6 +3917,38 @@ c_common_nodes_and_builtins (void)
wchar_array_type_node
= build_array_type (wchar_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));
+ char16_type_size = TYPE_PRECISION (char16_type_node);
+ if (c_dialect_cxx ())
+ {
+ char16_type_node = make_unsigned_type (char16_type_size);
+
+ if (cxx_dialect == cxx0x)
+ record_builtin_type (RID_CHAR16, "char16_t", char16_type_node);
+ }
+
+ /* This is for UTF-16 string constants. */
+ char16_array_type_node
+ = build_array_type (char16_type_node, array_domain_type);
+
+ /* Define 'char32_t'. */
+ char32_type_node = get_identifier (CHAR32_TYPE);
+ char32_type_node = TREE_TYPE (identifier_global_value (char32_type_node));
+ char32_type_size = TYPE_PRECISION (char32_type_node);
+ if (c_dialect_cxx ())
+ {
+ char32_type_node = make_unsigned_type (char32_type_size);
+
+ if (cxx_dialect == cxx0x)
+ record_builtin_type (RID_CHAR32, "char32_t", char32_type_node);
+ }
+
+ /* This is for UTF-32 string constants. */
+ char32_array_type_node
+ = build_array_type (char32_type_node, array_domain_type);
+
wint_type_node =
TREE_TYPE (identifier_global_value (get_identifier (WINT_TYPE)));
@@ -6662,20 +6733,39 @@ c_parse_error (const char *gmsgid, enum cpp_ttype token, tree value)
if (token == CPP_EOF)
message = catenate_messages (gmsgid, " at end of input");
- else if (token == CPP_CHAR || token == CPP_WCHAR)
+ else if (token == CPP_CHAR || token == CPP_WCHAR || token == CPP_CHAR16
+ || token == CPP_CHAR32)
{
unsigned int val = TREE_INT_CST_LOW (value);
- const char *const ell = (token == CPP_CHAR) ? "" : "L";
+ const char *prefix;
+
+ switch (token)
+ {
+ default:
+ prefix = "";
+ break;
+ case CPP_WCHAR:
+ prefix = "L";
+ break;
+ case CPP_CHAR16:
+ prefix = "u";
+ break;
+ case CPP_CHAR32:
+ prefix = "U";
+ break;
+ }
+
if (val <= UCHAR_MAX && ISGRAPH (val))
message = catenate_messages (gmsgid, " before %s'%c'");
else
message = catenate_messages (gmsgid, " before %s'\\x%x'");
- error (message, ell, val);
+ error (message, prefix, val);
free (message);
message = NULL;
}
- else if (token == CPP_STRING || token == CPP_WSTRING)
+ else if (token == CPP_STRING || token == CPP_WSTRING || token == CPP_STRING16
+ || token == CPP_STRING32)
message = catenate_messages (gmsgid, " before string constant");
else if (token == CPP_NUMBER)
message = catenate_messages (gmsgid, " before numeric constant");
diff --git a/gcc/c-common.h b/gcc/c-common.h
index 10933e9..3ca3c8b 100644
--- a/gcc/c-common.h
+++ b/gcc/c-common.h
@@ -85,7 +85,7 @@ enum rid
RID_NEW, RID_OFFSETOF, RID_OPERATOR,
RID_THIS, RID_THROW, RID_TRUE,
RID_TRY, RID_TYPENAME, RID_TYPEID,
- RID_USING,
+ RID_USING, RID_CHAR16, RID_CHAR32,
/* casts */
RID_CONSTCAST, RID_DYNCAST, RID_REINTCAST, RID_STATCAST,
@@ -143,6 +143,8 @@ extern GTY ((length ("(int) RID_MAX"))) tree *ridpointers;
enum c_tree_index
{
+ CTI_CHAR16_TYPE,
+ CTI_CHAR32_TYPE,
CTI_WCHAR_TYPE,
CTI_SIGNED_WCHAR_TYPE,
CTI_UNSIGNED_WCHAR_TYPE,
@@ -155,6 +157,8 @@ enum c_tree_index
CTI_WIDEST_UINT_LIT_TYPE,
CTI_CHAR_ARRAY_TYPE,
+ CTI_CHAR16_ARRAY_TYPE,
+ CTI_CHAR32_ARRAY_TYPE,
CTI_WCHAR_ARRAY_TYPE,
CTI_INT_ARRAY_TYPE,
CTI_STRING_TYPE,
@@ -190,6 +194,8 @@ struct c_common_identifier GTY(())
struct cpp_hashnode node;
};
+#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 signed_wchar_type_node c_global_trees[CTI_SIGNED_WCHAR_TYPE]
#define unsigned_wchar_type_node c_global_trees[CTI_UNSIGNED_WCHAR_TYPE]
@@ -206,6 +212,8 @@ struct c_common_identifier GTY(())
#define truthvalue_false_node c_global_trees[CTI_TRUTHVALUE_FALSE]
#define char_array_type_node c_global_trees[CTI_CHAR_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]
#define int_array_type_node c_global_trees[CTI_INT_ARRAY_TYPE]
#define string_type_node c_global_trees[CTI_STRING_TYPE]
diff --git a/gcc/c-lex.c b/gcc/c-lex.c
index 617cd7e..c3e7f6e 100644
--- a/gcc/c-lex.c
+++ b/gcc/c-lex.c
@@ -174,7 +174,7 @@ cb_ident (cpp_reader * ARG_UNUSED (pfile),
{
/* Convert escapes in the string. */
cpp_string cstr = { 0, 0 };
- if (cpp_interpret_string (pfile, str, 1, &cstr, false))
+ if (cpp_interpret_string (pfile, str, 1, &cstr, CPP_STRING))
{
ASM_OUTPUT_IDENT (asm_out_file, (const char *) cstr.text);
free (CONST_CAST (unsigned char *, cstr.text));
@@ -361,6 +361,8 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags,
case CPP_STRING:
case CPP_WSTRING:
+ case CPP_STRING16:
+ case CPP_STRING32:
type = lex_string (tok, value, true, true);
break;
@@ -410,11 +412,15 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags,
case CPP_CHAR:
case CPP_WCHAR:
+ case CPP_CHAR16:
+ case CPP_CHAR32:
*value = lex_charconst (tok);
break;
case CPP_STRING:
case CPP_WSTRING:
+ case CPP_STRING16:
+ case CPP_STRING32:
if ((lex_flags & C_LEX_RAW_STRINGS) == 0)
{
type = lex_string (tok, value, false,
@@ -822,12 +828,12 @@ interpret_fixed (const cpp_token *token, unsigned int flags)
return value;
}
-/* Convert a series of STRING and/or WSTRING tokens into a tree,
- performing string constant concatenation. TOK is the first of
- these. VALP is the location to write the string into. OBJC_STRING
- indicates whether an '@' token preceded the incoming token.
+/* Convert a series of STRING, WSTRING, STRING16 and/or STRING32 tokens
+ into a tree, performing string constant concatenation. TOK is the
+ first of these. VALP is the location to write the string into.
+ OBJC_STRING indicates whether an '@' token preceded the incoming token.
Returns the CPP token type of the result (CPP_STRING, CPP_WSTRING,
- or CPP_OBJC_STRING).
+ CPP_STRING32, CPP_STRING16, or CPP_OBJC_STRING).
This is unfortunately more work than it should be. If any of the
strings in the series has an L prefix, the result is a wide string
@@ -842,19 +848,16 @@ static enum cpp_ttype
lex_string (const cpp_token *tok, tree *valp, bool objc_string, bool translate)
{
tree value;
- bool wide = false;
size_t concats = 0;
struct obstack str_ob;
cpp_string istr;
+ enum cpp_ttype type = tok->type;
/* Try to avoid the overhead of creating and destroying an obstack
for the common case of just one string. */
cpp_string str = tok->val.str;
cpp_string *strs = &str;
- if (tok->type == CPP_WSTRING)
- wide = true;
-
retry:
tok = cpp_get_token (parse_in);
switch (tok->type)
@@ -873,8 +876,15 @@ lex_string (const cpp_token *tok, tree *valp, bool objc_string, bool translate)
break;
case CPP_WSTRING:
- wide = true;
- /* FALLTHROUGH */
+ case CPP_STRING16:
+ case CPP_STRING32:
+ if (type != tok->type)
+ {
+ if (type == CPP_STRING)
+ type = tok->type;
+ else
+ error ("unsupported non-standard concatenation of string literals");
+ }
case CPP_STRING:
if (!concats)
@@ -899,7 +909,7 @@ lex_string (const cpp_token *tok, tree *valp, bool objc_string, bool translate)
if ((translate
? cpp_interpret_string : cpp_interpret_string_notranslate)
- (parse_in, strs, concats + 1, &istr, wide))
+ (parse_in, strs, concats + 1, &istr, type))
{
value = build_string (istr.len, (const char *) istr.text);
free (CONST_CAST (unsigned char *, istr.text));
@@ -909,22 +919,52 @@ lex_string (const cpp_token *tok, tree *valp, bool objc_string, bool translate)
/* Callers cannot generally handle error_mark_node in this context,
so return the empty string instead. cpp_interpret_string has
issued an error. */
- if (wide)
- value = build_string (TYPE_PRECISION (wchar_type_node)
- / TYPE_PRECISION (char_type_node),
- "\0\0\0"); /* widest supported wchar_t
- is 32 bits */
- else
- value = build_string (1, "");
+ switch (type)
+ {
+ default:
+ case CPP_STRING:
+ value = build_string (1, "");
+ break;
+ case CPP_STRING16:
+ value = build_string (TYPE_PRECISION (char16_type_node)
+ / TYPE_PRECISION (char_type_node),
+ "\0"); /* char16_t is 16 bits */
+ break;
+ case CPP_STRING32:
+ value = build_string (TYPE_PRECISION (char32_type_node)
+ / TYPE_PRECISION (char_type_node),
+ "\0\0\0"); /* char32_t is 32 bits */
+ break;
+ case CPP_WSTRING:
+ value = build_string (TYPE_PRECISION (wchar_type_node)
+ / TYPE_PRECISION (char_type_node),
+ "\0\0\0"); /* widest supported wchar_t
+ is 32 bits */
+ break;
+ }
}
- TREE_TYPE (value) = wide ? wchar_array_type_node : char_array_type_node;
+ switch (type)
+ {
+ default:
+ case CPP_STRING:
+ TREE_TYPE (value) = char_array_type_node;
+ break;
+ case CPP_STRING16:
+ TREE_TYPE (value) = char16_array_type_node;
+ break;
+ case CPP_STRING32:
+ TREE_TYPE (value) = char32_array_type_node;
+ break;
+ case CPP_WSTRING:
+ TREE_TYPE (value) = wchar_array_type_node;
+ }
*valp = fix_string_type (value);
if (concats)
obstack_free (&str_ob, 0);
- return objc_string ? CPP_OBJC_STRING : wide ? CPP_WSTRING : CPP_STRING;
+ return objc_string ? CPP_OBJC_STRING : type;
}
/* Converts a (possibly wide) character constant token into a tree. */
@@ -941,6 +981,10 @@ lex_charconst (const cpp_token *token)
if (token->type == CPP_WCHAR)
type = wchar_type_node;
+ else if (token->type == CPP_CHAR32)
+ type = char32_type_node;
+ else if (token->type == CPP_CHAR16)
+ type = char16_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)
diff --git a/gcc/c-parser.c b/gcc/c-parser.c
index 09b6359..d98640d 100644
--- a/gcc/c-parser.c
+++ b/gcc/c-parser.c
@@ -5163,12 +5163,16 @@ c_parser_postfix_expression (c_parser *parser)
{
case CPP_NUMBER:
case CPP_CHAR:
+ case CPP_CHAR16:
+ case CPP_CHAR32:
case CPP_WCHAR:
expr.value = c_parser_peek_token (parser)->value;
expr.original_code = ERROR_MARK;
c_parser_consume_token (parser);
break;
case CPP_STRING:
+ case CPP_STRING16:
+ case CPP_STRING32:
case CPP_WSTRING:
expr.value = c_parser_peek_token (parser)->value;
expr.original_code = STRING_CST;
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 3169ba0..b348c0d 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,22 @@
+2008-04-18 Kris Van Hees <kris.van.hees@oracle.com>
+
+ * cvt.c (type_promotes_to): Support char16_t and char32_t.
+ * decl.c (grokdeclarator): Disallow signed/unsigned/short/long on
+ char16_t and char32_t.
+ * lex.c (reswords): Add char16_t and char32_t (for c++0x).
+ * mangle.c (write_builtin_type): Mangle char16_t/char32_t as vendor
+ extended builtin type "u8char{16,32}_t".
+ * parser.c (cp_lexer_next_token_is_decl_specifier_keyword): Support
+ RID_CHAR{16,32}.
+ (cp_lexer_print_token): Support CPP_STRING{16,32}.
+ (cp_parser_is_string_literal): Idem.
+ (cp_parser_string_literal): Idem.
+ (cp_parser_primary_expression): Support CPP_CHAR{16,32} and
+ CPP_STRING{16,32}.
+ (cp_parser_simple_type_specifier): Support RID_CHAR{16,32}.
+ * tree.c (char_type_p): Support char16_t and char32_t as char types.
+ * typeck.c (string_conv_p): Support char16_t and char32_t.
+
2008-04-17 Jason Merrill <jason@redhat.com>
PR c++/35773
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index fe1ed29..b2c17c5 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -1219,6 +1219,8 @@ type_promotes_to (tree type)
/* Normally convert enums to int, but convert wide enums to something
wider. */
else if (TREE_CODE (type) == ENUMERAL_TYPE
+ || type == char16_type_node
+ || type == char32_type_node
|| type == wchar_type_node)
{
int precision = MAX (TYPE_PRECISION (type),
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 66e8f42..d16cb78 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -7732,6 +7732,13 @@ grokdeclarator (const cp_declarator *declarator,
error ("%<long%> or %<short%> specified with char for %qs", name);
else if (long_p && short_p)
error ("%<long%> and %<short%> specified together for %qs", name);
+ else if (type == char16_type_node || type == char32_type_node)
+ {
+ if (signed_p || unsigned_p)
+ error ("%<signed%> or %<unsigned%> invalid for %qs", name);
+ else if (short_p || long_p)
+ error ("%<short%> or %<long%> invalid for %qs", name);
+ }
else
{
ok = 1;
diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c
index 4552305..8484a4b 100644
--- a/gcc/cp/lex.c
+++ b/gcc/cp/lex.c
@@ -241,6 +241,8 @@ static const struct resword reswords[] =
{ "case", RID_CASE, 0 },
{ "catch", RID_CATCH, 0 },
{ "char", RID_CHAR, 0 },
+ { "char16_t", RID_CHAR16, D_CXX0X },
+ { "char32_t", RID_CHAR32, D_CXX0X },
{ "class", RID_CLASS, 0 },
{ "const", RID_CONST, 0 },
{ "const_cast", RID_CONSTCAST, 0 },
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 09a34562..5ac5bce 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -1782,10 +1782,14 @@ write_builtin_type (tree type)
break;
case INTEGER_TYPE:
- /* TYPE may still be wchar_t, since that isn't in
- integer_type_nodes. */
+ /* TYPE may still be wchar_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 == char16_type_node)
+ write_string ("u8char16_t");
+ else if (type == char32_type_node)
+ write_string ("u8char32_t");
else if (TYPE_FOR_JAVA (type))
write_java_integer_type_codes (type);
else
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index f57ce28..f2acddb 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -556,6 +556,8 @@ cp_lexer_next_token_is_decl_specifier_keyword (cp_lexer *lexer)
case RID_TYPENAME:
/* Simple type specifiers. */
case RID_CHAR:
+ case RID_CHAR16:
+ case RID_CHAR32:
case RID_WCHAR:
case RID_BOOL:
case RID_SHORT:
@@ -789,6 +791,8 @@ cp_lexer_print_token (FILE * stream, cp_token *token)
break;
case CPP_STRING:
+ case CPP_STRING16:
+ case CPP_STRING32:
case CPP_WSTRING:
fprintf (stream, " \"%s\"", TREE_STRING_POINTER (token->u.value));
break;
@@ -2033,7 +2037,10 @@ cp_parser_parsing_tentatively (cp_parser* parser)
static bool
cp_parser_is_string_literal (cp_token* token)
{
- return (token->type == CPP_STRING || token->type == CPP_WSTRING);
+ return (token->type == CPP_STRING ||
+ token->type == CPP_STRING16 ||
+ token->type == CPP_STRING32 ||
+ token->type == CPP_WSTRING);
}
/* Returns nonzero if TOKEN is the indicated KEYWORD. */
@@ -2867,11 +2874,11 @@ static tree
cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
{
tree value;
- bool wide = false;
size_t count;
struct obstack str_ob;
cpp_string str, istr, *strs;
cp_token *tok;
+ enum cpp_ttype type;
tok = cp_lexer_peek_token (parser->lexer);
if (!cp_parser_is_string_literal (tok))
@@ -2880,6 +2887,8 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
return error_mark_node;
}
+ type = tok->type;
+
/* Try to avoid the overhead of creating and destroying an obstack
for the common case of just one string. */
if (!cp_parser_is_string_literal
@@ -2890,8 +2899,6 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
str.text = (const unsigned char *)TREE_STRING_POINTER (tok->u.value);
str.len = TREE_STRING_LENGTH (tok->u.value);
count = 1;
- if (tok->type == CPP_WSTRING)
- wide = true;
strs = &str;
}
@@ -2906,8 +2913,14 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
count++;
str.text = (const unsigned char *)TREE_STRING_POINTER (tok->u.value);
str.len = TREE_STRING_LENGTH (tok->u.value);
- if (tok->type == CPP_WSTRING)
- wide = true;
+
+ if (type != tok->type)
+ {
+ if (type == CPP_STRING)
+ type = tok->type;
+ else if (tok->type != CPP_STRING)
+ error ("unsupported non-standard concatenation of string literals");
+ }
obstack_grow (&str_ob, &str, sizeof (cpp_string));
@@ -2918,19 +2931,35 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
strs = (cpp_string *) obstack_finish (&str_ob);
}
- if (wide && !wide_ok)
+ if (type != CPP_STRING && !wide_ok)
{
cp_parser_error (parser, "a wide string is invalid in this context");
- wide = false;
+ type = CPP_STRING;
}
if ((translate ? cpp_interpret_string : cpp_interpret_string_notranslate)
- (parse_in, strs, count, &istr, wide))
+ (parse_in, strs, count, &istr, type))
{
value = build_string (istr.len, (const char *)istr.text);
free (CONST_CAST (unsigned char *, istr.text));
- TREE_TYPE (value) = wide ? wchar_array_type_node : char_array_type_node;
+ switch (type)
+ {
+ default:
+ case CPP_STRING:
+ TREE_TYPE (value) = char_array_type_node;
+ break;
+ case CPP_STRING16:
+ TREE_TYPE (value) = char16_array_type_node;
+ break;
+ case CPP_STRING32:
+ TREE_TYPE (value) = char32_array_type_node;
+ break;
+ case CPP_WSTRING:
+ TREE_TYPE (value) = wchar_array_type_node;
+ break;
+ }
+
value = fix_string_type (value);
}
else
@@ -3085,6 +3114,8 @@ cp_parser_primary_expression (cp_parser *parser,
string-literal
boolean-literal */
case CPP_CHAR:
+ case CPP_CHAR16:
+ case CPP_CHAR32:
case CPP_WCHAR:
case CPP_NUMBER:
token = cp_lexer_consume_token (parser->lexer);
@@ -3136,6 +3167,8 @@ cp_parser_primary_expression (cp_parser *parser,
return token->u.value;
case CPP_STRING:
+ case CPP_STRING16:
+ case CPP_STRING32:
case CPP_WSTRING:
/* ??? Should wide strings be allowed when parser->translate_strings_p
is false (i.e. in attributes)? If not, we can kill the third
@@ -10762,6 +10795,8 @@ cp_parser_type_specifier (cp_parser* parser,
simple-type-specifier:
auto
decltype ( expression )
+ char16_t
+ char32_t
GNU Extension:
@@ -10791,6 +10826,12 @@ cp_parser_simple_type_specifier (cp_parser* parser,
decl_specs->explicit_char_p = true;
type = char_type_node;
break;
+ case RID_CHAR16:
+ type = char16_type_node;
+ break;
+ case RID_CHAR32:
+ type = char32_type_node;
+ break;
case RID_WCHAR:
type = wchar_type_node;
break;
@@ -17754,13 +17795,16 @@ 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 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 the user tries to redeclare bool, 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_specs->specs[(int) ds_typedef]
&& !user_defined_p
&& (type_spec == boolean_type_node
+ || type_spec == char16_type_node
+ || type_spec == char32_type_node
|| type_spec == wchar_type_node)
&& (decl_specs->type
|| decl_specs->specs[(int) ds_long]
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 027f1c9..73adbb5 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -2474,6 +2474,8 @@ 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, char16_type_node)
+ || same_type_p (type, char32_type_node)
|| same_type_p (type, wchar_type_node));
}
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index de10c0e..9e9d461 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1722,12 +1722,14 @@ 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, char16_type_node)
+ && !same_type_p (t, char32_type_node)
&& !same_type_p (t, wchar_type_node))
return 0;
if (TREE_CODE (exp) == STRING_CST)
{
- /* Make sure that we don't try to convert between char and wchar_t. */
+ /* Make sure that we don't try to convert between char and wide chars. */
if (!same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (exp))), t))
return 0;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 339ac3a..e839cde 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,35 @@
+2008-04-18 Kris Van Hees <kris.van.hees@oracle.com>
+
+ Tests for char16_t and char32_t support.
+ * g++.dg/ext/utf-cvt.C: New
+ * g++.dg/ext/utf-cxx0x.C: New
+ * g++.dg/ext/utf-cxx98.C: New
+ * g++.dg/ext/utf-dflt.C: New
+ * g++.dg/ext/utf-gnuxx0x.C: New
+ * g++.dg/ext/utf-gnuxx98.C: New
+ * g++.dg/ext/utf-mangle.C: New
+ * g++.dg/ext/utf-typedef-cxx0x.C: New
+ * g++.dg/ext/utf-typedef-cxx98.C: New
+ * g++.dg/ext/utf-typespec.C: New
+ * g++.dg/ext/utf16-1.C: New
+ * g++.dg/ext/utf16-2.C: New
+ * g++.dg/ext/utf16-3.C: New
+ * g++.dg/ext/utf16-4.C: New
+ * g++.dg/ext/utf32-1.C: New
+ * g++.dg/ext/utf32-2.C: New
+ * g++.dg/ext/utf32-3.C: New
+ * g++.dg/ext/utf32-4.C: New
+ * gcc.dg/utf-cvt.c: New
+ * gcc.dg/utf-dflt.c: New
+ * gcc.dg/utf16-1.c: New
+ * gcc.dg/utf16-2.c: New
+ * gcc.dg/utf16-3.c: New
+ * gcc.dg/utf16-4.c: New
+ * gcc.dg/utf32-1.c: New
+ * gcc.dg/utf32-2.c: New
+ * gcc.dg/utf32-3.c: New
+ * gcc.dg/utf32-4.c: New
+
2008-04-18 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/specs/varsize_return.ads: New test.
diff --git a/gcc/testsuite/g++.dg/ext/utf-badconcat.C b/gcc/testsuite/g++.dg/ext/utf-badconcat.C
new file mode 100644
index 0000000..bab020e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/utf-badconcat.C
@@ -0,0 +1,22 @@
+/* Contributed by Kris Van Hees <kris.van.hees@oracle.com> */
+/* Test unsupported concatenation of char16_t/char32_t* string literals. */
+/* { dg-do compile } */
+/* { dg-options "-std=c++0x" } */
+
+const void *s0 = u"a" "b";
+const void *s1 = "a" u"b";
+const void *s2 = u"a" U"b"; /* { dg-error "non-standard concatenation" } */
+const void *s3 = U"a" u"b"; /* { dg-error "non-standard concatenation" } */
+const void *s4 = u"a" L"b"; /* { dg-error "non-standard concatenation" } */
+const void *s5 = L"a" u"b"; /* { dg-error "non-standard concatenation" } */
+const void *s6 = u"a" u"b";
+const void *s7 = U"a" "b";
+const void *s8 = "a" U"b";
+const void *s9 = U"a" L"b"; /* { dg-error "non-standard concatenation" } */
+const void *sa = L"a" U"b"; /* { dg-error "non-standard concatenation" } */
+const void *sb = U"a" U"b";
+const void *sc = L"a" "b";
+const void *sd = "a" L"b";
+const void *se = L"a" L"b";
+
+int main () {}
diff --git a/gcc/testsuite/g++.dg/ext/utf-cvt.C b/gcc/testsuite/g++.dg/ext/utf-cvt.C
new file mode 100644
index 0000000..0e6b17a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/utf-cvt.C
@@ -0,0 +1,46 @@
+/* Contributed by Kris Van Hees <kris.van.hees@oracle.com> */
+/* Test the char16_t and char32_t promotion rules. */
+/* { dg-do compile } */
+/* { dg-options "-std=c++0x -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);
+
+void m(char16_t c0, char32_t c1)
+{
+ f_c (c0); /* { dg-warning "alter its value" } */
+ fsc (c0); /* { dg-warning "alter its value" } */
+ fuc (c0); /* { dg-warning "alter its value" } */
+ f_s (c0); /* { dg-warning "change the sign" } */
+ fss (c0); /* { dg-warning "change the sign" } */
+ fus (c0);
+ f_i (c0);
+ fsi (c0);
+ fui (c0);
+ f_l (c0);
+ fsl (c0);
+ ful (c0);
+
+ f_c (c1); /* { dg-warning "alter its value" } */
+ fsc (c1); /* { dg-warning "alter its value" } */
+ fuc (c1); /* { dg-warning "alter its value" } */
+ f_s (c1); /* { dg-warning "alter its value" } */
+ fss (c1); /* { dg-warning "alter its value" } */
+ fus (c1); /* { dg-warning "alter its value" } */
+ f_i (c1); /* { dg-warning "change the sign" } */
+ fsi (c1); /* { dg-warning "change the sign" } */
+ fui (c1);
+ f_l (c1); /* { dg-warning "change the sign" } */
+ fsl (c1); /* { dg-warning "change the sign" } */
+ ful (c1);
+}
diff --git a/gcc/testsuite/g++.dg/ext/utf-cxx0x.C b/gcc/testsuite/g++.dg/ext/utf-cxx0x.C
new file mode 100644
index 0000000..1daa0de
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/utf-cxx0x.C
@@ -0,0 +1,14 @@
+/* Contributed by Kris Van Hees <kris.van.hees@oracle.com> */
+/* Test parsing of u and U prefixes when also used as macros. */
+/* { dg-do compile } */
+/* { dg-options "-std=c++0x" } */
+
+#define u L
+#define U L
+
+const unsigned short c2 = u'a';
+const unsigned long c3 = U'a';
+const void *s0 = u"a";
+const void *s1 = U"a";
+
+int main () {}
diff --git a/gcc/testsuite/g++.dg/ext/utf-cxx98.C b/gcc/testsuite/g++.dg/ext/utf-cxx98.C
new file mode 100644
index 0000000..a8dd13a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/utf-cxx98.C
@@ -0,0 +1,29 @@
+/* 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. */
+/* { 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" } */
+ /* { dg-error "expected ',' or ';'" "" { target *-*-* } 10 } */
+const unsigned long c3 = U'a'; /* { dg-error "not declared" } */
+ /* { dg-error "expected ',' or ';'" "" { target *-*-* } 12 } */
+
+#define u 1 +
+#define U 2 +
+
+const unsigned short c5 = u'a';
+const unsigned long c6 = U'a';
+
+#undef u
+#undef U
+#define u "a"
+#define U "b"
+
+const void *s0 = u"a";
+const void *s1 = U"a";
+
+int main () {}
diff --git a/gcc/testsuite/g++.dg/ext/utf-dflt.C b/gcc/testsuite/g++.dg/ext/utf-dflt.C
new file mode 100644
index 0000000..942f2b2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/utf-dflt.C
@@ -0,0 +1,29 @@
+/* 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. */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+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" } */
+ /* { dg-error "expected ',' or ';'" "" { target *-*-* } 10 } */
+const unsigned long c3 = U'a'; /* { dg-error "not declared" } */
+ /* { dg-error "expected ',' or ';'" "" { target *-*-* } 12 } */
+
+#define u 1 +
+#define U 2 +
+
+const unsigned short c4 = u'a';
+const unsigned long c5 = U'a';
+
+#undef u
+#undef U
+#define u "a"
+#define U "b"
+
+const void *s0 = u"a";
+const void *s1 = U"a";
+
+int main () {}
diff --git a/gcc/testsuite/g++.dg/ext/utf-gnuxx0x.C b/gcc/testsuite/g++.dg/ext/utf-gnuxx0x.C
new file mode 100644
index 0000000..0a6967f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/utf-gnuxx0x.C
@@ -0,0 +1,14 @@
+/* Contributed by Kris Van Hees <kris.van.hees@oracle.com> */
+/* Test parsing of u and U prefixes when also used as macros. */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu++0x" } */
+
+#define u L
+#define U L
+
+const unsigned short c2 = u'a';
+const unsigned long c3 = U'a';
+const void *s0 = u"a";
+const void *s1 = U"a";
+
+int main () {}
diff --git a/gcc/testsuite/g++.dg/ext/utf-gnuxx98.C b/gcc/testsuite/g++.dg/ext/utf-gnuxx98.C
new file mode 100644
index 0000000..fc8068b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/utf-gnuxx98.C
@@ -0,0 +1,29 @@
+/* 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. */
+/* { 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" } */
+ /* { dg-error "expected ',' or ';'" "" { target *-*-* } 10 } */
+const unsigned long c3 = U'a'; /* { dg-error "not declared" } */
+ /* { dg-error "expected ',' or ';'" "" { target *-*-* } 12 } */
+
+#define u 1 +
+#define U 2 +
+
+const unsigned short c5 = u'a';
+const unsigned long c6 = U'a';
+
+#undef u
+#undef U
+#define u "a"
+#define U "b"
+
+const void *s0 = u"a";
+const void *s1 = U"a";
+
+int main () {}
diff --git a/gcc/testsuite/g++.dg/ext/utf-mangle.C b/gcc/testsuite/g++.dg/ext/utf-mangle.C
new file mode 100644
index 0000000..bb5e382
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/utf-mangle.C
@@ -0,0 +1,14 @@
+// Contributed by Kris Van Hees <kris.van.hees@oracle.com>
+// Test the support for char16_t character constants.
+// { dg-do compile }
+// { dg-options "-std=c++0x" }
+
+void f0 (char16_t c) {}
+void f1 (char32_t c) {}
+void f2 (char16_t *s) {}
+void f3 (char32_t *s) {}
+
+// { dg-final { scan-assembler "_Z2f0u8char16_t:" } }
+// { dg-final { scan-assembler "_Z2f1u8char32_t:" } }
+// { dg-final { scan-assembler "_Z2f2Pu8char16_t:" } }
+// { dg-final { scan-assembler "_Z2f3Pu8char32_t:" } }
diff --git a/gcc/testsuite/g++.dg/ext/utf-typedef-cxx0x.C b/gcc/testsuite/g++.dg/ext/utf-typedef-cxx0x.C
new file mode 100644
index 0000000..789d08b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/utf-typedef-cxx0x.C
@@ -0,0 +1,7 @@
+/* Contributed by Kris Van Hees <kris.van.hees@oracle.com> */
+/* Ensure that a typedef to char16_t/char32_t issues a warning in c++0x. */
+/* { dg-do compile } */
+/* { dg-options "-std=c++0x" } */
+
+typedef short unsigned int char16_t; /* { dg-warning "redeclaration" } */
+typedef unsigned int char32_t; /* { dg-warning "redeclaration" } */
diff --git a/gcc/testsuite/g++.dg/ext/utf-typedef-cxx98.C b/gcc/testsuite/g++.dg/ext/utf-typedef-cxx98.C
new file mode 100644
index 0000000..8922856
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/utf-typedef-cxx98.C
@@ -0,0 +1,7 @@
+/* Contributed by Kris Van Hees <kris.van.hees@oracle.com> */
+/* Ensure that a typedef to char16_t/char32_t is fine in c++98. */
+/* { dg-do compile } */
+/* { dg-options "-std=c++98" } */
+
+typedef short unsigned int char16_t;
+typedef unsigned int char32_t;
diff --git a/gcc/testsuite/g++.dg/ext/utf-typespec.C b/gcc/testsuite/g++.dg/ext/utf-typespec.C
new file mode 100644
index 0000000..6a4af25
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/utf-typespec.C
@@ -0,0 +1,25 @@
+/* Contributed by Kris Van Hees <kris.van.hees@oracle.com> */
+/* Ensure that type specifiers are not allowed for char16_t/char32_t. */
+/* { dg-do compile } */
+/* { dg-options "-std=c++0x" } */
+
+signed char16_t c0; /* { dg-error "signed" } */
+signed char32_t c1; /* { dg-error "signed" } */
+unsigned char16_t c2; /* { dg-error "unsigned" } */
+unsigned char32_t c3; /* { dg-error "unsigned" } */
+
+short char16_t c4; /* { dg-error "short" } */
+long char16_t c5; /* { dg-error "long" } */
+short char32_t c6; /* { dg-error "short" } */
+long char32_t c7; /* { dg-error "long" } */
+
+signed short char16_t c8; /* { dg-error "signed" } */
+signed short char32_t c9; /* { dg-error "signed" } */
+signed long char16_t ca; /* { dg-error "signed" } */
+signed long char32_t cb; /* { dg-error "signed" } */
+unsigned short char16_t cc; /* { dg-error "unsigned" } */
+unsigned short char32_t cd; /* { dg-error "unsigned" } */
+unsigned long char16_t ce; /* { dg-error "unsigned" } */
+unsigned long char32_t cf; /* { dg-error "unsigned" } */
+
+int main () {}
diff --git a/gcc/testsuite/g++.dg/ext/utf16-1.C b/gcc/testsuite/g++.dg/ext/utf16-1.C
new file mode 100644
index 0000000..fa07de9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/utf16-1.C
@@ -0,0 +1,65 @@
+/* Contributed by Kris Van Hees <kris.van.hees@oracle.com> */
+/* Test the support for char16_t character constants. */
+/* { dg-do run } */
+/* { dg-options "-std=c++0x -Wall -Werror" } */
+
+extern "C" void abort (void);
+
+const static char16_t c0 = u'a';
+const static char16_t c1 = u'\0';
+const static char16_t c2 = u'\u0024';
+const static char16_t c3 = u'\u2029';
+const static char16_t c4 = u'\u8010';
+
+const static char16_t c5 = 'a';
+const static char16_t c6 = U'a';
+const static char16_t c7 = U'\u2029';
+const static char16_t c8 = U'\u8010';
+const static char16_t c9 = L'a';
+const static char16_t ca = L'\u2029';
+const static char16_t cb = L'\u8010';
+
+#define A 0x0061
+#define D 0x0024
+#define X 0x2029
+#define Y 0x8010
+
+int main ()
+{
+ if (sizeof (u'a') != sizeof (char16_t))
+ abort ();
+ if (sizeof (u'\0') != sizeof (char16_t))
+ abort ();
+ if (sizeof (u'\u0024') != sizeof (char16_t))
+ abort ();
+ if (sizeof (u'\u2029') != sizeof (char16_t))
+ abort ();
+ if (sizeof (u'\u8010') != sizeof (char16_t))
+ abort ();
+
+ if (c0 != A)
+ abort ();
+ if (c1 != 0x0000)
+ abort ();
+ if (c2 != D)
+ abort ();
+ if (c3 != X)
+ abort ();
+ if (c4 != Y)
+ abort ();
+
+ if (c5 != A)
+ abort ();
+ if (c6 != A)
+ abort ();
+ if (c7 != X)
+ abort ();
+ if (c8 != Y)
+ abort ();
+ if (c9 != A)
+ abort ();
+ if (ca != X)
+ abort ();
+ if (cb != Y)
+ abort ();
+}
diff --git a/gcc/testsuite/g++.dg/ext/utf16-2.C b/gcc/testsuite/g++.dg/ext/utf16-2.C
new file mode 100644
index 0000000..d7a6056
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/utf16-2.C
@@ -0,0 +1,30 @@
+/* Contributed by Kris Van Hees <kris.van.hees@oracle.com> */
+/* Test the support for char16_t* string literals. */
+/* { dg-do run } */
+/* { dg-options "-std=c++0x -Wall -Werror" } */
+
+extern "C" void abort (void);
+
+const static char16_t *s0 = u"ab";
+const static char16_t *s1 = u"a\u0024";
+const static char16_t *s2 = u"a\u2029";
+const static char16_t *s3 = u"a\U00064321";
+
+#define A 0x0061
+#define B 0x0062
+#define D 0x0024
+#define X 0x2029
+#define Y1 0xD950
+#define Y2 0xDF21
+
+int main ()
+{
+ if (s0[0] != A || s0[1] != B || s0[2] != 0x0000)
+ abort ();
+ if (s1[0] != A || s1[1] != D || s0[2] != 0x0000)
+ abort ();
+ if (s2[0] != A || s2[1] != X || s0[2] != 0x0000)
+ abort ();
+ if (s3[0] != A || s3[1] != Y1 || s3[2] != Y2 || s3[3] != 0x0000)
+ abort ();
+}
diff --git a/gcc/testsuite/g++.dg/ext/utf16-3.C b/gcc/testsuite/g++.dg/ext/utf16-3.C
new file mode 100644
index 0000000..183347b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/utf16-3.C
@@ -0,0 +1,47 @@
+/* Contributed by Kris Van Hees <kris.van.hees@oracle.com> */
+/* Test concatenation of char16_t* string literals. */
+/* { dg-do run } */
+/* { dg-options "-std=c++0x -Wall -Werror" } */
+
+extern "C" void abort (void);
+
+const static char16_t *s0 = u"a" u"b";
+
+const static char16_t *s1 = u"a" "b";
+const static char16_t *s2 = "a" u"b";
+const static char16_t *s3 = u"a" "\u2029";
+const static char16_t *s4 = "\u2029" u"b";
+const static char16_t *s5 = u"a" "\U00064321";
+const static char16_t *s6 = "\U00064321" u"b";
+
+#define A 0x0061
+#define B 0x0062
+#define X 0x2029
+#define Y1 0xD950
+#define Y2 0xDF21
+
+int main ()
+{
+ if (sizeof ((u"a" u"b")[0]) != sizeof (char16_t))
+ abort ();
+ if (sizeof ((u"a" "b")[0]) != sizeof (char16_t))
+ abort ();
+ if (sizeof (( "a" u"b")[0]) != sizeof (char16_t))
+ abort ();
+
+ if (s0[0] != A || s0[1] != B || s0[2] != 0x0000)
+ abort ();
+
+ if (s1[0] != A || s1[1] != B || s1[2] != 0x0000)
+ abort ();
+ if (s2[0] != A || s2[1] != B || s2[2] != 0x0000)
+ abort ();
+ if (s3[0] != A || s3[1] != X || s3[2] != 0x0000)
+ abort ();
+ if (s4[0] != X || s4[1] != B || s4[2] != 0x0000)
+ abort ();
+ if (s5[0] != A || s5[1] != Y1 || s5[2] != Y2 || s5[3] != 0x0000)
+ abort ();
+ if (s6[0] != Y1 || s6[1] != Y2 || s6[2] != B || s6[3] != 0x0000)
+ abort ();
+}
diff --git a/gcc/testsuite/g++.dg/ext/utf16-4.C b/gcc/testsuite/g++.dg/ext/utf16-4.C
new file mode 100644
index 0000000..0fb7459
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/utf16-4.C
@@ -0,0 +1,18 @@
+/* Contributed by Kris Van Hees <kris.van.hees@oracle.com> */
+/* Expected errors for char16_t character constants. */
+/* { dg-do compile } */
+/* { dg-options "-std=c++0x" } */
+
+const static char16_t c0 = u''; /* { dg-error "empty character" } */
+const static char16_t c1 = u'ab'; /* { dg-warning "constant too long" } */
+const static char16_t c2 = u'\U00064321'; /* { dg-warning "constant too long" } */
+
+const static char16_t c3 = 'a';
+const static char16_t c4 = U'a';
+const static char16_t c5 = U'\u2029';
+const static char16_t c6 = U'\U00064321'; /* { dg-warning "implicitly truncated" } */
+const static char16_t c7 = L'a';
+const static char16_t c8 = L'\u2029';
+const static char16_t c9 = L'\U00064321'; /* { dg-warning "implicitly truncated" } */
+
+int main () {}
diff --git a/gcc/testsuite/g++.dg/ext/utf32-1.C b/gcc/testsuite/g++.dg/ext/utf32-1.C
new file mode 100644
index 0000000..98465a0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/utf32-1.C
@@ -0,0 +1,42 @@
+/* Contributed by Kris Van Hees <kris.van.hees@oracle.com> */
+/* Test the support for char32_t character constants. */
+/* { dg-do run } */
+/* { dg-options "-std=c++0x -Wall -Werror" } */
+
+extern "C" void abort (void);
+
+const static char32_t c0 = U'a';
+const static char32_t c1 = U'\0';
+const static char32_t c2 = U'\u0024';
+const static char32_t c3 = U'\u2029';
+const static char32_t c4 = U'\U00064321';
+
+#define A 0x00000061
+#define D 0x00000024
+#define X 0x00002029
+#define Y 0x00064321
+
+int main ()
+{
+ if (sizeof (U'a') != sizeof (char32_t))
+ abort ();
+ if (sizeof (U'\0') != sizeof (char32_t))
+ abort ();
+ if (sizeof (U'\u0024') != sizeof (char32_t))
+ abort ();
+ if (sizeof (U'\u2029') != sizeof (char32_t))
+ abort ();
+ if (sizeof (U'\U00064321') != sizeof (char32_t))
+ abort ();
+
+ if (c0 != A)
+ abort ();
+ if (c1 != 0x0000)
+ abort ();
+ if (c2 != D)
+ abort ();
+ if (c3 != X)
+ abort ();
+ if (c4 != Y)
+ abort ();
+}
diff --git a/gcc/testsuite/g++.dg/ext/utf32-2.C b/gcc/testsuite/g++.dg/ext/utf32-2.C
new file mode 100644
index 0000000..e2256ba
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/utf32-2.C
@@ -0,0 +1,29 @@
+/* Contributed by Kris Van Hees <kris.van.hees@oracle.com> */
+/* Test the support for char32_t* string constants. */
+/* { dg-do run } */
+/* { dg-options "-std=c++0x -Wall -Werror" } */
+
+extern "C" void abort (void);
+
+const static char32_t *s0 = U"ab";
+const static char32_t *s1 = U"a\u0024";
+const static char32_t *s2 = U"a\u2029";
+const static char32_t *s3 = U"a\U00064321";
+
+#define A 0x00000061
+#define B 0x00000062
+#define D 0x00000024
+#define X 0x00002029
+#define Y 0x00064321
+
+int main ()
+{
+ if (s0[0] != A || s0[1] != B || s0[2] != 0x00000000)
+ abort ();
+ if (s1[0] != A || s1[1] != D || s0[2] != 0x00000000)
+ abort ();
+ if (s2[0] != A || s2[1] != X || s0[2] != 0x00000000)
+ abort ();
+ if (s3[0] != A || s3[1] != Y || s3[2] != 0x00000000)
+ abort ();
+}
diff --git a/gcc/testsuite/g++.dg/ext/utf32-3.C b/gcc/testsuite/g++.dg/ext/utf32-3.C
new file mode 100644
index 0000000..bba893c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/utf32-3.C
@@ -0,0 +1,46 @@
+/* Contributed by Kris Van Hees <kris.van.hees@oracle.com> */
+/* Test concatenation of char32_t* string literals. */
+/* { dg-do run } */
+/* { dg-options "-std=c++0x -Wall -Werror" } */
+
+extern "C" void abort (void);
+
+const static char32_t *s0 = U"a" U"b";
+
+const static char32_t *s1 = U"a" "b";
+const static char32_t *s2 = "a" U"b";
+const static char32_t *s3 = U"a" "\u2029";
+const static char32_t *s4 = "\u2029" U"b";
+const static char32_t *s5 = U"a" "\U00064321";
+const static char32_t *s6 = "\U00064321" U"b";
+
+#define A 0x00000061
+#define B 0x00000062
+#define X 0x00002029
+#define Y 0x00064321
+
+int main ()
+{
+ if (sizeof ((U"a" U"b")[0]) != sizeof (char32_t))
+ abort ();
+ if (sizeof ((U"a" "b")[0]) != sizeof (char32_t))
+ abort ();
+ if (sizeof (( "a" U"b")[0]) != sizeof (char32_t))
+ abort ();
+
+ if (s0[0] != A || s0[1] != B || s0[2] != 0x00000000)
+ abort ();
+
+ if (s1[0] != A || s1[1] != B || s1[2] != 0x00000000)
+ abort ();
+ if (s2[0] != A || s2[1] != B || s2[2] != 0x00000000)
+ abort ();
+ if (s3[0] != A || s3[1] != X || s3[2] != 0x00000000)
+ abort ();
+ if (s4[0] != X || s4[1] != B || s4[2] != 0x00000000)
+ abort ();
+ if (s5[0] != A || s5[1] != Y || s5[2] != 0x00000000)
+ abort ();
+ if (s6[0] != Y || s6[1] != B || s6[2] != 0x00000000)
+ abort ();
+}
diff --git a/gcc/testsuite/g++.dg/ext/utf32-4.C b/gcc/testsuite/g++.dg/ext/utf32-4.C
new file mode 100644
index 0000000..af2fa8d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/utf32-4.C
@@ -0,0 +1,18 @@
+/* Contributed by Kris Van Hees <kris.van.hees@oracle.com> */
+/* Expected errors for char32_t character constants. */
+/* { dg-do compile } */
+/* { dg-options "-std=c++0x" } */
+
+const static char32_t c0 = U''; /* { dg-error "empty character" } */
+const static char32_t c1 = U'ab'; /* { dg-warning "constant too long" } */
+const static char32_t c2 = U'\U00064321';
+
+const static char32_t c3 = 'a';
+const static char32_t c4 = u'a';
+const static char32_t c5 = u'\u2029';
+const static char32_t c6 = u'\U00064321'; /* { dg-warning "constant too long" } */
+const static char32_t c7 = L'a';
+const static char32_t c8 = L'\u2029';
+const static char32_t c9 = L'\U00064321';
+
+int main () {}
diff --git a/gcc/testsuite/gcc.dg/utf-badconcat.c b/gcc/testsuite/gcc.dg/utf-badconcat.c
new file mode 100644
index 0000000..61ce495
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/utf-badconcat.c
@@ -0,0 +1,22 @@
+/* Contributed by Kris Van Hees <kris.van.hees@oracle.com> */
+/* Test unsupported concatenation of char16_t/char32_t* string literals. */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu99" } */
+
+void *s0 = u"a" "b";
+void *s1 = "a" u"b";
+void *s2 = u"a" U"b"; /* { dg-error "non-standard concatenation" } */
+void *s3 = U"a" u"b"; /* { dg-error "non-standard concatenation" } */
+void *s4 = u"a" L"b"; /* { dg-error "non-standard concatenation" } */
+void *s5 = L"a" u"b"; /* { dg-error "non-standard concatenation" } */
+void *s6 = u"a" u"b";
+void *s7 = U"a" "b";
+void *s8 = "a" U"b";
+void *s9 = U"a" L"b"; /* { dg-error "non-standard concatenation" } */
+void *sa = L"a" U"b"; /* { dg-error "non-standard concatenation" } */
+void *sb = U"a" U"b";
+void *sc = L"a" "b";
+void *sd = "a" L"b";
+void *se = L"a" L"b";
+
+int main () {}
diff --git a/gcc/testsuite/gcc.dg/utf-cvt.c b/gcc/testsuite/gcc.dg/utf-cvt.c
new file mode 100644
index 0000000..e4bc624
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/utf-cvt.c
@@ -0,0 +1,49 @@
+/* Contributed by Kris Van Hees <kris.van.hees@oracle.com> */
+/* Test the char16_t and char32_t promotion rules. */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu99 -Wall -Wconversion -Wsign-conversion" } */
+
+typedef unsigned short char16_t;
+typedef unsigned int char32_t;
+
+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);
+
+void m (char16_t c0, char32_t c1)
+{
+ f_c (c0); /* { dg-warning "alter its value" } */
+ fsc (c0); /* { dg-warning "alter its value" } */
+ fuc (c0); /* { dg-warning "alter its value" } */
+ f_s (c0); /* { dg-warning "change the sign" } */
+ fss (c0); /* { dg-warning "change the sign" } */
+ fus (c0);
+ f_i (c0);
+ fsi (c0);
+ fui (c0);
+ f_l (c0);
+ fsl (c0);
+ ful (c0);
+
+ f_c (c1); /* { dg-warning "alter its value" } */
+ fsc (c1); /* { dg-warning "alter its value" } */
+ fuc (c1); /* { dg-warning "alter its value" } */
+ f_s (c1); /* { dg-warning "alter its value" } */
+ fss (c1); /* { dg-warning "alter its value" } */
+ fus (c1); /* { dg-warning "alter its value" } */
+ f_i (c1); /* { dg-warning "change the sign" } */
+ fsi (c1); /* { dg-warning "change the sign" } */
+ fui (c1);
+ f_l (c1); /* { dg-warning "change the sign" } */
+ fsl (c1); /* { dg-warning "change the sign" } */
+ ful (c1);
+}
diff --git a/gcc/testsuite/gcc.dg/utf-dflt.c b/gcc/testsuite/gcc.dg/utf-dflt.c
new file mode 100644
index 0000000..7281ef3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/utf-dflt.c
@@ -0,0 +1,25 @@
+/* Contributed by Kris Van Hees <kris.van.hees@oracle.com> */
+/* If not gnu99, the u and U prefixes should be parsed as separate tokens. */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+const unsigned short c0 = u'a'; /* { dg-error "undeclared" } */
+ /* { dg-error "expected ',' or ';'" "" { target *-*-* } 6 } */
+const unsigned long c1 = U'a'; /* { dg-error "undeclared" } */
+ /* { dg-error "expected ',' or ';'" "" { target *-*-* } 8 } */
+
+#define u 1 +
+#define U 2 +
+
+const unsigned short c2 = u'a';
+const unsigned long c3 = U'a';
+
+#undef u
+#undef U
+#define u "a"
+#define U "b"
+
+const void *s0 = u"a";
+const void *s1 = U"a";
+
+int main () {}
diff --git a/gcc/testsuite/gcc.dg/utf16-1.c b/gcc/testsuite/gcc.dg/utf16-1.c
new file mode 100644
index 0000000..b2c65c0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/utf16-1.c
@@ -0,0 +1,67 @@
+/* Contributed by Kris Van Hees <kris.van.hees@oracle.com> */
+/* Test the support for char16_t character constants. */
+/* { dg-do run } */
+/* { dg-options "-std=gnu99 -Wall -Werror" } */
+
+typedef short unsigned int char16_t;
+
+extern void abort (void);
+
+char16_t c0 = u'a';
+char16_t c1 = u'\0';
+char16_t c2 = u'\u0024';
+char16_t c3 = u'\u2029';
+char16_t c4 = u'\u8010';
+
+char16_t c5 = 'a';
+char16_t c6 = U'a';
+char16_t c7 = U'\u2029';
+char16_t c8 = U'\u8010';
+char16_t c9 = L'a';
+char16_t ca = L'\u2029';
+char16_t cb = L'\u8010';
+
+#define A 0x0061
+#define D 0x0024
+#define X 0x2029
+#define Y 0x8010
+
+int main ()
+{
+ if (sizeof (u'a') != sizeof (char16_t))
+ abort ();
+ if (sizeof (u'\0') != sizeof (char16_t))
+ abort ();
+ if (sizeof (u'\u0024') != sizeof (char16_t))
+ abort ();
+ if (sizeof (u'\u2029') != sizeof (char16_t))
+ abort ();
+ if (sizeof (u'\u8010') != sizeof (char16_t))
+ abort ();
+
+ if (c0 != A)
+ abort ();
+ if (c1 != 0x0000)
+ abort ();
+ if (c2 != D)
+ abort ();
+ if (c3 != X)
+ abort ();
+ if (c4 != Y)
+ abort ();
+
+ if (c5 != A)
+ abort ();
+ if (c6 != A)
+ abort ();
+ if (c7 != X)
+ abort ();
+ if (c8 != Y)
+ abort ();
+ if (c9 != A)
+ abort ();
+ if (ca != X)
+ abort ();
+ if (cb != Y)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.dg/utf16-2.c b/gcc/testsuite/gcc.dg/utf16-2.c
new file mode 100644
index 0000000..ad99a1a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/utf16-2.c
@@ -0,0 +1,32 @@
+/* Contributed by Kris Van Hees <kris.van.hees@oracle.com> */
+/* Test the support for char16_t* string literals. */
+/* { dg-do run } */
+/* { dg-options "-std=gnu99 -Wall -Werror" } */
+
+typedef short unsigned int char16_t;
+
+extern void abort (void);
+
+char16_t *s0 = u"ab";
+char16_t *s1 = u"a\u0024";
+char16_t *s2 = u"a\u2029";
+char16_t *s3 = u"a\U00064321";
+
+#define A 0x0061
+#define B 0x0062
+#define D 0x0024
+#define X 0x2029
+#define Y1 0xD950
+#define Y2 0xDF21
+
+int main ()
+{
+ if (s0[0] != A || s0[1] != B || s0[2] != 0x0000)
+ abort ();
+ if (s1[0] != A || s1[1] != D || s0[2] != 0x0000)
+ abort ();
+ if (s2[0] != A || s2[1] != X || s0[2] != 0x0000)
+ abort ();
+ if (s3[0] != A || s3[1] != Y1 || s3[2] != Y2 || s3[3] != 0x0000)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.dg/utf16-3.c b/gcc/testsuite/gcc.dg/utf16-3.c
new file mode 100644
index 0000000..d5e31b2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/utf16-3.c
@@ -0,0 +1,49 @@
+/* Contributed by Kris Van Hees <kris.van.hees@oracle.com> */
+/* Test concatenation of char16_t* string literals. */
+/* { dg-do run } */
+/* { dg-options "-std=gnu99 -Wall -Werror" } */
+
+typedef short unsigned int char16_t;
+
+extern void abort (void);
+
+char16_t *s0 = u"a" u"b";
+
+char16_t *s1 = u"a" "b";
+char16_t *s2 = "a" u"b";
+char16_t *s3 = u"a" "\u2029";
+char16_t *s4 = "\u2029" u"b";
+char16_t *s5 = u"a" "\U00064321";
+char16_t *s6 = "\U00064321" u"b";
+
+#define A 0x0061
+#define B 0x0062
+#define X 0x2029
+#define Y1 0xD950
+#define Y2 0xDF21
+
+int main ()
+{
+ if (sizeof ((u"a" u"b")[0]) != sizeof (char16_t))
+ abort ();
+ if (sizeof ((u"a" "b")[0]) != sizeof (char16_t))
+ abort ();
+ if (sizeof (( "a" u"b")[0]) != sizeof (char16_t))
+ abort ();
+
+ if (s0[0] != A || s0[1] != B || s0[2] != 0x0000)
+ abort ();
+
+ if (s1[0] != A || s1[1] != B || s1[2] != 0x0000)
+ abort ();
+ if (s2[0] != A || s2[1] != B || s2[2] != 0x0000)
+ abort ();
+ if (s3[0] != A || s3[1] != X || s3[2] != 0x0000)
+ abort ();
+ if (s4[0] != X || s4[1] != B || s4[2] != 0x0000)
+ abort ();
+ if (s5[0] != A || s5[1] != Y1 || s5[2] != Y2 || s5[3] != 0x0000)
+ abort ();
+ if (s6[0] != Y1 || s6[1] != Y2 || s6[2] != B || s6[3] != 0x0000)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.dg/utf16-4.c b/gcc/testsuite/gcc.dg/utf16-4.c
new file mode 100644
index 0000000..812c8d2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/utf16-4.c
@@ -0,0 +1,20 @@
+/* Contributed by Kris Van Hees <kris.van.hees@oracle.com> */
+/* Expected errors for char16_t character constants. */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu99" } */
+
+typedef short unsigned int char16_t;
+
+char16_t c0 = u''; /* { dg-error "empty character" } */
+char16_t c1 = u'ab'; /* { dg-warning "constant too long" } */
+char16_t c2 = u'\U00064321'; /* { dg-warning "constant too long" } */
+
+char16_t c3 = 'a';
+char16_t c4 = U'a';
+char16_t c5 = U'\u2029';
+char16_t c6 = U'\U00064321'; /* { dg-warning "implicitly truncated" } */
+char16_t c7 = L'a';
+char16_t c8 = L'\u2029';
+char16_t c9 = L'\U00064321'; /* { dg-warning "implicitly truncated" } */
+
+int main () {}
diff --git a/gcc/testsuite/gcc.dg/utf32-1.c b/gcc/testsuite/gcc.dg/utf32-1.c
new file mode 100644
index 0000000..1807d57
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/utf32-1.c
@@ -0,0 +1,44 @@
+/* Contributed by Kris Van Hees <kris.van.hees@oracle.com> */
+/* Test the support for char32_t character constants. */
+/* { dg-do run } */
+/* { dg-options "-std=gnu99 -Wall -Werror" } */
+
+typedef unsigned int char32_t;
+
+extern void abort (void);
+
+char32_t c0 = U'a';
+char32_t c1 = U'\0';
+char32_t c2 = U'\u0024';
+char32_t c3 = U'\u2029';
+char32_t c4 = U'\U00064321';
+
+#define A 0x00000061
+#define D 0x00000024
+#define X 0x00002029
+#define Y 0x00064321
+
+int main ()
+{
+ if (sizeof (U'a') != sizeof (char32_t))
+ abort ();
+ if (sizeof (U'\0') != sizeof (char32_t))
+ abort ();
+ if (sizeof (U'\u0024') != sizeof (char32_t))
+ abort ();
+ if (sizeof (U'\u2029') != sizeof (char32_t))
+ abort ();
+ if (sizeof (U'\U00064321') != sizeof (char32_t))
+ abort ();
+
+ if (c0 != A)
+ abort ();
+ if (c1 != 0x0000)
+ abort ();
+ if (c2 != D)
+ abort ();
+ if (c3 != X)
+ abort ();
+ if (c4 != Y)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.dg/utf32-2.c b/gcc/testsuite/gcc.dg/utf32-2.c
new file mode 100644
index 0000000..820eb8c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/utf32-2.c
@@ -0,0 +1,31 @@
+/* Contributed by Kris Van Hees <kris.van.hees@oracle.com> */
+/* Test the support for char32_t* string constants. */
+/* { dg-do run } */
+/* { dg-options "-std=gnu99 -Wall -Werror" } */
+
+typedef unsigned int char32_t;
+
+extern void abort (void);
+
+char32_t *s0 = U"ab";
+char32_t *s1 = U"a\u0024";
+char32_t *s2 = U"a\u2029";
+char32_t *s3 = U"a\U00064321";
+
+#define A 0x00000061
+#define B 0x00000062
+#define D 0x00000024
+#define X 0x00002029
+#define Y 0x00064321
+
+int main ()
+{
+ if (s0[0] != A || s0[1] != B || s0[2] != 0x00000000)
+ abort ();
+ if (s1[0] != A || s1[1] != D || s0[2] != 0x00000000)
+ abort ();
+ if (s2[0] != A || s2[1] != X || s0[2] != 0x00000000)
+ abort ();
+ if (s3[0] != A || s3[1] != Y || s3[2] != 0x00000000)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.dg/utf32-3.c b/gcc/testsuite/gcc.dg/utf32-3.c
new file mode 100644
index 0000000..20cbc78
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/utf32-3.c
@@ -0,0 +1,48 @@
+/* Contributed by Kris Van Hees <kris.van.hees@oracle.com> */
+/* Test concatenation of char32_t* string literals. */
+/* { dg-do run } */
+/* { dg-options "-std=gnu99 -Wall -Werror" } */
+
+typedef unsigned int char32_t;
+
+extern void abort (void);
+
+char32_t *s0 = U"a" U"b";
+
+char32_t *s1 = U"a" "b";
+char32_t *s2 = "a" U"b";
+char32_t *s3 = U"a" "\u2029";
+char32_t *s4 = "\u2029" U"b";
+char32_t *s5 = U"a" "\U00064321";
+char32_t *s6 = "\U00064321" U"b";
+
+#define A 0x00000061
+#define B 0x00000062
+#define X 0x00002029
+#define Y 0x00064321
+
+int main ()
+{
+ if (sizeof ((U"a" U"b")[0]) != sizeof (char32_t))
+ abort ();
+ if (sizeof ((U"a" "b")[0]) != sizeof (char32_t))
+ abort ();
+ if (sizeof (( "a" U"b")[0]) != sizeof (char32_t))
+ abort ();
+
+ if (s0[0] != A || s0[1] != B || s0[2] != 0x00000000)
+ abort ();
+
+ if (s1[0] != A || s1[1] != B || s1[2] != 0x00000000)
+ abort ();
+ if (s2[0] != A || s2[1] != B || s2[2] != 0x00000000)
+ abort ();
+ if (s3[0] != A || s3[1] != X || s3[2] != 0x00000000)
+ abort ();
+ if (s4[0] != X || s4[1] != B || s4[2] != 0x00000000)
+ abort ();
+ if (s5[0] != A || s5[1] != Y || s5[2] != 0x00000000)
+ abort ();
+ if (s6[0] != Y || s6[1] != B || s6[2] != 0x00000000)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.dg/utf32-4.c b/gcc/testsuite/gcc.dg/utf32-4.c
new file mode 100644
index 0000000..dd05a9a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/utf32-4.c
@@ -0,0 +1,20 @@
+/* Contributed by Kris Van Hees <kris.van.hees@oracle.com> */
+/* Expected errors for char32_t character constants. */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu99" } */
+
+typedef unsigned int char32_t;
+
+char32_t c0 = U''; /* { dg-error "empty character" } */
+char32_t c1 = U'ab'; /* { dg-warning "constant too long" } */
+char32_t c2 = U'\U00064321';
+
+char32_t c3 = 'a';
+char32_t c4 = u'a';
+char32_t c5 = u'\u2029';
+char32_t c6 = u'\U00064321'; /* { dg-warning "constant too long" } */
+char32_t c7 = L'a';
+char32_t c8 = L'\u2029';
+char32_t c9 = L'\U00064321';
+
+int main () {}