Skip to content

Commit 732622c

Browse files
emilioqsdrqs
authored andcommitted
context: Fix tokenization of C++20 inline namespace. (rust-lang#2294)
Fixes rust-lang#2293
1 parent 3187393 commit 732622c

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

Lines changed: 21 additions & 0 deletions
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

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 5 additions & 0 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 35 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2124,13 +2124,18 @@ If you encounter an error missing from this list, please file an issue or a PR!"
21242124
}
21252125

21262126
let mut kind = ModuleKind::Normal;
2127-
let mut found_namespace_keyword = false;
2127+
let mut looking_for_name = false;
21282128
for token in cursor.tokens().iter() {
21292129
match token.spelling() {
21302130
b"inline" => {
2131-
assert!(!found_namespace_keyword);
2132-
assert!(kind != ModuleKind::Inline);
2131+
debug_assert!(
2132+
kind != ModuleKind::Inline,
2133+
"Multiple inline keywords?"
2134+
);
21332135
kind = ModuleKind::Inline;
2136+
// When hitting a nested inline namespace we get a spelling
2137+
// that looks like ["inline", "foo"]. Deal with it properly.
2138+
looking_for_name = true;
21342139
}
21352140
// The double colon allows us to handle nested namespaces like
21362141
// namespace foo::bar { }
@@ -2139,45 +2144,39 @@ If you encounter an error missing from this list, please file an issue or a PR!"
21392144
// but the tokenization of the second begins with the double
21402145
// colon. That's ok, so we only need to handle the weird
21412146
// tokenization here.
2142-
//
2143-
// Fortunately enough, inline nested namespace specifiers aren't
2144-
// a thing, and are invalid C++ :)
21452147
b"namespace" | b"::" => {
2146-
found_namespace_keyword = true;
2148+
looking_for_name = true;
21472149
}
21482150
b"{" => {
2149-
assert!(found_namespace_keyword);
2151+
// This should be an anonymous namespace.
2152+
assert!(looking_for_name);
21502153
break;
21512154
}
2152-
name if found_namespace_keyword => {
2153-
if module_name.is_none() {
2154-
module_name =
2155-
Some(String::from_utf8_lossy(name).into_owned());
2155+
name => {
2156+
if looking_for_name {
2157+
if module_name.is_none() {
2158+
module_name = Some(
2159+
String::from_utf8_lossy(name).into_owned(),
2160+
);
2161+
}
2162+
break;
2163+
} else {
2164+
// This is _likely_, but not certainly, a macro that's
2165+
// been placed just before the namespace keyword.
2166+
// Unfortunately, clang tokens don't let us easily see
2167+
// through the ifdef tokens, so we don't know what this
2168+
// token should really be. Instead of panicking though,
2169+
// we warn the user that we assumed the token was blank,
2170+
// and then move on.
2171+
//
2172+
// See also https://github.com/rust-lang/rust-bindgen/issues/1676.
2173+
warn!(
2174+
"Ignored unknown namespace prefix '{}' at {:?} in {:?}",
2175+
String::from_utf8_lossy(name),
2176+
token,
2177+
cursor
2178+
);
21562179
}
2157-
break;
2158-
}
2159-
spelling if !found_namespace_keyword => {
2160-
// This is _likely_, but not certainly, a macro that's been placed just before
2161-
// the namespace keyword. Unfortunately, clang tokens don't let us easily see
2162-
// through the ifdef tokens, so we don't know what this token should really be.
2163-
// Instead of panicking though, we warn the user that we assumed the token was
2164-
// blank, and then move on.
2165-
//
2166-
// See also https://github.com/rust-lang/rust-bindgen/issues/1676.
2167-
warn!(
2168-
"Ignored unknown namespace prefix '{}' at {:?} in {:?}",
2169-
String::from_utf8_lossy(spelling),
2170-
token,
2171-
cursor
2172-
);
2173-
}
2174-
spelling => {
2175-
panic!(
2176-
"Unknown token '{}' while processing namespace at {:?} in {:?}",
2177-
String::from_utf8_lossy(spelling),
2178-
token,
2179-
cursor
2180-
);
21812180
}
21822181
}
21832182
}

0 commit comments

Comments
 (0)