Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apply defines to struct literal #956

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

youknowone
Copy link

Fix #955

@youknowone youknowone force-pushed the cfg-literal branch 3 times, most recently from cc3bb3f to 0e7afe1 Compare May 17, 2024 10:25
Comment on lines 13 to 26
#[repr(C)]
pub struct Bar {
pub x: i32,
#[cfg(windows)]
pub y: u32,
}

impl Bar {
pub const BAR: Self = Self {
x: 0,
#[cfg(windows)]
y: 0,
};
}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How can I properly add a test? This change doesn't add diff

@youknowone
Copy link
Author

I didn't push newline/indent fix not to break test yet. Please let me know if the approach is okay. Then I will finish the whitespace work.

Copy link
Collaborator

@emilio emilio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, looks good with a question.

Regarding the test, let's put it in tests/rust/cfg.rs.

Feel free to remove tests/rust/cfg_field.rs, it was meant as a crashtest at some point, looking at the git history, but right now it's covered by tests/rust/cfg.

// In C++, same order as defined is required.
let ordered_fields = out.bindings().struct_field_names(path);
for ordered_key in ordered_fields.iter() {
let last_i = ordered_fields.len() - 1;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, the question didn't get saved. It's basically... can't this underflow? It'd be better to do if ordered_fields.is_empty() { 0 } else { ordered_fields.len() - 1 };

Copy link
Collaborator

@emilio emilio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, it might be harder than that... Recording with a bit whether we have conditional fields, and either skip generating the constant or generate it without the conditions for C seems feasible.

Alternatively doing some macro soup for C might work but it is annoying. Something like gathering the conditional fields first, and generating something like:

#ifdef X11
#define zero_(v) .zero = v,
#else
#define zero_(v)
#endif
#define ConditionalField_ZERO (ConditionalField){ \
  zero_(0) \
};

Or so, but that gets clunky.

tests/expectations/cfg.compat.c Show resolved Hide resolved
Copy link
Author

@youknowone youknowone left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the advice. It had progress, but not yet finished.

I left another comment for duplicated field generation.
Another problem is constexpr context. write_literal needs context about allow_constexpr to choose macro or inline field. Do you have a suggestion for that? This is solved

Comment on lines 959 to 992
if self.config.language == Language::C {
for ordered_key in ordered_fields.iter() {
if let Some(lit) = fields.get(ordered_key) {
if let Some(condition) = lit.cfg.to_condition(self.config) {
out.new_line();
condition.write_before(self.config, out);
let define = format!("#define __{export_name}_{ordered_key}(v)");
write!(out, "{define} (v)");
write!(out, "\n#else\n");
write!(out, "{define}");
condition.write_after(self.config, out);
}
}
}
}
Copy link
Author

@youknowone youknowone Aug 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is the good place to put this?
From this place, it will write duplicated definitions for each literal definition. That will trigger compiler warnings about redefinition.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@emilio This part is also not resolved yet

@@ -911,30 +911,42 @@ impl LanguageBackend for CLikeLanguageBackend<'_> {
fields,
path,
} => {
let is_constexpr = self.config.language == Language::Cxx
&& (self.config.constant.allow_constexpr || l.can_be_constexpr());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems wrong? Shouldn't it be allow_constexpr && can_be_constexpr?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh.. I was confused by allow_static_const. Thank you

if is_constexpr {
if i > 0 {
write!(out, ", ");
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Factor this out of the if/else?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you looked in first commit, this is changed in second commit

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you don't mind, I separated the former 2 commits to another PR in #988, which is not directly related to cfg handling.

} else {
write!(out, ".{} = ", ordered_key);
}
self.write_literal(out, lit);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

#else
#define __ConditionalField_field(v)
#endif
#define ConditionalField_ONE (ConditionalField){ .field = __ConditionalField_field(1) }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this even build when it's not defined? Doesn't it expand to .field =?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, fixed it

@youknowone
Copy link
Author

@emilio could you take another look?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

defines is not applied for impl const
2 participants