aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog25
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/cvt.c1
-rw-r--r--gcc/cp/decl.c4
-rw-r--r--gcc/cp/lex.c2
-rw-r--r--gcc/cp/mangle.c4
-rw-r--r--gcc/cp/parser.c16
-rw-r--r--gcc/cp/rtti.c2
-rw-r--r--gcc/cp/tree.c1
-rw-r--r--gcc/cp/typeck.c4
-rw-r--r--gcc/cp/typeck2.c57
11 files changed, 85 insertions, 32 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 82412a7..5d0ef12 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,28 @@
+2019-01-14 Tom Honermann <tom@honermann.net>
+
+ Implement P0482R5, char8_t: A type for UTF-8 characters and strings
+ * cvt.c (type_promotes_to): Handle char8_t promotion.
+ * decl.c (grokdeclarator): Handle invalid type specifier
+ combinations involving char8_t.
+ * lex.c (init_reswords): Add char8_t as a reserved word.
+ * mangle.c (write_builtin_type): Add name mangling for char8_t (Du).
+ * parser.c (cp_keyword_starts_decl_specifier_p)
+ (cp_parser_simple_type_specifier): Recognize char8_t as a simple
+ type specifier.
+ (cp_parser_string_literal): Use char8_array_type_node for the type
+ of CPP_UTF8STRING.
+ (cp_parser_set_decl_spec_type): Tolerate char8_t typedefs in system
+ headers.
+ * rtti.c (emit_support_tinfos): type_info support for char8_t.
+ * tree.c (char_type_p): Recognize char8_t as a character type.
+ * typeck.c (string_conv_p): Handle conversions of u8 string
+ literals of char8_t type.
+ (check_literal_operator_args): Handle UDLs with u8 string literals
+ of char8_t type.
+ * typeck2.c (ordinary_char_type_p): New.
+ (digest_init_r): Disallow initializing a char array with a u8 string
+ literal.
+
2019-01-14 Martin Liska <mliska@suse.cz>
PR gcov-profile/88263
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 5648946..6a20043 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7488,6 +7488,7 @@ extern tree store_init_value (tree, tree, vec<tree, va_gc>**, int);
extern tree split_nonconstant_init (tree, tree);
extern bool check_narrowing (tree, tree, tsubst_flags_t,
bool = false);
+extern bool ordinary_char_type_p (tree);
extern tree digest_init (tree, tree, tsubst_flags_t);
extern tree digest_init_flags (tree, tree, int, tsubst_flags_t);
extern tree digest_nsdmi_init (tree, tree, tsubst_flags_t);
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 449ce50..9142811 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -1877,6 +1877,7 @@ type_promotes_to (tree type)
wider. Scoped enums don't promote, but pretend they do for backward
ABI bug compatibility wrt varargs. */
else if (TREE_CODE (type) == ENUMERAL_TYPE
+ || type == char8_type_node
|| type == char16_type_node
|| type == char32_type_node
|| type == wchar_type_node)
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 6e75c3d..41972aa 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -10770,7 +10770,9 @@ grokdeclarator (const cp_declarator *declarator,
error_at (&richloc, "%<long%> and %<short%> specified together");
}
else if (TREE_CODE (type) != INTEGER_TYPE
- || type == char16_type_node || type == char32_type_node
+ || type == char8_type_node
+ || type == char16_type_node
+ || type == char32_type_node
|| ((long_p || short_p)
&& (explicit_char || explicit_intN)))
error_at (loc, "%qs specified with %qT", key, type);
diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c
index 36ffa37..369ecc0 100644
--- a/gcc/cp/lex.c
+++ b/gcc/cp/lex.c
@@ -233,6 +233,8 @@ init_reswords (void)
mask |= D_CXX_CONCEPTS;
if (!flag_tm)
mask |= D_TRANSMEM;
+ if (!flag_char8_t)
+ mask |= D_CXX_CHAR8_T;
if (flag_no_asm)
mask |= D_ASM | D_EXT;
if (flag_no_gnu_keywords)
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 919f7b3..00bde4e 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -2473,10 +2473,12 @@ write_builtin_type (tree type)
break;
case INTEGER_TYPE:
- /* TYPE may still be wchar_t, char16_t, or char32_t, since that
+ /* TYPE may still be wchar_t, char8_t, char16_t, or char32_t, since that
isn't in integer_type_nodes. */
if (type == wchar_type_node)
write_char ('w');
+ else if (type == char8_type_node)
+ write_string ("Du");
else if (type == char16_type_node)
write_string ("Ds");
else if (type == char32_type_node)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index be669f2..7d7b029 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -948,6 +948,7 @@ cp_keyword_starts_decl_specifier_p (enum rid keyword)
case RID_TYPENAME:
/* Simple type specifiers. */
case RID_CHAR:
+ case RID_CHAR8:
case RID_CHAR16:
case RID_CHAR32:
case RID_WCHAR:
@@ -4235,9 +4236,14 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok,
{
default:
case CPP_STRING:
- case CPP_UTF8STRING:
TREE_TYPE (value) = char_array_type_node;
break;
+ case CPP_UTF8STRING:
+ if (flag_char8_t)
+ TREE_TYPE (value) = char8_array_type_node;
+ else
+ TREE_TYPE (value) = char_array_type_node;
+ break;
case CPP_STRING16:
TREE_TYPE (value) = char16_array_type_node;
break;
@@ -17504,6 +17510,9 @@ cp_parser_simple_type_specifier (cp_parser* parser,
decl_specs->explicit_char_p = true;
type = char_type_node;
break;
+ case RID_CHAR8:
+ type = char8_type_node;
+ break;
case RID_CHAR16:
type = char16_type_node;
break;
@@ -28919,14 +28928,15 @@ cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs,
{
decl_specs->any_specifiers_p = true;
- /* If the user tries to redeclare bool, char16_t, char32_t, or wchar_t
- (with, for example, in "typedef int wchar_t;") we remember that
+ /* If the user tries to redeclare bool, char8_t, char16_t, char32_t, or
+ wchar_t (with, for example, in "typedef int wchar_t;") we remember that
this is what happened. In system headers, we ignore these
declarations so that G++ can work with system headers that are not
C++-safe. */
if (decl_spec_seq_has_spec_p (decl_specs, ds_typedef)
&& !type_definition_p
&& (type_spec == boolean_type_node
+ || type_spec == char8_type_node
|| type_spec == char16_type_node
|| type_spec == char32_type_node
|| type_spec == wchar_type_node)
diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c
index a6d32b9..c4aabea 100644
--- a/gcc/cp/rtti.c
+++ b/gcc/cp/rtti.c
@@ -1539,7 +1539,7 @@ emit_support_tinfos (void)
{
&void_type_node,
&boolean_type_node,
- &wchar_type_node, &char16_type_node, &char32_type_node,
+ &wchar_type_node, &char8_type_node, &char16_type_node, &char32_type_node,
&char_type_node, &signed_char_type_node, &unsigned_char_type_node,
&short_integer_type_node, &short_unsigned_type_node,
&integer_type_node, &unsigned_type_node,
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 4db89a4..5000216 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -5022,6 +5022,7 @@ char_type_p (tree type)
return (same_type_p (type, char_type_node)
|| same_type_p (type, unsigned_char_type_node)
|| same_type_p (type, signed_char_type_node)
+ || same_type_p (type, char8_type_node)
|| same_type_p (type, char16_type_node)
|| same_type_p (type, char32_type_node)
|| same_type_p (type, wchar_type_node));
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 43d2899..88e2cd6 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -2216,6 +2216,7 @@ string_conv_p (const_tree totype, const_tree exp, int warn)
t = TREE_TYPE (totype);
if (!same_type_p (t, char_type_node)
+ && !same_type_p (t, char8_type_node)
&& !same_type_p (t, char16_type_node)
&& !same_type_p (t, char32_type_node)
&& !same_type_p (t, wchar_type_node))
@@ -10288,6 +10289,7 @@ check_literal_operator_args (const_tree decl,
t = TYPE_MAIN_VARIANT (t);
if ((maybe_raw_p = same_type_p (t, char_type_node))
|| same_type_p (t, wchar_type_node)
+ || same_type_p (t, char8_type_node)
|| same_type_p (t, char16_type_node)
|| same_type_p (t, char32_type_node))
{
@@ -10320,6 +10322,8 @@ check_literal_operator_args (const_tree decl,
max_arity = 1;
else if (same_type_p (t, wchar_type_node))
max_arity = 1;
+ else if (same_type_p (t, char8_type_node))
+ max_arity = 1;
else if (same_type_p (t, char16_type_node))
max_arity = 1;
else if (same_type_p (t, char32_type_node))
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index ecc313b..cd43132 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -1026,6 +1026,17 @@ check_narrowing (tree type, tree init, tsubst_flags_t complain, bool const_only)
return ok;
}
+/* True iff TYPE is a C++2a "ordinary" character type. */
+
+bool
+ordinary_char_type_p (tree type)
+{
+ type = TYPE_MAIN_VARIANT (type);
+ return (type == char_type_node
+ || type == signed_char_type_node
+ || type == unsigned_char_type_node);
+}
+
/* Process the initializer INIT for a variable of type TYPE, emitting
diagnostics for invalid initializers and converting the initializer as
appropriate.
@@ -1091,36 +1102,30 @@ digest_init_r (tree type, tree init, int nested, int flags,
&& TREE_CODE (stripped_init) == STRING_CST)
{
tree char_type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (init)));
+ bool incompat_string_cst = false;
- if (TYPE_PRECISION (typ1) == BITS_PER_UNIT)
+ if (typ1 != char_type)
{
- if (char_type != char_type_node
- && char_type != signed_char_type_node
- && char_type != unsigned_char_type_node)
- {
- if (complain & tf_error)
- error_at (loc, "char-array initialized from wide string");
- return error_mark_node;
- }
+ /* The array element type does not match the initializing string
+ literal element type; this is only allowed when both types are
+ ordinary character type. There are no string literals of
+ signed or unsigned char type in the language, but we can get
+ them internally from converting braced-init-lists to
+ STRING_CST. */
+ if (ordinary_char_type_p (typ1)
+ && ordinary_char_type_p (char_type))
+ /* OK */;
+ else
+ incompat_string_cst = true;
}
- else
+
+ if (incompat_string_cst)
{
- if (char_type == char_type_node
- || char_type == signed_char_type_node
- || char_type == unsigned_char_type_node)
- {
- if (complain & tf_error)
- error_at (loc,
- "int-array initialized from non-wide string");
- return error_mark_node;
- }
- else if (char_type != typ1)
- {
- if (complain & tf_error)
- error_at (loc, "int-array initialized from incompatible "
- "wide string");
- return error_mark_node;
- }
+ if (complain & tf_error)
+ error_at (loc, "cannot initialize array of %qT from "
+ "a string literal with type array of %qT",
+ typ1, char_type);
+ return error_mark_node;
}
if (nested == 2 && !TYPE_DOMAIN (type))