@@ -2267,7 +2267,8 @@ static vec<tree, va_gc> *cp_parser_paren
(cp_parser *, int, bool, bool, bool *, location_t * = NULL,
bool = false);
/* Values for the second parameter of cp_parser_parenthesized_expression_list. */
-enum { non_attr = 0, normal_attr = 1, id_attr = 2, assume_attr = 3 };
+enum { non_attr = 0, normal_attr = 1, id_attr = 2, assume_attr = 3,
+ uneval_string_attr = 4 };
static void cp_parser_pseudo_destructor_name
(cp_parser *, tree, tree *, tree *);
static cp_expr cp_parser_unary_expression
@@ -4409,7 +4410,8 @@ cp_parser_identifier (cp_parser* parser)
return error_mark_node;
}
-/* Worker for cp_parser_string_literal and cp_parser_userdef_string_literal.
+/* Worker for cp_parser_string_literal, cp_parser_userdef_string_literal
+ and cp_parser_unevaluated_string_literal.
Do not call this directly; use either of the above.
Parse a sequence of adjacent string constants. Return a
@@ -4417,7 +4419,8 @@ cp_parser_identifier (cp_parser* parser)
constant. If TRANSLATE is true, translate the string to the
execution character set. If WIDE_OK is true, a wide string is
valid here. If UDL_OK is true, a string literal with user-defined
- suffix can be used in this context.
+ suffix can be used in this context. If UNEVAL is true, diagnose
+ numeric and conditional escape sequences in it if pedantic.
C++98 [lex.string] says that if a narrow string literal token is
adjacent to a wide string literal token, the behavior is undefined.
@@ -4431,7 +4434,7 @@ cp_parser_identifier (cp_parser* parser)
static cp_expr
cp_parser_string_literal_common (cp_parser *parser, bool translate,
bool wide_ok, bool udl_ok,
- bool lookup_udlit)
+ bool lookup_udlit, bool uneval)
{
tree value;
size_t count;
@@ -4584,6 +4587,8 @@ cp_parser_string_literal_common (cp_pars
cp_parser_error (parser, "a wide string is invalid in this context");
type = CPP_STRING;
}
+ if (uneval)
+ type = CPP_UNEVAL_STRING;
if ((translate ? cpp_interpret_string : cpp_interpret_string_notranslate)
(parse_in, strs, count, &istr, type))
@@ -4658,7 +4663,8 @@ cp_parser_string_literal (cp_parser *par
{
return cp_parser_string_literal_common (parser, translate, wide_ok,
/*udl_ok=*/false,
- /*lookup_udlit=*/false);
+ /*lookup_udlit=*/false,
+ /*uneval=*/false);
}
/* Parse a string literal or user defined string literal.
@@ -4673,7 +4679,21 @@ cp_parser_userdef_string_literal (cp_par
{
return cp_parser_string_literal_common (parser, /*translate=*/true,
/*wide_ok=*/true, /*udl_ok=*/true,
- lookup_udlit);
+ lookup_udlit, /*uneval=*/false);
+}
+
+/* Parse an unevaluated string literal.
+
+ unevaluated-string:
+ string-literal */
+
+static inline cp_expr
+cp_parser_unevaluated_string_literal (cp_parser *parser)
+{
+ return cp_parser_string_literal_common (parser, /*translate=*/false,
+ /*wide_ok=*/false, /*udl_ok=*/false,
+ /*lookup_udlit=*/false,
+ /*uneval=*/true);
}
/* Look up a literal operator with the name and the exact arguments. */
@@ -8578,6 +8598,8 @@ cp_parser_parenthesized_expression_list
expr = cp_lexer_consume_token (parser->lexer)->u.value;
else if (is_attribute_list == assume_attr)
expr = cp_parser_conditional_expression (parser);
+ else if (is_attribute_list == uneval_string_attr)
+ expr = cp_parser_unevaluated_string_literal (parser);
else
expr
= cp_parser_parenthesized_expression_list_elt (parser, cast_p,
@@ -16319,8 +16341,12 @@ cp_parser_linkage_specification (cp_pars
/* Look for the string-literal. */
cp_token *string_token = cp_lexer_peek_token (parser->lexer);
- tree linkage = cp_parser_string_literal (parser, /*translate=*/false,
- /*wide_ok=*/false);
+ tree linkage;
+ if (cxx_dialect >= cxx26)
+ linkage = cp_parser_unevaluated_string_literal (parser);
+ else
+ linkage = cp_parser_string_literal (parser, /*translate=*/false,
+ /*wide_ok=*/false);
/* Transform the literal into an identifier. If the literal is a
wide-character string, or contains embedded NULs, then we can't
@@ -16449,8 +16475,11 @@ cp_parser_static_assert (cp_parser *pars
cp_parser_require (parser, CPP_COMMA, RT_COMMA);
/* Parse the string-literal message. */
- message = cp_parser_string_literal (parser, /*translate=*/false,
- /*wide_ok=*/true);
+ if (cxx_dialect >= cxx26)
+ message = cp_parser_unevaluated_string_literal (parser);
+ else
+ message = cp_parser_string_literal (parser, /*translate=*/false,
+ /*wide_ok=*/true);
/* A `)' completes the static assertion. */
if (!parens.require_close (parser))
@@ -29442,6 +29471,11 @@ cp_parser_std_attribute (cp_parser *pars
&& attribute_takes_identifier_p (attr_id))
/* A GNU attribute that takes an identifier in parameter. */
attr_flag = id_attr;
+ else if (attr_ns == NULL_TREE
+ && cxx_dialect >= cxx26
+ && (is_attribute_p ("deprecated", attr_id)
+ || is_attribute_p ("nodiscard", attr_id)))
+ attr_flag = uneval_string_attr;
/* If this is a fake attribute created to handle -Wno-attributes,
we must skip parsing the arguments. */
@@ -0,0 +1,103 @@
+// C++26 P2361R6 - Unevaluated strings
+// { dg-do compile { target c++26 } }
+
+static_assert (true, "foo");
+static_assert (true, "foo" " " "bar");
+static_assert (true, "\u01FC\U000001FC\u{1FC}\N{LATIN CAPITAL LETTER AE WITH ACUTE}\\\'\"\?\a\b\f\n\r\t\v");
+static_assert (true, L"foo"); // { dg-error "a wide string is invalid in this context" }
+static_assert (true, u"foo"); // { dg-error "a wide string is invalid in this context" }
+static_assert (true, U"foo"); // { dg-error "a wide string is invalid in this context" }
+static_assert (true, u8"foo"); // { dg-error "a wide string is invalid in this context" }
+static_assert (true, L"fo" "o"); // { dg-error "a wide string is invalid in this context" }
+static_assert (true, u"fo" "o"); // { dg-error "a wide string is invalid in this context" }
+static_assert (true, U"fo" "o"); // { dg-error "a wide string is invalid in this context" }
+static_assert (true, u8"fo" "o"); // { dg-error "a wide string is invalid in this context" }
+static_assert (true, "fo" L"o"); // { dg-error "a wide string is invalid in this context" }
+static_assert (true, "fo" u"o"); // { dg-error "a wide string is invalid in this context" }
+static_assert (true, "fo" U"o"); // { dg-error "a wide string is invalid in this context" }
+static_assert (true, "fo" u8"o"); // { dg-error "a wide string is invalid in this context" }
+static_assert (true, "\0"); // { dg-error "numeric escape sequence in unevaluated string" }
+static_assert (true, "\17"); // { dg-error "numeric escape sequence in unevaluated string" }
+static_assert (true, "\x20"); // { dg-error "numeric escape sequence in unevaluated string" }
+static_assert (true, "\o{17}"); // { dg-error "numeric escape sequence in unevaluated string" }
+static_assert (true, "\x{20}"); // { dg-error "numeric escape sequence in unevaluated string" }
+static_assert (true, "\h"); // { dg-error "unknown escape sequence" }
+
+extern "C" "+" "+" int f0 ();
+extern "C" int f1 ();
+extern "C" { int f2 (); };
+extern L"C" int f3 (); // { dg-error "a wide string is invalid in this context" }
+extern L"C" { int f4 (); } // { dg-error "a wide string is invalid in this context" }
+extern u"C" int f5 (); // { dg-error "a wide string is invalid in this context" }
+extern u"C" { int f6 (); } // { dg-error "a wide string is invalid in this context" }
+extern U"C" int f7 (); // { dg-error "a wide string is invalid in this context" }
+extern U"C" { int f8 (); } // { dg-error "a wide string is invalid in this context" }
+extern u8"C" int f9 (); // { dg-error "a wide string is invalid in this context" }
+extern u8"C" { int f10 (); } // { dg-error "a wide string is invalid in this context" }
+extern "\x43" int f11 (); // { dg-error "numeric escape sequence in unevaluated string" }
+extern "\x{43}" { int f12 (); } // { dg-error "numeric escape sequence in unevaluated string" }
+extern "\103" int f13 (); // { dg-error "numeric escape sequence in unevaluated string" }
+extern "\o{0103}" { int f14 (); } // { dg-error "numeric escape sequence in unevaluated string" }
+
+[[deprecated ("foo")]] int g0 ();
+[[deprecated ("foo" " " "bar")]] int g1 ();
+[[deprecated ("\u01FC\U000001FC\u{1FC}\N{LATIN CAPITAL LETTER AE WITH ACUTE}\\\'\"\?\a\b\f\n\r\t\v")]] int g2 ();
+[[deprecated (L"foo")]] int g3 (); // { dg-error "a wide string is invalid in this context" }
+[[deprecated (u"foo")]] int g4 (); // { dg-error "a wide string is invalid in this context" }
+[[deprecated (U"foo")]] int g5 (); // { dg-error "a wide string is invalid in this context" }
+[[deprecated (u8"foo")]] int g6 (); // { dg-error "a wide string is invalid in this context" }
+[[deprecated (L"fo" "o")]] int g7 (); // { dg-error "a wide string is invalid in this context" }
+[[deprecated (u"fo" "o")]] int g8 (); // { dg-error "a wide string is invalid in this context" }
+[[deprecated (U"fo" "o")]] int g9 (); // { dg-error "a wide string is invalid in this context" }
+[[deprecated (u8"fo" "o")]] int g10 (); // { dg-error "a wide string is invalid in this context" }
+[[deprecated ("fo" L"o")]] int g11 (); // { dg-error "a wide string is invalid in this context" }
+[[deprecated ("fo" u"o")]] int g12 (); // { dg-error "a wide string is invalid in this context" }
+[[deprecated ("fo" U"o")]] int g13 (); // { dg-error "a wide string is invalid in this context" }
+[[deprecated ("fo" u8"o")]] int g14 (); // { dg-error "a wide string is invalid in this context" }
+[[deprecated ("\0")]] int g15 (); // { dg-error "numeric escape sequence in unevaluated string" }
+[[deprecated ("\17")]] int g16 (); // { dg-error "numeric escape sequence in unevaluated string" }
+[[deprecated ("\x20")]] int g17 (); // { dg-error "numeric escape sequence in unevaluated string" }
+[[deprecated ("\o{17}")]] int g18 (); // { dg-error "numeric escape sequence in unevaluated string" }
+[[deprecated ("\x{20}")]] int g19 (); // { dg-error "numeric escape sequence in unevaluated string" }
+[[deprecated ("\h")]] int g20 (); // { dg-error "unknown escape sequence" }
+
+[[nodiscard ("foo")]] int h0 ();
+[[nodiscard ("foo" " " "bar")]] int h1 ();
+[[nodiscard ("\u01FC\U000001FC\u{1FC}\N{LATIN CAPITAL LETTER AE WITH ACUTE}\\\'\"\?\a\b\f\n\r\t\v")]] int h2 ();
+[[nodiscard (L"foo")]] int h3 (); // { dg-error "a wide string is invalid in this context" }
+[[nodiscard (u"foo")]] int h4 (); // { dg-error "a wide string is invalid in this context" }
+[[nodiscard (U"foo")]] int h5 (); // { dg-error "a wide string is invalid in this context" }
+[[nodiscard (u8"foo")]] int h6 (); // { dg-error "a wide string is invalid in this context" }
+[[nodiscard (L"fo" "o")]] int h7 (); // { dg-error "a wide string is invalid in this context" }
+[[nodiscard (u"fo" "o")]] int h8 (); // { dg-error "a wide string is invalid in this context" }
+[[nodiscard (U"fo" "o")]] int h9 (); // { dg-error "a wide string is invalid in this context" }
+[[nodiscard (u8"fo" "o")]] int h10 (); // { dg-error "a wide string is invalid in this context" }
+[[nodiscard ("fo" L"o")]] int h11 (); // { dg-error "a wide string is invalid in this context" }
+[[nodiscard ("fo" u"o")]] int h12 (); // { dg-error "a wide string is invalid in this context" }
+[[nodiscard ("fo" U"o")]] int h13 (); // { dg-error "a wide string is invalid in this context" }
+[[nodiscard ("fo" u8"o")]] int h14 (); // { dg-error "a wide string is invalid in this context" }
+[[nodiscard ("\0")]] int h15 (); // { dg-error "numeric escape sequence in unevaluated string" }
+[[nodiscard ("\17")]] int h16 (); // { dg-error "numeric escape sequence in unevaluated string" }
+[[nodiscard ("\x20")]] int h17 (); // { dg-error "numeric escape sequence in unevaluated string" }
+[[nodiscard ("\o{17}")]] int h18 (); // { dg-error "numeric escape sequence in unevaluated string" }
+[[nodiscard ("\x{20}")]] int h19 (); // { dg-error "numeric escape sequence in unevaluated string" }
+[[nodiscard ("\h")]] int h20 (); // { dg-error "unknown escape sequence" }
+
+float operator "" _my0 (const char *);
+float operator "" "" _my1 (const char *);
+float operator L"" _my2 (const char *); // { dg-error "invalid encoding prefix in literal operator" }
+float operator u"" _my3 (const char *); // { dg-error "invalid encoding prefix in literal operator" }
+float operator U"" _my4 (const char *); // { dg-error "invalid encoding prefix in literal operator" }
+float operator u8"" _my5 (const char *); // { dg-error "invalid encoding prefix in literal operator" }
+float operator L"" "" _my6 (const char *); // { dg-error "invalid encoding prefix in literal operator" }
+float operator u"" "" _my7 (const char *); // { dg-error "invalid encoding prefix in literal operator" }
+float operator U"" "" _my8 (const char *); // { dg-error "invalid encoding prefix in literal operator" }
+float operator u8"" "" _my9 (const char *); // { dg-error "invalid encoding prefix in literal operator" }
+float operator "" L"" _my10 (const char *); // { dg-error "invalid encoding prefix in literal operator" }
+float operator "" u"" _my11 (const char *); // { dg-error "invalid encoding prefix in literal operator" }
+float operator "" U"" _my12 (const char *); // { dg-error "invalid encoding prefix in literal operator" }
+float operator "" u8"" _my13 (const char *); // { dg-error "invalid encoding prefix in literal operator" }
+float operator "\0" _my14 (const char *); // { dg-error "expected empty string after 'operator' keyword" }
+float operator "\x00" _my15 (const char *); // { dg-error "expected empty string after 'operator' keyword" }
+float operator "\h" _my16 (const char *); // { dg-error "expected empty string after 'operator' keyword" }
+ // { dg-error "unknown escape sequence" "" { target *-*-* } .-1 }
@@ -0,0 +1,110 @@
+// C++26 P2361R6 - Unevaluated strings
+// { dg-do compile { target { c++11 && c++23_down } } }
+// { dg-options "-pedantic" }
+
+static_assert (true, "foo");
+static_assert (true, "foo" " " "bar");
+static_assert (true, "\u01FC\U000001FC\u{1FC}\N{LATIN CAPITAL LETTER AE WITH ACUTE}\\\'\"\?\a\b\f\n\r\t\v");
+// { dg-warning "delimited escape sequences are only valid in" "" { target c++20_down } .-1 }
+// { dg-warning "named universal character escapes are only valid in" "" { target c++20_down } .-2 }
+static_assert (true, L"foo");
+static_assert (true, u"foo");
+static_assert (true, U"foo");
+static_assert (true, u8"foo");
+static_assert (true, L"fo" "o");
+static_assert (true, u"fo" "o");
+static_assert (true, U"fo" "o");
+static_assert (true, u8"fo" "o");
+static_assert (true, "fo" L"o");
+static_assert (true, "fo" u"o");
+static_assert (true, "fo" U"o");
+static_assert (true, "fo" u8"o");
+static_assert (true, "\0");
+static_assert (true, "\17");
+static_assert (true, "\x20");
+static_assert (true, "\o{17}"); // { dg-warning "delimited escape sequences are only valid in" "" { target c++20_down } }
+static_assert (true, "\x{20}"); // { dg-warning "delimited escape sequences are only valid in" "" { target c++20_down } }
+static_assert (true, "\h"); // { dg-warning "unknown escape sequence" }
+
+extern "C" "+" "+" int f0 ();
+extern "C" int f1 ();
+extern "C" { int f2 (); };
+extern L"C" int f3 (); // { dg-error "a wide string is invalid in this context" }
+extern L"C" { int f4 (); } // { dg-error "a wide string is invalid in this context" }
+extern u"C" int f5 (); // { dg-error "a wide string is invalid in this context" }
+extern u"C" { int f6 (); } // { dg-error "a wide string is invalid in this context" }
+extern U"C" int f7 (); // { dg-error "a wide string is invalid in this context" }
+extern U"C" { int f8 (); } // { dg-error "a wide string is invalid in this context" }
+extern u8"C" int f9 (); // { dg-error "a wide string is invalid in this context" }
+extern u8"C" { int f10 (); } // { dg-error "a wide string is invalid in this context" }
+extern "\x43" int f11 ();
+extern "\x{43}" { int f12 (); } // { dg-warning "delimited escape sequences are only valid in" "" { target c++20_down } }
+extern "\103" int f13 ();
+extern "\o{0103}" { int f14 (); } // { dg-warning "delimited escape sequences are only valid in" "" { target c++20_down } }
+
+[[deprecated ("foo")]] int g0 ();
+[[deprecated ("foo" " " "bar")]] int g1 ();
+[[deprecated ("\u01FC\U000001FC\u{1FC}\N{LATIN CAPITAL LETTER AE WITH ACUTE}\\\'\"\?\a\b\f\n\r\t\v")]] int g2 ();
+// { dg-warning "delimited escape sequences are only valid in" "" { target c++20_down } .-1 }
+// { dg-warning "named universal character escapes are only valid in" "" { target c++20_down } .-2 }
+[[deprecated (L"foo")]] int g3 ();
+[[deprecated (u"foo")]] int g4 ();
+[[deprecated (U"foo")]] int g5 ();
+[[deprecated (u8"foo")]] int g6 ();
+[[deprecated (L"fo" "o")]] int g7 ();
+[[deprecated (u"fo" "o")]] int g8 ();
+[[deprecated (U"fo" "o")]] int g9 ();
+[[deprecated (u8"fo" "o")]] int g10 ();
+[[deprecated ("fo" L"o")]] int g11 ();
+[[deprecated ("fo" u"o")]] int g12 ();
+[[deprecated ("fo" U"o")]] int g13 ();
+[[deprecated ("fo" u8"o")]] int g14 ();
+[[deprecated ("\0")]] int g15 ();
+[[deprecated ("\17")]] int g16 ();
+[[deprecated ("\x20")]] int g17 ();
+[[deprecated ("\o{17}")]] int g18 (); // { dg-warning "delimited escape sequences are only valid in" "" { target c++20_down } }
+[[deprecated ("\x{20}")]] int g19 (); // { dg-warning "delimited escape sequences are only valid in" "" { target c++20_down } }
+[[deprecated ("\h")]] int g20 (); // { dg-warning "unknown escape sequence" }
+
+[[nodiscard ("foo")]] int h0 ();
+[[nodiscard ("foo" " " "bar")]] int h1 ();
+[[nodiscard ("\u01FC\U000001FC\u{1FC}\N{LATIN CAPITAL LETTER AE WITH ACUTE}\\\'\"\?\a\b\f\n\r\t\v")]] int h2 ();
+// { dg-warning "delimited escape sequences are only valid in" "" { target c++20_down } .-1 }
+// { dg-warning "named universal character escapes are only valid in" "" { target c++20_down } .-2 }
+[[nodiscard (L"foo")]] int h3 ();
+[[nodiscard (u"foo")]] int h4 ();
+[[nodiscard (U"foo")]] int h5 ();
+[[nodiscard (u8"foo")]] int h6 ();
+[[nodiscard (L"fo" "o")]] int h7 ();
+[[nodiscard (u"fo" "o")]] int h8 ();
+[[nodiscard (U"fo" "o")]] int h9 ();
+[[nodiscard (u8"fo" "o")]] int h10 ();
+[[nodiscard ("fo" L"o")]] int h11 ();
+[[nodiscard ("fo" u"o")]] int h12 ();
+[[nodiscard ("fo" U"o")]] int h13 ();
+[[nodiscard ("fo" u8"o")]] int h14 ();
+[[nodiscard ("\0")]] int h15 ();
+[[nodiscard ("\17")]] int h16 ();
+[[nodiscard ("\x20")]] int h17 ();
+[[nodiscard ("\o{17}")]] int h18 (); // { dg-warning "delimited escape sequences are only valid in" "" { target c++20_down } }
+[[nodiscard ("\x{20}")]] int h19 (); // { dg-warning "delimited escape sequences are only valid in" "" { target c++20_down } }
+[[nodiscard ("\h")]] int h20 (); // { dg-warning "unknown escape sequence" }
+
+float operator "" _my0 (const char *);
+float operator "" "" _my1 (const char *);
+float operator L"" _my2 (const char *); // { dg-error "invalid encoding prefix in literal operator" }
+float operator u"" _my3 (const char *); // { dg-error "invalid encoding prefix in literal operator" }
+float operator U"" _my4 (const char *); // { dg-error "invalid encoding prefix in literal operator" }
+float operator u8"" _my5 (const char *); // { dg-error "invalid encoding prefix in literal operator" }
+float operator L"" "" _my6 (const char *); // { dg-error "invalid encoding prefix in literal operator" }
+float operator u"" "" _my7 (const char *); // { dg-error "invalid encoding prefix in literal operator" }
+float operator U"" "" _my8 (const char *); // { dg-error "invalid encoding prefix in literal operator" }
+float operator u8"" "" _my9 (const char *); // { dg-error "invalid encoding prefix in literal operator" }
+float operator "" L"" _my10 (const char *); // { dg-error "invalid encoding prefix in literal operator" }
+float operator "" u"" _my11 (const char *); // { dg-error "invalid encoding prefix in literal operator" }
+float operator "" U"" _my12 (const char *); // { dg-error "invalid encoding prefix in literal operator" }
+float operator "" u8"" _my13 (const char *); // { dg-error "invalid encoding prefix in literal operator" "" { target c++20 } }
+float operator "\0" _my14 (const char *); // { dg-error "expected empty string after 'operator' keyword" }
+float operator "\x00" _my15 (const char *); // { dg-error "expected empty string after 'operator' keyword" }
+float operator "\h" _my16 (const char *); // { dg-error "expected empty string after 'operator' keyword" }
+ // { dg-warning "unknown escape sequence" "" { target *-*-* } .-1 }
@@ -13,7 +13,7 @@ void operator""_x(const char *, decltype
extern "C"_x { void g(); } // { dg-error "before user-defined string literal" }
static_assert(true, "foo"_x); // { dg-error "string literal with user-defined suffix is invalid in this context|expected" }
-[[deprecated("oof"_x)]]
+[[deprecated("oof"_x)]] // { dg-error "string literal with user-defined suffix is invalid in this context" "" { target c++26 } }
void
lol () // { dg-error "not a string" }
{
@@ -129,17 +129,18 @@ struct _cpp_file;
TK(UTF8STRING, LITERAL) /* u8"string" */ \
TK(OBJC_STRING, LITERAL) /* @"string" - Objective-C */ \
TK(HEADER_NAME, LITERAL) /* <stdio.h> in #include */ \
+ TK(UNEVAL_STRING, LITERAL) /* unevaluated "string" - C++26 */ \
\
- TK(CHAR_USERDEF, LITERAL) /* 'char'_suffix - C++-0x */ \
- TK(WCHAR_USERDEF, LITERAL) /* L'char'_suffix - C++-0x */ \
- TK(CHAR16_USERDEF, LITERAL) /* u'char'_suffix - C++-0x */ \
- TK(CHAR32_USERDEF, LITERAL) /* U'char'_suffix - C++-0x */ \
- TK(UTF8CHAR_USERDEF, LITERAL) /* u8'char'_suffix - C++-0x */ \
- TK(STRING_USERDEF, LITERAL) /* "string"_suffix - C++-0x */ \
- TK(WSTRING_USERDEF, LITERAL) /* L"string"_suffix - C++-0x */ \
- TK(STRING16_USERDEF, LITERAL) /* u"string"_suffix - C++-0x */ \
- TK(STRING32_USERDEF, LITERAL) /* U"string"_suffix - C++-0x */ \
- TK(UTF8STRING_USERDEF,LITERAL) /* u8"string"_suffix - C++-0x */ \
+ TK(CHAR_USERDEF, LITERAL) /* 'char'_suffix - C++11 */ \
+ TK(WCHAR_USERDEF, LITERAL) /* L'char'_suffix - C++11 */ \
+ TK(CHAR16_USERDEF, LITERAL) /* u'char'_suffix - C++11 */ \
+ TK(CHAR32_USERDEF, LITERAL) /* U'char'_suffix - C++11 */ \
+ TK(UTF8CHAR_USERDEF, LITERAL) /* u8'char'_suffix - C++11 */ \
+ TK(STRING_USERDEF, LITERAL) /* "string"_suffix - C++11 */ \
+ TK(WSTRING_USERDEF, LITERAL) /* L"string"_suffix - C++11 */ \
+ TK(STRING16_USERDEF, LITERAL) /* u"string"_suffix - C++11 */ \
+ TK(STRING32_USERDEF, LITERAL) /* U"string"_suffix - C++11 */ \
+ TK(UTF8STRING_USERDEF,LITERAL) /* u8"string"_suffix - C++11 */ \
\
TK(COMMENT, LITERAL) /* Only if output comments. */ \
/* SPELL_LITERAL happens to DTRT. */ \
@@ -2156,7 +2156,7 @@ static const uchar *
convert_escape (cpp_reader *pfile, const uchar *from, const uchar *limit,
struct _cpp_strbuf *tbuf, struct cset_converter cvt,
cpp_string_location_reader *loc_reader,
- cpp_substring_ranges *ranges)
+ cpp_substring_ranges *ranges, bool uneval)
{
/* Values of \a \b \e \f \n \r \t \v respectively. */
#if HOST_CHARSET == HOST_CHARSET_ASCII
@@ -2183,12 +2183,20 @@ convert_escape (cpp_reader *pfile, const
char_range, loc_reader, ranges);
case 'x':
+ if (uneval && CPP_PEDANTIC (pfile))
+ cpp_error (pfile, CPP_DL_PEDWARN,
+ "numeric escape sequence in unevaluated string: "
+ "'\\%c'", (int) c);
return convert_hex (pfile, from, limit, tbuf, cvt,
char_range, loc_reader, ranges);
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
case 'o':
+ if (uneval && CPP_PEDANTIC (pfile))
+ cpp_error (pfile, CPP_DL_PEDWARN,
+ "numeric escape sequence in unevaluated string: "
+ "'\\%c'", (int) c);
return convert_oct (pfile, from, limit, tbuf, cvt,
char_range, loc_reader, ranges);
@@ -2296,7 +2304,7 @@ converter_for_type (cpp_reader *pfile, e
static bool
cpp_interpret_string_1 (cpp_reader *pfile, const cpp_string *from, size_t count,
- cpp_string *to, enum cpp_ttype type,
+ cpp_string *to, enum cpp_ttype type,
cpp_string_location_reader *loc_readers,
cpp_substring_ranges *out)
{
@@ -2427,7 +2435,7 @@ cpp_interpret_string_1 (cpp_reader *pfil
struct _cpp_strbuf *tbuf_ptr = to ? &tbuf : NULL;
p = convert_escape (pfile, p + 1, limit, tbuf_ptr, cvt,
- loc_reader, out);
+ loc_reader, out, type == CPP_UNEVAL_STRING);
}
}
@@ -2465,7 +2473,7 @@ cpp_interpret_string_1 (cpp_reader *pfil
false for failure. */
bool
cpp_interpret_string (cpp_reader *pfile, const cpp_string *from, size_t count,
- cpp_string *to, enum cpp_ttype type)
+ cpp_string *to, enum cpp_ttype type)
{
return cpp_interpret_string_1 (pfile, from, count, to, type, NULL, NULL);
}
@@ -2548,7 +2556,7 @@ cpp_interpret_string_ranges (cpp_reader
bool
cpp_interpret_string_notranslate (cpp_reader *pfile, const cpp_string *from,
size_t count, cpp_string *to,
- enum cpp_ttype type ATTRIBUTE_UNUSED)
+ enum cpp_ttype type)
{
struct cset_converter save_narrow_cset_desc = pfile->narrow_cset_desc;
bool retval;
@@ -2557,7 +2565,9 @@ cpp_interpret_string_notranslate (cpp_re
pfile->narrow_cset_desc.cd = (iconv_t) -1;
pfile->narrow_cset_desc.width = CPP_OPTION (pfile, char_precision);
- retval = cpp_interpret_string (pfile, from, count, to, CPP_STRING);
+ retval = cpp_interpret_string (pfile, from, count, to,
+ type == CPP_UNEVAL_STRING
+ ? CPP_UNEVAL_STRING : CPP_STRING);
pfile->narrow_cset_desc = save_narrow_cset_desc;
return retval;