diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 6e310f2c0fd..2891856098c 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -9868,6 +9868,17 @@ cp_parser_parenthesized_expression_list (cp_parser* parser, expression_list->quick_push (arg); goto get_comma; } + else if (is_attribute_list == normal_attr + && cp_lexer_next_token_is (parser->lexer, CPP_STRING) + && (cp_lexer_nth_token_is (parser->lexer, 2, CPP_COMMA) + || cp_lexer_nth_token_is (parser->lexer, 2, CPP_CLOSE_PAREN))) + { + auto t = make_temp_override (parser->translate_strings_p, false); + expr + = cp_parser_parenthesized_expression_list_elt (parser, cast_p, + allow_expansion_p, + non_constant_p); + } else expr = cp_parser_parenthesized_expression_list_elt (parser, cast_p, diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index 35bc48e49dc..3e1a86fae6c 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -47,6 +47,7 @@ along with GCC; see the file COPYING3. If not see #include "memmodel.h" #include "gimplify.h" #include "contracts.h" +#include "c-family/c-pragma.h" /* There routines provide a modular interface to perform many parsing operations. They may therefore be used during actual parsing, or @@ -12855,6 +12856,24 @@ cexpr_str::extract (location_t location, const char * & msg, int &len) return false; } } + /* Convert the string from execution charset to SOURCE_CHARSET. */ + cpp_string istr, ostr; + istr.len = len; + istr.text = (const unsigned char *) msg; + if (!cpp_translate_string (parse_in, &istr, &ostr, CPP_STRING, true)) + { + error_at (location, "could not convert constexpr string from " + "ordinary literal encoding to source character " + "set"); + return false; + } + else + { + if (buf) + XDELETEVEC (buf); + msg = buf = const_cast ((const char *) ostr.text); + len = ostr.len; + } } else { diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-asm-6.C b/gcc/testsuite/g++.dg/cpp1z/constexpr-asm-6.C new file mode 100644 index 00000000000..ca435f5ed45 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-asm-6.C @@ -0,0 +1,34 @@ +/* { dg-do compile { target c++17 } } */ +/* { dg-skip-if "requires hosted libstdc++ for string" { ! hostedlib } } */ +// { dg-require-iconv "IBM1047" } +// { dg-options "-fexec-charset=IBM1047" } + +#include + +constexpr std::string_view genfoo () +{ + return "foo %1,%0"; +} + +constexpr std::string_view genoutput () +{ + return "=r"; +} + +constexpr std::string_view geninput () +{ + return "r"; +} + +constexpr std::string_view genclobber () +{ + return "memory"; +} + +void f() +{ + int a; + asm((genfoo ()) : (genoutput ()) (a) : (geninput ()) (1) : (genclobber ())); +} + +/* { dg-final { scan-assembler "foo" } } */ diff --git a/gcc/testsuite/g++.dg/cpp23/charset2.C b/gcc/testsuite/g++.dg/cpp23/charset2.C new file mode 100644 index 00000000000..8230b442b17 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/charset2.C @@ -0,0 +1,36 @@ +// P2246R1 +// { dg-do compile { target c++23 } } +// { dg-require-iconv "IBM1047" } +// { dg-options "-pedantic-errors -fexec-charset=IBM1047" } + +[[deprecated ("foo")]] int d; // { dg-message "declared here" } +int e = d; // { dg-warning "'d' is deprecated: foo" } +static_assert (false, "bar"); // { dg-error "static assertion failed: bar" } +#error "baz" // { dg-error "#error \"baz\"" } +[[nodiscard ("qux")]] int foo (); // { dg-message "declared here" } +void +bar () +{ + foo (); // { dg-warning "ignoring return value of 'int foo\\\(\\\)', declared with attribute 'nodiscard': 'qux'" } +} +#if __cplusplus > 202302L +#warning "fred" // { dg-warning "#warning \"fred\"" "" { target c++26 } } +#endif +#if __cpp_static_assert >= 202306L +struct A { constexpr int size () const { return 5; } + constexpr const char *data () const { return "xyzzy"; } }; +static_assert (false, A {}); // { dg-error "static assertion failed: xyzzy" "" { target c++26 } } +#endif +#if __cpp_deleted_function >= 202403L +int baz () = delete ("garply"); // { dg-message "declared here" "" { target c++26 } } +void +plugh () +{ + baz (); // { dg-error "use of deleted function 'int baz\\\(\\\)': garply" "" { target c++26 } } +} +#endif +namespace [[deprecated ("corge")]] ND // { dg-message "declared here" } +{ + int i; +}; +int j = ND::i; // { dg-warning "'ND' is deprecated: corge" } diff --git a/gcc/testsuite/g++.dg/cpp23/charset3.C b/gcc/testsuite/g++.dg/cpp23/charset3.C new file mode 100644 index 00000000000..fd9e1585d90 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/charset3.C @@ -0,0 +1,24 @@ +// P2246R1 +// { dg-do compile { target c++11 } } +// { dg-require-iconv "IBM1047" } +// { dg-options "-fexec-charset=IBM1047" } + +[[gnu::deprecated ("foo")]] int d; // { dg-message "declared here" } +int e = d; // { dg-warning "'d' is deprecated: foo" } +[[gnu::unavailable ("bar")]] int f; // { dg-message "declared here" } +int g = f; // { dg-error "'f' is unavailable: bar" } +__attribute__((deprecated ("baz"))) int h; // { dg-message "declared here" } +int i = h; // { dg-warning "'h' is deprecated: baz" } +__attribute__((unavailable ("qux"))) int j; // { dg-message "declared here" } +int k = j; // { dg-error "'j' is unavailable: qux" } +#warning "fred" // { dg-warning "#warning \"fred\"" } +namespace [[gnu::deprecated ("corge")]] ND // { dg-message "declared here" } +{ + int l; +}; +int m = ND::l; // { dg-warning "'ND' is deprecated: corge" } +namespace __attribute__((deprecated ("xyzzy"))) NE // { dg-message "declared here" } +{ + int l; +}; +int n = NE::l; // { dg-warning "'NE' is deprecated: xyzzy" } diff --git a/gcc/testsuite/g++.dg/cpp23/charset4.C b/gcc/testsuite/g++.dg/cpp23/charset4.C new file mode 100644 index 00000000000..e79188225b4 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/charset4.C @@ -0,0 +1,36 @@ +// P2246R1 +// { dg-do compile { target c++23 } } +// { dg-require-iconv "UTF-8" } +// { dg-options "-pedantic-errors -fexec-charset=UTF-8" } + +[[deprecated ("áæ)")]] int d; // { dg-message "declared here" } +int e = d; // { dg-warning "'d' is deprecated: áæ" } +static_assert (false, "áæ"); // { dg-error "static assertion failed: áæ" } +#error "áæ" // { dg-error "#error \"áæ\"" } +[[nodiscard ("áæ")]] int foo (); // { dg-message "declared here" } +void +bar () +{ + foo (); // { dg-warning "ignoring return value of 'int foo\\\(\\\)', declared with attribute 'nodiscard': 'áæ'" } +} +#if __cplusplus > 202302L +#warning "áæ" // { dg-warning "#warning \"áæ\"" "" { target c++26 } } +#endif +#if __cpp_static_assert >= 202306L +struct A { constexpr int size () const { return sizeof ("áæ") - 1; } + constexpr const char *data () const { return "áæ"; } }; +static_assert (false, A {}); // { dg-error "static assertion failed: áæ" "" { target c++26 } } +#endif +#if __cpp_deleted_function >= 202403L +int baz () = delete ("áæ"); // { dg-message "declared here" "" { target c++26 } } +void +plugh () +{ + baz (); // { dg-error "use of deleted function 'int baz\\\(\\\)': áæ" "" { target c++26 } } +} +#endif +namespace [[deprecated ("áæ")]] ND // { dg-message "declared here" } +{ + int i; +}; +int j = ND::i; // { dg-warning "'ND' is deprecated: áæ" } diff --git a/gcc/testsuite/g++.dg/cpp23/charset5.C b/gcc/testsuite/g++.dg/cpp23/charset5.C new file mode 100644 index 00000000000..06766937142 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/charset5.C @@ -0,0 +1,24 @@ +// P2246R1 +// { dg-do compile { target c++11 } } +// { dg-require-iconv "UTF-8" } +// { dg-options "-fexec-charset=UTF-8" } + +[[gnu::deprecated ("áæ")]] int d; // { dg-message "declared here" } +int e = d; // { dg-warning "'d' is deprecated: áæ" } +[[gnu::unavailable ("áæ")]] int f; // { dg-message "declared here" } +int g = f; // { dg-error "'f' is unavailable: áæ" } +__attribute__((deprecated ("áæ"))) int h; // { dg-message "declared here" } +int i = h; // { dg-warning "'h' is deprecated: áæ" } +__attribute__((unavailable ("áæ"))) int j; // { dg-message "declared here" } +int k = j; // { dg-error "'j' is unavailable: áæ" } +#warning "áæ" // { dg-warning "#warning \"áæ\"" } +namespace [[gnu::deprecated ("áæ")]] ND // { dg-message "declared here" } +{ + int l; +}; +int m = ND::l; // { dg-warning "'ND' is deprecated: áæ" } +namespace __attribute__((deprecated ("áæ"))) NE // { dg-message "declared here" } +{ + int l; +}; +int n = NE::l; // { dg-warning "'NE' is deprecated: áæ" }