Skip to content

Commit e85dcbf

Browse files
committed
Add is_va_arg attribute in IR
1 parent b1052cf commit e85dcbf

2 files changed

Lines changed: 49 additions & 8 deletions

File tree

rule-preprocessor/src/ir.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,21 @@ pub struct TypeIr {
123123
#[derive(Debug, Clone, Serialize, Deserialize)]
124124
#[serde(untagged)]
125125
pub enum BodyFragment {
126-
Text { text: String },
127-
Placeholder { placeholder: PlaceholderInner },
128-
Generic { generic: i32 },
129-
MethodCall { method_call: MethodCallInner },
126+
Text {
127+
text: String,
128+
},
129+
Placeholder {
130+
placeholder: PlaceholderInner,
131+
},
132+
Generic {
133+
generic: i32,
134+
},
135+
MethodCall {
136+
method_call: MethodCallInner,
137+
},
138+
VaArgs {
139+
va_args: std::marker::PhantomData<()>,
140+
},
130141
}
131142

132143
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]

rule-preprocessor/src/syntactic.rs

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,20 @@ fn pointer_flags(ty: &ast::Type) -> (bool, bool) {
4040
flags
4141
}
4242

43+
fn is_va_args_type(ty: &ast::Type) -> bool {
44+
if let ast::Type::RefType(r) = ty
45+
&& let Some(ast::Type::SliceType(slice)) = r.ty()
46+
{
47+
return matches!(slice.ty(), Some(ast::Type::PathType(path))
48+
if path
49+
.path()
50+
.and_then(|p| p.segment())
51+
.and_then(|s| s.name_ref())
52+
.is_some_and(|name| name.text() == "VaArg"));
53+
}
54+
false
55+
}
56+
4357
fn cfg_matches_host(fn_item: &ast::Fn) -> bool {
4458
for attr in fn_item.attrs() {
4559
let Some(meta) = attr.meta() else { continue };
@@ -205,6 +219,13 @@ impl<'a> FragmentCtx<'a> {
205219
}
206220
if token.kind() == SyntaxKind::IDENT {
207221
if let Some(param) = self.params.iter().find(|p| p.name == token.text()) {
222+
if param.is_va_args {
223+
self.flush_text();
224+
self.fragments.push(BodyFragment::VaArgs {
225+
va_args: std::marker::PhantomData,
226+
});
227+
return;
228+
}
208229
let mut access = self.builder.classify_access(token);
209230
if param.is_mut_ref && self.text_buf.ends_with('*') {
210231
self.text_buf.pop();
@@ -272,6 +293,7 @@ struct ParamInfo {
272293
is_refcount_pointer: bool,
273294
is_unsafe_pointer: bool,
274295
is_mut_ref: bool,
296+
is_va_args: bool,
275297
}
276298

277299
struct FnIrBuilder<'a> {
@@ -297,15 +319,22 @@ impl<'a> FnIrBuilder<'a> {
297319
};
298320

299321
let (is_refcount_pointer, is_unsafe_pointer) = pointer_flags(&ty);
322+
let name = ident
323+
.name()
324+
.map(|n| n.text().to_string())
325+
.unwrap_or_default();
326+
let is_va_args = is_va_args_type(&ty);
327+
assert!(
328+
!is_va_args || name == "va",
329+
"variadic argument parameter must be named `va`, found `{name}`"
330+
);
300331
params.push(ParamInfo {
301-
name: ident
302-
.name()
303-
.map(|n| n.text().to_string())
304-
.unwrap_or_default(),
332+
name,
305333
ty: ty.syntax().text().to_string(),
306334
is_refcount_pointer,
307335
is_unsafe_pointer,
308336
is_mut_ref: matches!(&ty, ast::Type::RefType(r) if r.mut_token().is_some()),
337+
is_va_args,
309338
});
310339
}
311340
params
@@ -482,6 +511,7 @@ impl<'a> FnIrBuilder<'a> {
482511

483512
let params_map: BTreeMap<String, TypeInfo> = params
484513
.iter()
514+
.filter(|p| !p.is_va_args)
485515
.map(|p| {
486516
(
487517
p.name.clone(),

0 commit comments

Comments
 (0)