Assert that `format_cc_ident` doesn't return reserved C++ keywords.
PiperOrigin-RevId: 479324790
diff --git a/common/code_gen_utils.rs b/common/code_gen_utils.rs
index c1161bf..8f05d74 100644
--- a/common/code_gen_utils.rs
+++ b/common/code_gen_utils.rs
@@ -2,7 +2,9 @@
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+use once_cell::sync::Lazy;
use proc_macro2::TokenStream;
+use std::collections::HashSet;
// TODO(lukasza): Consider adding more items into `code_gen_utils` (this crate).
// For example, the following items from `src_code_gen.rs` will be most likely
@@ -10,11 +12,125 @@
// - `make_rs_ident`
// - `NamespaceQualifier`
-/// Formats a C++ identifier. Does not escape C++ keywords.
+/// Formats a C++ identifier. Panics when `ident` is a C++ reserved keyword.
pub fn format_cc_ident(ident: &str) -> TokenStream {
+ // C++ doesn't have an equivalent of
+ // https://doc.rust-lang.org/rust-by-example/compatibility/raw_identifiers.html and therefore
+ // we panic when `ident` is a C++ reserved keyword.
+ assert!(
+ !RESERVED_CC_KEYWORDS.contains(ident),
+ "The following reserved keyword can't be used as a C++ identifier: {}",
+ ident
+ );
+
ident.parse().unwrap()
}
+static RESERVED_CC_KEYWORDS: Lazy<HashSet<&'static str>> = Lazy::new(|| {
+ // `RESERVED_CC_KEYWORDS` are based on https://en.cppreference.com/w/cpp/keyword
+ [
+ "alignas",
+ "alignof",
+ "and",
+ "and_eq",
+ "asm",
+ "atomic_cancel",
+ "atomic_commit",
+ "atomic_noexcept",
+ "auto",
+ "bitand",
+ "bitor",
+ "bool",
+ "break",
+ "case",
+ "catch",
+ "char",
+ "char8_t",
+ "char16_t",
+ "char32_t",
+ "class",
+ "compl",
+ "concept",
+ "const",
+ "consteval",
+ "constexpr",
+ "constinit",
+ "const_cast",
+ "continue",
+ "co_await",
+ "co_return",
+ "co_yield",
+ "decltype",
+ "default",
+ "delete",
+ "do",
+ "double",
+ "dynamic_cast",
+ "else",
+ "enum",
+ "explicit",
+ "export",
+ "extern",
+ "false",
+ "float",
+ "for",
+ "friend",
+ "goto",
+ "if",
+ "inline",
+ "int",
+ "long",
+ "mutable",
+ "namespace",
+ "new",
+ "noexcept",
+ "not",
+ "not_eq",
+ "nullptr",
+ "operator",
+ "or",
+ "or_eq",
+ "private",
+ "protected",
+ "public",
+ "reflexpr",
+ "register",
+ "reinterpret_cast",
+ "requires",
+ "return",
+ "short",
+ "signed",
+ "sizeof",
+ "static",
+ "static_assert",
+ "static_cast",
+ "struct",
+ "switch",
+ "synchronized",
+ "template",
+ "this",
+ "thread_local",
+ "throw",
+ "true",
+ "try",
+ "typedef",
+ "typeid",
+ "typename",
+ "union",
+ "unsigned",
+ "using",
+ "virtual",
+ "void",
+ "volatile",
+ "wchar_t",
+ "while",
+ "xor",
+ "xor_eq",
+ ]
+ .into_iter()
+ .collect()
+});
+
#[cfg(test)]
pub mod tests {
use super::*;
@@ -32,7 +148,8 @@
}
#[test]
+ #[should_panic(expected = "can't be used as a C++ identifier: reinterpret_cast")]
fn test_format_cc_ident_reserved_cc_keyword() {
- assert_cc_matches!(format_cc_ident("int"), quote! { int });
+ format_cc_ident("reinterpret_cast");
}
}