-
Notifications
You must be signed in to change notification settings - Fork 609
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
Implement _Alignas and _Alignof support with tests #435
Conversation
pycparser/_c_ast.cfg
Outdated
|
||
# A typedef declaration. | ||
# Very similar to Decl, but without some attributes | ||
# | ||
Typedef: [name, quals, storage, type*] | ||
Typedef: [name, quals, align, storage, type*] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can typedefs have _Alignas?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No.
pycparser/_ast_gen.py
Outdated
@@ -134,6 +134,22 @@ def _gen_children(self): | |||
|
|||
return src | |||
|
|||
def _gen_eq(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this related to the PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, required by tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please clarify which tests need this? pycparser has hundreds of AST tests which don't need this comparison, so I'm wondering what's new here. In any case I would prefer to decouple this large change from the _Align*
PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one. I am fine to create a separate PR for that.
======================================================================
FAIL: test_alignment (tests.test_c_generator.TestCtoC)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/user/AppleDeveloper/pycparser/tests/test_c_generator.py", line 100, in test_alignment
self._assert_ctoc_correct('_Alignas(32) int b;')
File "/Users/user/AppleDeveloper/pycparser/tests/test_c_generator.py", line 79, in _assert_ctoc_correct
"{!r} != {!r}".format(src, src2))
AssertionError: '_Alignas(32) int b;' != '_Alignas(32) int b;\n'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, let's move the equality stuff out to a separate PR that can be discussed after this one lands.
pycparser/_ast_gen.py
Outdated
@@ -134,6 +134,22 @@ def _gen_children(self): | |||
|
|||
return src | |||
|
|||
def _gen_eq(self): | |||
src = ' def __eq__(self, o):\n' | |||
src += ' if not o: return False\n' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this comparing children?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which particular case do you mean?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if self.{0} != o.{0}
will trigger recursive __ne__
→ __eq__
calls. If you mean inner members.
pycparser/_ast_gen.py
Outdated
@@ -134,6 +134,22 @@ def _gen_children(self): | |||
|
|||
return src | |||
|
|||
def _gen_eq(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please clarify which tests need this? pycparser has hundreds of AST tests which don't need this comparison, so I'm wondering what's new here. In any case I would prefer to decouple this large change from the _Align*
PR.
@@ -618,6 +623,12 @@ def test_sizeof(self): | |||
['TypeDecl', | |||
['IdentifierType', ['int']]]]]]) | |||
|
|||
def test_alignof(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to see more parser tests here.
At least one test separately for _Alignof
without _Alignas
(look at the existing sizeof
tests)
A test for _Alignas
with a true constant like 4
A test for _Alignas
with a type inside e.g. _Alignas(int)
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, thanks.
pycparser/c_parser.py
Outdated
@@ -310,6 +310,11 @@ def _fix_decl_name_type(self, decl, typename): | |||
decl.name = type.declname | |||
type.quals = decl.quals[:] | |||
|
|||
for tn in typename: | |||
if isinstance(tn, c_ast.Alignas): | |||
type.align = tn |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a bit confused here: isn't align an attribute, not a child node? Should it be a child node instead if you're assigning nodes to it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is an attribute indeed, not a child node. This code was merely a fixup for the parser limitation. Previously one of the tests triggered an issue without this code, however, currently none does. I am in a good faith to believe that the issue was resolved more properly in one of the future iterations of the code and I did not notice it. Will simply remove.
pycparser/c_parser.py
Outdated
for tn in typename: | ||
if isinstance(tn, c_ast.Alignas): | ||
type.align = tn | ||
typename.remove(tn) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't modify a list you're iterating.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, if we allow a list of alignment specifiers, does it show here or do we only overwrite them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
pycparser/c_parser.py
Outdated
@@ -920,9 +940,20 @@ def p_specifier_qualifier_list_3(self, p): | |||
def p_specifier_qualifier_list_4(self, p): | |||
""" specifier_qualifier_list : type_qualifier_list type_specifier | |||
""" | |||
spec = dict(qual=p[1], storage=[], type=[], function=[]) | |||
spec = dict(qual=p[1], alignment=[], storage=[], type=[], function=[]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So you really need _add_declaration_specifier here? Can't you just copy the type
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rebased on top of master fixing. Indeed no need.
pycparser/c_parser.py
Outdated
""" specifier_qualifier_list : alignment_specifier | ||
""" | ||
spec = dict(qual=[], alignment=[], storage=[], type=[], function=[]) | ||
p[0] = self._add_declaration_specifier(spec, p[1], 'alignment') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same question here, it's not clear why you need to create an empty spec
and pass it to _add_declaration_specifier
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds like literal copy-pasting from the existing code, nice catch. Also fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, this looks close just. Just remove the equality generation for now, and I'll take a final look
pycparser/_ast_gen.py
Outdated
@@ -134,6 +134,22 @@ def _gen_children(self): | |||
|
|||
return src | |||
|
|||
def _gen_eq(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, let's move the equality stuff out to a separate PR that can be discussed after this one lands.
Sure, shall I comment the test part for now? |
No, please remove everything related to generating equality and the test that requires it from the PR. I'm still not convinced this is needed at all, and wanted to separate it to its own PR so as not to block the align feature |
Hmm, this is the whole |
@@ -96,6 +96,27 @@ def test_complex_decls(self): | |||
self._assert_ctoc_correct('int test(const char* const* arg);') | |||
self._assert_ctoc_correct('int test(const char** const arg);') | |||
|
|||
# FIXME: These require custom equality comparison. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can remove that block if you think it is better.
…ests This lets us re-enable that were commented out in #435
I've re-enabled the commented-out tests in d4c2922 |
Thanks a lot! |
Thank you for pushing the align and other changes through and improving C11 support for pycparser :) |
Rebased the original PR on master.