aboutsummaryrefslogtreecommitdiff
path: root/libcpp
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2023-11-02 07:44:24 +0100
committerJakub Jelinek <jakub@redhat.com>2023-11-02 07:44:24 +0100
commit1c58566450f21cf1d9951284176ea6da0cc11fc9 (patch)
treea246d75e345bc4f459fbe61de78602c04f5d1fd6 /libcpp
parent4ea36076d66eea0f5ccb9cbb9774028a667e122c (diff)
downloadgcc-1c58566450f21cf1d9951284176ea6da0cc11fc9.zip
gcc-1c58566450f21cf1d9951284176ea6da0cc11fc9.tar.gz
gcc-1c58566450f21cf1d9951284176ea6da0cc11fc9.tar.bz2
c++: Implement C++26 P2361R6 - Unevaluated strings [PR110342]
The following patch implements C++26 unevaluated-string. As it seems to me just extra pedanticity, it is implemented only for -std=c++26 or -std=gnu++26 and later and only if -pedantic/-pedantic-errors. Nothing is done for inline asm, while the spec changes those, it changes it to a balanced token sequence with implementation defined rules on what is and isn't allowed (so pedantically accepting asm ("" : "+m" (x)); was accepts-invalid before C++26, but we didn't diagnose anything). For the other spots mentioned in the paper, static_assert message, linkage specification, deprecated/nodiscard attributes it enforces the requirements (no prefixes, udlit suffixes, no octal/hexadecimal escapes (conditional escape sequences were rejected with pedantic already before). For the deprecated operator "" identifier case I've kept things as is, because everything seems to have been diagnosed already (a lot being implied from the string having to be empty). 2023-11-02 Jakub Jelinek <jakub@redhat.com> PR c++/110342 gcc/cp/ * parser.cc: Implement C++26 P2361R6 - Unevaluated strings. (uneval_string_attr): New enumerator. (cp_parser_string_literal_common): Add UNEVAL argument. If true, pass CPP_UNEVAL_STRING rather than CPP_STRING to cpp_interpret_string_notranslate. (cp_parser_string_literal, cp_parser_userdef_string_literal): Adjust callers of cp_parser_string_literal_common. (cp_parser_unevaluated_string_literal): New function. (cp_parser_parenthesized_expression_list): Handle uneval_string_attr. (cp_parser_linkage_specification): Use cp_parser_unevaluated_string_literal for C++26. (cp_parser_static_assert): Likewise. (cp_parser_std_attribute): Use uneval_string_attr for standard deprecated and nodiscard attributes. gcc/testsuite/ * g++.dg/cpp26/unevalstr1.C: New test. * g++.dg/cpp26/unevalstr2.C: New test. * g++.dg/cpp0x/udlit-error1.C (lol): Expect an error for C++26 about user-defined literal in deprecated attribute. libcpp/ * include/cpplib.h (TTYPE_TABLE): Add CPP_UNEVAL_STRING literal entry. Use C++11 instead of C++-0x in comments. * charset.cc (convert_escape): Add UNEVAL argument, if true, pedantically diagnose numeric escape sequences. (cpp_interpret_string_1): Formatting fix. Adjust convert_escape caller. (cpp_interpret_string): Formatting string. (cpp_interpret_string_notranslate): Pass type through to cpp_interpret_string if it is CPP_UNEVAL_STRING.
Diffstat (limited to 'libcpp')
-rw-r--r--libcpp/charset.cc22
-rw-r--r--libcpp/include/cpplib.h21
2 files changed, 27 insertions, 16 deletions
diff --git a/libcpp/charset.cc b/libcpp/charset.cc
index 7b625c9..d5a0275 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 fe73a27..d873897 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. */ \