diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 6e664a162df92..ca83e2be5c147 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -45,6 +45,7 @@ mod diagnostic; #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] pub use diagnostic::{Diagnostic, Level, MultiSpan}; +use std::ffi::CStr; use std::ops::{Range, RangeBounds}; use std::path::PathBuf; use std::str::FromStr; @@ -1351,6 +1352,13 @@ impl Literal { Literal::new(bridge::LitKind::ByteStr, &string, None) } + /// C string literal. + #[unstable(feature = "proc_macro_c_str_literals", issue = "119750")] + pub fn c_string(string: &CStr) -> Literal { + let string = string.to_bytes().escape_ascii().to_string(); + Literal::new(bridge::LitKind::CStr, &string, None) + } + /// Returns the span encompassing this literal. #[stable(feature = "proc_macro_lib2", since = "1.29.0")] pub fn span(&self) -> Span { diff --git a/tests/ui/feature-gates/feature-gate-proc_macro_c_str_literals.rs b/tests/ui/feature-gates/feature-gate-proc_macro_c_str_literals.rs new file mode 100644 index 0000000000000..5554c81392553 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-proc_macro_c_str_literals.rs @@ -0,0 +1,11 @@ +// edition: 2021 +// force-host +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::Literal; + +fn test() { + Literal::c_string(c"a"); //~ ERROR use of unstable library feature 'proc_macro_c_str_literals' +} diff --git a/tests/ui/feature-gates/feature-gate-proc_macro_c_str_literals.stderr b/tests/ui/feature-gates/feature-gate-proc_macro_c_str_literals.stderr new file mode 100644 index 0000000000000..9bba1d50ce362 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-proc_macro_c_str_literals.stderr @@ -0,0 +1,13 @@ +error[E0658]: use of unstable library feature 'proc_macro_c_str_literals' + --> $DIR/feature-gate-proc_macro_c_str_literals.rs:10:5 + | +LL | Literal::c_string(c"a"); + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #119750 for more information + = help: add `#![feature(proc_macro_c_str_literals)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/proc-macro/auxiliary/api/mod.rs b/tests/ui/proc-macro/auxiliary/api/mod.rs index 3bea5d75779aa..5a533b9e17e16 100644 --- a/tests/ui/proc-macro/auxiliary/api/mod.rs +++ b/tests/ui/proc-macro/auxiliary/api/mod.rs @@ -1,10 +1,12 @@ // force-host // no-prefer-dynamic +// edition: 2021 #![crate_type = "proc-macro"] #![crate_name = "proc_macro_api_tests"] #![feature(proc_macro_span)] #![feature(proc_macro_byte_character)] +#![feature(proc_macro_c_str_literals)] #![deny(dead_code)] // catch if a test function is never called extern crate proc_macro; diff --git a/tests/ui/proc-macro/auxiliary/api/parse.rs b/tests/ui/proc-macro/auxiliary/api/parse.rs index 07c9f464961ae..801c616c80404 100644 --- a/tests/ui/proc-macro/auxiliary/api/parse.rs +++ b/tests/ui/proc-macro/auxiliary/api/parse.rs @@ -19,10 +19,8 @@ fn test_display_literal() { "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0", ); - assert_eq!( - Literal::string("a \t ❤ ' \" \u{1}").to_string(), - "\"a \\t ❤ ' \\\" \\u{1}\"", - ); + assert_eq!(Literal::string("a \t ❤ ' \" \u{1}").to_string(), "\"a \\t ❤ ' \\\" \\u{1}\"",); + assert_eq!(Literal::c_string(c"\'\"\x7f\u{7fff}").to_string(), r#"c"\'\"\x7f\xe7\xbf\xbf""#); assert_eq!(Literal::character('a').to_string(), "'a'"); assert_eq!(Literal::character('\t').to_string(), "'\\t'"); assert_eq!(Literal::character('❤').to_string(), "'❤'"); @@ -41,6 +39,7 @@ fn test_parse_literal() { assert_eq!("b'a'".parse::().unwrap().to_string(), "b'a'"); assert_eq!("\"\n\"".parse::().unwrap().to_string(), "\"\n\""); assert_eq!("b\"\"".parse::().unwrap().to_string(), "b\"\""); + assert_eq!("c\"\"".parse::().unwrap().to_string(), "c\"\""); assert_eq!("r##\"\"##".parse::().unwrap().to_string(), "r##\"\"##"); assert_eq!("10ulong".parse::().unwrap().to_string(), "10ulong"); assert_eq!("-10ulong".parse::().unwrap().to_string(), "-10ulong"); diff --git a/tests/ui/proc-macro/test.rs b/tests/ui/proc-macro/test.rs index c96aa73175f2c..2ec620720202b 100644 --- a/tests/ui/proc-macro/test.rs +++ b/tests/ui/proc-macro/test.rs @@ -1,5 +1,6 @@ // check-pass // aux-build:api/mod.rs +// edition: 2021 //! This is for everything that *would* be a #[test] inside of libproc_macro, //! except for the fact that proc_macro objects are not capable of existing