Skip to content

Commit 756b1f9

Browse files
Fix compat with Clang 22 (#1671)
2 parents f409961 + 2bb54a4 commit 756b1f9

137 files changed

Lines changed: 805 additions & 114 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ jobs:
1818
os: Linux
1919
arch: x86_64
2020
clang-version: 15
21+
- runner: macos-15
22+
os: macOS
23+
arch: aarch64
24+
clang-version: 22
2125
- runner: macos-15
2226
os: macOS
2327
arch: aarch64

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ LLVM_CONFIG_PATH="$(brew --prefix)/opt/llvm/bin/llvm-config" cargo install --loc
118118
or for a specific LLVM version,
119119
120120
```sh
121-
LLVM_CONFIG_PATH="$(brew --prefix)/opt/llvm@21/bin/llvm-config" cargo install --locked c2rust
121+
LLVM_CONFIG_PATH="$(brew --prefix)/opt/llvm@22/bin/llvm-config" cargo install --locked c2rust
122122
```
123123
124124
On Gentoo, you need to point the build system to

c2rust-ast-exporter/build.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,20 @@ fn build_native(llvm_info: &LLVMInfo) {
217217
.unwrap();
218218
clang_libs.insert(sema_pos + 1, "clangAPINotes");
219219
}
220+
if llvm_info.llvm_major_version >= 22 {
221+
// clang 22+ moved option parsing helpers into a separate library.
222+
// Keep this after users like clangFrontend/clangDriver.
223+
let driver_pos = clang_libs.iter().position(|&r| r == "clangDriver").unwrap();
224+
clang_libs.insert(driver_pos + 1, "clangOptions");
225+
226+
// clang 22+ split lifetime safety analysis from clangAnalysis.
227+
// Keep this after users like clangSema.
228+
let analysis_pos = clang_libs
229+
.iter()
230+
.position(|&r| r == "clangAnalysis")
231+
.unwrap();
232+
clang_libs.insert(analysis_pos + 1, "clangAnalysisLifetimeSafety");
233+
}
220234

221235
for lib in &clang_libs {
222236
println!("cargo:rustc-link-lib={}", lib);

c2rust-ast-exporter/src/AstExporter.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,7 @@ class TypeEncoder final : public TypeVisitor<TypeEncoder> {
657657
VisitQualType(t);
658658
}
659659

660+
#if CLANG_VERSION_MAJOR < 22
660661
void VisitElaboratedType(const ElaboratedType *T) {
661662
auto t = T->desugar();
662663
auto qt = encodeQualType(t);
@@ -665,6 +666,7 @@ class TypeEncoder final : public TypeVisitor<TypeEncoder> {
665666

666667
VisitQualType(t);
667668
}
669+
#endif
668670

669671
void VisitDecayedType(const DecayedType *T) {
670672
auto t = T->desugar();
@@ -690,6 +692,16 @@ class TypeEncoder final : public TypeVisitor<TypeEncoder> {
690692

691693
VisitQualType(t);
692694
}
695+
696+
#if CLANG_VERSION_MAJOR >= 22
697+
void VisitPredefinedSugarType(const clang::PredefinedSugarType *T) {
698+
auto t = T->desugar();
699+
auto k = T->getKind();
700+
encodeType(T, TagPredefinedSugarType,
701+
[k](CborEncoder *local) { cbor_encode_uint(local, uint64_t(k)); });
702+
VisitQualType(t);
703+
}
704+
#endif
693705
};
694706

695707
class TranslateASTVisitor final
@@ -2276,8 +2288,6 @@ class TranslateASTVisitor final
22762288
auto recordAlignment = 0;
22772289
auto byteSize = 0;
22782290

2279-
auto t = D->getTypeForDecl();
2280-
22812291
auto loc = D->getSourceRange();
22822292
std::vector<void *> childIds;
22832293
if (def) {
@@ -2357,8 +2367,6 @@ class TranslateASTVisitor final
23572367
// They are used in actual code and accepted by compilers, so we cannot
23582368
// exit early via code like `if (!D->isCompleteDefinition()) return true;`.
23592369

2360-
auto t = D->getTypeForDecl();
2361-
23622370
std::vector<void *> childIds;
23632371
for (auto x : D->enumerators()) {
23642372
childIds.push_back(x->getCanonicalDecl());

c2rust-ast-exporter/src/ast_tags.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ enum TypeTag {
154154
TagAtomicType,
155155

156156
TagAutoType,
157+
TagPredefinedSugarType,
157158
};
158159

159160
enum StringTypeTag {

c2rust-build-paths/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ pub fn find_llvm_config() -> Option<PathBuf> {
9191
.or_else(|| {
9292
// In PATH
9393
[
94+
"llvm-config-22",
9495
"llvm-config-21",
9596
"llvm-config-20",
9697
"llvm-config-19",
@@ -109,6 +110,7 @@ pub fn find_llvm_config() -> Option<PathBuf> {
109110
"llvm-config-7.0",
110111
"llvm-config",
111112
// Homebrew install locations on Intel macOS
113+
"/usr/local/opt/llvm@22/bin/llvm-config",
112114
"/usr/local/opt/llvm@21/bin/llvm-config",
113115
"/usr/local/opt/llvm@20/bin/llvm-config",
114116
"/usr/local/opt/llvm@19/bin/llvm-config",
@@ -125,6 +127,7 @@ pub fn find_llvm_config() -> Option<PathBuf> {
125127
"/usr/local/opt/llvm@8/bin/llvm-config",
126128
"/usr/local/opt/llvm/bin/llvm-config",
127129
// Homebrew install locations on Apple Silicon macOS
130+
"/opt/homebrew/opt/llvm@22/bin/llvm-config",
128131
"/opt/homebrew/opt/llvm@21/bin/llvm-config",
129132
"/opt/homebrew/opt/llvm@20/bin/llvm-config",
130133
"/opt/homebrew/opt/llvm@19/bin/llvm-config",

c2rust-transpile/src/c_ast/conversion.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,21 @@ impl ConversionContext {
813813
self.processed_nodes.insert(new_id, expected_ty);
814814
}
815815

816+
TypeTag::TagPredefinedSugarType => {
817+
let kind = from_value(ty_node.extras[0].clone())
818+
.expect("Predefined sugar type kind not found");
819+
820+
// See `clang::PredefinedSugarKind`.
821+
let predef_sugar_ty = match kind {
822+
0 => CTypeKind::Size,
823+
1 => CTypeKind::SSize,
824+
2 => CTypeKind::PtrDiff,
825+
_ => panic!("Predefined sugar type kind {kind} not known"),
826+
};
827+
self.add_type(new_id, not_located(predef_sugar_ty));
828+
self.processed_nodes.insert(new_id, expected_ty);
829+
}
830+
816831
TypeTag::TagEnumType if expected_ty & OTHER_TYPE != 0 => {
817832
let decl = from_value(ty_node.extras[0].clone()).expect("Enum decl not found");
818833
let decl_new = CDeclId(self.visit_node_type(decl, ENUM_DECL));

c2rust-transpile/src/c_ast/iterators.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -377,13 +377,15 @@ impl<'context> Iterator for DFExpr<'context> {
377377
pub struct DFNodes<'context> {
378378
context: &'context TypedAstContext,
379379
stack: Vec<SomeId>,
380+
visited: HashSet<SomeId>,
380381
}
381382

382383
impl<'context> DFNodes<'context> {
383384
pub fn new(context: &'context TypedAstContext, start: SomeId) -> Self {
384385
DFNodes {
385386
context,
386387
stack: vec![start],
388+
visited: <_>::from([start]),
387389
}
388390
}
389391
pub fn prune(&mut self, n: usize) {
@@ -401,7 +403,12 @@ impl<'context> Iterator for DFNodes<'context> {
401403
// Compute list of immediate children
402404
let children = immediate_children_all_types(self.context, i);
403405
// Add children in reverse order since we visit the end of the stack first
404-
self.stack.extend(children.into_iter().rev())
406+
self.stack.extend(
407+
children
408+
.into_iter()
409+
.rev()
410+
.filter(|child| self.visited.insert(*child)),
411+
)
405412
}
406413

407414
result
@@ -437,8 +444,9 @@ pub trait NodeVisitor {
437444
/// method afterward.
438445
fn visit_tree(&mut self, root: SomeId) {
439446
let mut stack = vec![VisitNode::new(root)];
447+
let mut visited = HashSet::new();
440448
while let Some(mut node) = stack.pop() {
441-
if !node.seen {
449+
if !node.seen && visited.insert(node.id) {
442450
let id = node.id;
443451
node.seen = true;
444452
stack.push(node);

c2rust-transpile/tests/snapshots.rs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::path::Path;
44
use std::path::PathBuf;
55
use std::process::Command;
66

7+
use c2rust_ast_exporter::get_clang_major_version;
78
use c2rust_rust_tools::rustc;
89
use c2rust_rust_tools::sanitize_file_name;
910
use c2rust_rust_tools::RustEdition;
@@ -105,6 +106,26 @@ fn transpile_snapshot(
105106
expect_compile_error: bool,
106107
imported_crates: &[&str],
107108
) {
109+
let c_file_name = c_path.file_name().unwrap().to_str().unwrap();
110+
let c_file_name = sanitize_file_name(&c_file_name);
111+
112+
// Some versions of clang can produce results different from their snapshots,
113+
// those tests append the clang version to the snapshot of the failing test.
114+
let clang_ver = match (get_clang_major_version().unwrap(), c_file_name.as_str()) {
115+
// Tests that change @ clang-22
116+
(22.., "varargs.c") => "clang22",
117+
(22.., "wide_strings.c") => "clang22",
118+
(22.., "auto_type.c") => "clang22",
119+
120+
// Tests that changed @ clang-17
121+
122+
// The minimum tested clang
123+
(15.., _) => "clang15",
124+
125+
// Clang versions bellow 15 test against 15 and hope for the best
126+
(0.., _) => "clang15",
127+
};
128+
108129
let cfg = config(edition);
109130
compile_and_transpile_file(c_path, cfg);
110131
let cwd = current_dir().unwrap();
@@ -116,9 +137,10 @@ fn transpile_snapshot(
116137
let rs_path = c_path.with_extension("rs");
117138
// We need to move the `.rs` file to a platform/edition-specific name
118139
// so that they don't overwrite each other.
119-
let ext = [&[edition.as_str()][..], platform]
140+
let ext = [&[edition.as_str()][..], platform, &[clang_ver][..]]
120141
.into_iter()
121142
.flatten()
143+
.filter(|s| !s.is_empty())
122144
.join(".");
123145
let old_rs_path = rs_path;
124146
let rs_path = old_rs_path.with_extension(format!("{ext}.rs"));
@@ -130,8 +152,6 @@ fn transpile_snapshot(
130152
// Replace real paths with placeholders
131153
let rs = rs.replace(cwd.to_str().unwrap(), ".");
132154

133-
let c_file_name = c_path.file_name().unwrap().to_str().unwrap();
134-
let c_file_name = sanitize_file_name(&c_file_name);
135155
let snapshot_name = format!("transpile@{c_file_name}.{ext}");
136156

137157
insta::assert_snapshot!(snapshot_name, &rs, &debug_expr);

c2rust-transpile/tests/snapshots/snapshots__transpile@alloca.c.2021.snap renamed to c2rust-transpile/tests/snapshots/snapshots__transpile@alloca.c.2021.clang15.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
source: c2rust-transpile/tests/snapshots.rs
3-
expression: cat tests/snapshots/alloca.2021.rs
3+
expression: cat tests/snapshots/alloca.2021.clang15.rs
44
---
55
#![allow(
66
clippy::missing_safety_doc,

0 commit comments

Comments
 (0)