blob: 8f05d74ddc4ef854d8c01feb21f905867695e037 [file] [log] [blame]
// Part of the Crubit project, under the Apache License v2.0 with LLVM
// 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
// reused from `cc_bindings_from_rs`:
// - `make_rs_ident`
// - `NamespaceQualifier`
/// 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::*;
use quote::quote;
use token_stream_matchers::assert_cc_matches;
#[test]
fn test_format_cc_ident_basic() {
assert_cc_matches!(format_cc_ident("foo"), quote! { foo });
}
#[test]
fn test_format_cc_ident_reserved_rust_keyword() {
assert_cc_matches!(format_cc_ident("impl"), quote! { impl });
}
#[test]
#[should_panic(expected = "can't be used as a C++ identifier: reinterpret_cast")]
fn test_format_cc_ident_reserved_cc_keyword() {
format_cc_ident("reinterpret_cast");
}
}