diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 5f1390435ccf67407d5cfb08e15a22ab50ed8122..20e1836590653a666a0cddd12442279f6a88ad06 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -2324,7 +2324,8 @@ static vec<tree, va_gc> *cp_parser_parenthesized_expression_list (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 @@ -4467,7 +4468,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 @@ -4475,7 +4477,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. @@ -4489,7 +4492,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; @@ -4642,6 +4645,8 @@ cp_parser_string_literal_common (cp_parser *parser, bool translate, 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)) @@ -4716,7 +4721,8 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok) { 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. @@ -4731,7 +4737,21 @@ cp_parser_userdef_string_literal (cp_parser *parser, bool lookup_udlit) { 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. */ @@ -8658,6 +8678,8 @@ cp_parser_parenthesized_expression_list (cp_parser* parser, 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, @@ -16513,8 +16535,12 @@ cp_parser_linkage_specification (cp_parser* parser, tree prefix_attr) /* 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 @@ -16643,8 +16669,11 @@ cp_parser_static_assert (cp_parser *parser, bool member_p) 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)) @@ -29650,6 +29679,11 @@ cp_parser_std_attribute (cp_parser *parser, tree attr_ns) && 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. */ diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-error1.C b/gcc/testsuite/g++.dg/cpp0x/udlit-error1.C index 66e300e350f11cb154cf9db83c319415d30c7954..40566e0572f31de5ad7750f4075488ae3065285b 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-error1.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-error1.C @@ -13,7 +13,7 @@ void operator""_x(const char *, decltype(sizeof(0))); 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" } { diff --git a/gcc/testsuite/g++.dg/cpp26/unevalstr1.C b/gcc/testsuite/g++.dg/cpp26/unevalstr1.C new file mode 100644 index 0000000000000000000000000000000000000000..3220cf04937ee3f05f48da686f3423df47e56d61 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/unevalstr1.C @@ -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 } diff --git a/gcc/testsuite/g++.dg/cpp26/unevalstr2.C b/gcc/testsuite/g++.dg/cpp26/unevalstr2.C new file mode 100644 index 0000000000000000000000000000000000000000..f719f25d6df8a8ecce5e9022d9b7477501877d07 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/unevalstr2.C @@ -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 } diff --git a/libcpp/charset.cc b/libcpp/charset.cc index 7b625c9956a62d82efb44ecf870c5bc90f55cebb..d5a027502cd6980831cb9a64a62b0b3c841c63ac 100644 --- a/libcpp/charset.cc +++ b/libcpp/charset.cc @@ -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 uchar *from, const uchar *limit, 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, enum cpp_ttype type) 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 *pfile, const cpp_string *from, size_t count, 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 *pfile, const cpp_string *from, size_t count, 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 *pfile, const cpp_string *from, 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_reader *pfile, const cpp_string *from, 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; diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h index fe73a27097622d691cb5aaf3b770faee8f0d9462..d873897bd3c4ef365a54b637ef922272799ac70c 100644 --- a/libcpp/include/cpplib.h +++ b/libcpp/include/cpplib.h @@ -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. */ \