Skip to content

Commit 576fd8d

Browse files
authored
context: Fix tokenization of C++20 inline namespace. (#2294)
Fixes #2293
1 parent 73ce4bc commit 576fd8d

File tree

5 files changed

+63
-37
lines changed

5 files changed

+63
-37
lines changed

bindgen-tests/tests/expectations/tests/inline_namespace_nested.rs

+21
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bindgen-tests/tests/expectations/tests/libclang-5/inline_namespace_nested.rs

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// bindgen-flags: --enable-cxx-namespaces -- -std=c++2a
2+
3+
namespace ranges::inline foo::bar {
4+
static int bar = 0;
5+
}

bindgen-tests/tests/tests.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ fn compare_generated_header(
252252
let actual = bindings.to_string();
253253
rustfmt(actual)
254254
}
255-
Err(_) => ("<error generating bindings>".to_string(), "".to_string()),
255+
Err(_) => ("/* error generating bindings */\n".into(), "".to_string()),
256256
};
257257
println!("{}", rustfmt_stderr);
258258

bindgen/ir/context.rs

+35-36
Original file line numberDiff line numberDiff line change
@@ -2107,13 +2107,18 @@ If you encounter an error missing from this list, please file an issue or a PR!"
21072107
}
21082108

21092109
let mut kind = ModuleKind::Normal;
2110-
let mut found_namespace_keyword = false;
2110+
let mut looking_for_name = false;
21112111
for token in cursor.tokens().iter() {
21122112
match token.spelling() {
21132113
b"inline" => {
2114-
assert!(!found_namespace_keyword);
2115-
assert!(kind != ModuleKind::Inline);
2114+
debug_assert!(
2115+
kind != ModuleKind::Inline,
2116+
"Multiple inline keywords?"
2117+
);
21162118
kind = ModuleKind::Inline;
2119+
// When hitting a nested inline namespace we get a spelling
2120+
// that looks like ["inline", "foo"]. Deal with it properly.
2121+
looking_for_name = true;
21172122
}
21182123
// The double colon allows us to handle nested namespaces like
21192124
// namespace foo::bar { }
@@ -2122,45 +2127,39 @@ If you encounter an error missing from this list, please file an issue or a PR!"
21222127
// but the tokenization of the second begins with the double
21232128
// colon. That's ok, so we only need to handle the weird
21242129
// tokenization here.
2125-
//
2126-
// Fortunately enough, inline nested namespace specifiers aren't
2127-
// a thing, and are invalid C++ :)
21282130
b"namespace" | b"::" => {
2129-
found_namespace_keyword = true;
2131+
looking_for_name = true;
21302132
}
21312133
b"{" => {
2132-
assert!(found_namespace_keyword);
2134+
// This should be an anonymous namespace.
2135+
assert!(looking_for_name);
21332136
break;
21342137
}
2135-
name if found_namespace_keyword => {
2136-
if module_name.is_none() {
2137-
module_name =
2138-
Some(String::from_utf8_lossy(name).into_owned());
2138+
name => {
2139+
if looking_for_name {
2140+
if module_name.is_none() {
2141+
module_name = Some(
2142+
String::from_utf8_lossy(name).into_owned(),
2143+
);
2144+
}
2145+
break;
2146+
} else {
2147+
// This is _likely_, but not certainly, a macro that's
2148+
// been placed just before the namespace keyword.
2149+
// Unfortunately, clang tokens don't let us easily see
2150+
// through the ifdef tokens, so we don't know what this
2151+
// token should really be. Instead of panicking though,
2152+
// we warn the user that we assumed the token was blank,
2153+
// and then move on.
2154+
//
2155+
// See also https://github.com/rust-lang/rust-bindgen/issues/1676.
2156+
warn!(
2157+
"Ignored unknown namespace prefix '{}' at {:?} in {:?}",
2158+
String::from_utf8_lossy(name),
2159+
token,
2160+
cursor
2161+
);
21392162
}
2140-
break;
2141-
}
2142-
spelling if !found_namespace_keyword => {
2143-
// This is _likely_, but not certainly, a macro that's been placed just before
2144-
// the namespace keyword. Unfortunately, clang tokens don't let us easily see
2145-
// through the ifdef tokens, so we don't know what this token should really be.
2146-
// Instead of panicking though, we warn the user that we assumed the token was
2147-
// blank, and then move on.
2148-
//
2149-
// See also https://github.com/rust-lang/rust-bindgen/issues/1676.
2150-
warn!(
2151-
"Ignored unknown namespace prefix '{}' at {:?} in {:?}",
2152-
String::from_utf8_lossy(spelling),
2153-
token,
2154-
cursor
2155-
);
2156-
}
2157-
spelling => {
2158-
panic!(
2159-
"Unknown token '{}' while processing namespace at {:?} in {:?}",
2160-
String::from_utf8_lossy(spelling),
2161-
token,
2162-
cursor
2163-
);
21642163
}
21652164
}
21662165
}

0 commit comments

Comments
 (0)