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

GDScript: Improve validation and documentation of @export_flags #72493

Merged
merged 1 commit into from
Feb 7, 2023

Conversation

dalexeev
Copy link
Member

@dalexeev dalexeev commented Feb 1, 2023

@export_flags supports specifying other values with a colon, just like @export_enum. See the comment.

return false;
}
int64_t value = t[1].to_int();
if (value < 1 || value >= (1LL << max_flags)) {
Copy link
Member Author

Choose a reason for hiding this comment

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

const int64_t max_flags = 32;
int64_t value = t[1].to_int();

value >= (1LL << max_flags)

I'm not sure if this is correct.

Copy link
Member

@raulsntos raulsntos Feb 7, 2023

Choose a reason for hiding this comment

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

1LL << max_flags should be 4294967296 (2^32) which is correct, since the underlying type is a 32-bit integer. The >= comparison is also correct, since the value needs to be less than the maximum; otherwise, it would overflow and become 0.

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm not sure if int_64t is needed for the constant 32, but I haven't found another way to satisfy CI (tests on multiple platforms have failed).

Copy link
Member

@raulsntos raulsntos Feb 7, 2023

Choose a reason for hiding this comment

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

The value 1 << 32 doesn't fit in an 32-bit integer. So I'd say it needs to be stored in a int64_t. As for the max_flags constant, I don't think it needs to be int64_t, unless the compiler is complaining about mixing types in bitwise operations.

Copy link
Member

Choose a reason for hiding this comment

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

It's all unsigned no? Usually for bitwise operations we use 1U << flags where flags is uint64_t.

Copy link
Member

Choose a reason for hiding this comment

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

The 2^32 value would still not fit in a 32-bit unsigned integer. It will fit in both a signed and unsigned 64-bit integer. I don't know if it matters in C++ if the 64-bit integer is signed, but yes flags usually are unsigned.

@dalexeev dalexeev force-pushed the gds-export-flags branch 2 times, most recently from ebae500 to 483d5ae Compare February 1, 2023 10:12
Copy link
Member

@vnen vnen left a comment

Choose a reason for hiding this comment

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

LGTM

modules/gdscript/doc_classes/@GDScript.xml Outdated Show resolved Hide resolved
modules/gdscript/doc_classes/@GDScript.xml Outdated Show resolved Hide resolved
Comment on lines 3640 to 3643
if (p_annotation->name == SNAME("@export_flags") && p_annotation->resolved_arguments.size() > max_flags) {
push_error(vformat(R"(The argument count limit for "@export_flags" is exceeded (%d/%d).)", p_annotation->resolved_arguments.size(), max_flags), p_annotation);
return false;
}
Copy link
Member Author

Choose a reason for hiding this comment

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

I think this code is no longer needed? Since the flag values are already checked below, and (in theory) there can be more than 32 arguments (different combinations of flags)?

Copy link
Member

@raulsntos raulsntos Feb 6, 2023

Choose a reason for hiding this comment

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

The value of each argument can't exceed 32^2 2^32 because the underlying type is a 32-bit integer. So this error is still useful because it helps avoid exceeding this limit when the arguments don't specify their value, although it could be improved.

Copy link
Member Author

Choose a reason for hiding this comment

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

No, I mean something like:

A:1,B:2,C:4,D:8,E:16,F:32,G:64,<X>

Where <X> is all combinations of 3 flags. C(7,3) = 7! / (3! * 4!) = 35. So there are 7 + 35 = 42 arguments in total. This is greater than 32, but each of the arguments does not exceed the allowed value.

The only thing missing from the check below is the calculation of an auto value if :number is not specified.

Note: I haven't checked how the inspector handles this.

Copy link
Member

Choose a reason for hiding this comment

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

My response was addressing your question I think this code is no longer needed?. I was thinking it was still needed for the case when values are not specified because it will increase the values automatically so the 33rd argument will exceed 2^32 (4294967296). But I totally missed that you also said Since the flag values are already checked below.

I think, when the value is not specified, this check would give a better error. Otherwise, it may be a bit confusing for users to get Invalid argument %d of annotation "@export_flags": The flag value must be at least 1 and at most 2 ** %d - 1. when they didn't specify any value.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think we can finalize this PR, and discuss further improvements separately.

Copy link
Member Author

Choose a reason for hiding this comment

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

@export_flags(\
"F00:1", "F01:1", "F02:1", "F03:1",
"F04:1", "F05:1", "F06:1", "F07:1",
"F08:1", "F09:1", "F10:1", "F11:1",
"F12:1", "F13:1", "F14:1", "F15:1",
"F16:1", "F17:1", "F18:1", "F19:1",
"F20:1", "F21:1", "F22:1", "F23:1",
"F24:1", "F25:1", "F26:1", "F27:1",
"F28:1", "F29:1", "F30:1", "F31:1",
"F32:2", "F33:4", "F34:8", "F35:16"
) var test

@dalexeev dalexeev force-pushed the gds-export-flags branch 2 times, most recently from 934a47b to 911a9b3 Compare February 7, 2023 16:08
@YuriSizov YuriSizov dismissed their stale review February 7, 2023 17:29

Changes made

@akien-mga akien-mga merged commit bd267c9 into godotengine:master Feb 7, 2023
@akien-mga
Copy link
Member

Thanks!

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

Successfully merging this pull request may close these issues.

5 participants