diff options
author | Kris Van Hees <kris.van.hees@oracle.com> | 2008-04-18 13:58:08 +0000 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2008-04-18 09:58:08 -0400 |
commit | b6baa67d7947f7e4fc1481c87fcb55d54c56f0cf (patch) | |
tree | 7a2e1b1d5ba3460de2699e7cd1bc2b1739fc3119 /gcc | |
parent | 14a8726b8a54cf83654426302e4fe91877cad971 (diff) | |
download | gcc-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')
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 () {} |