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

device.h: C++20 compatibility #70403

Merged
merged 4 commits into from
Jul 8, 2024
Merged

Conversation

marc-hb
Copy link
Collaborator

@marc-hb marc-hb commented Mar 19, 2024

2 fixes + 2 corresponding tests/ commits, please check commit messages.

Apply to device.h and pm/device.h the C/C++ compatibility lessons learned for init.h in #69411

* support for anonymous unions but they require these braces when
* combined with C99 designated initializers. These braces are
* compatible with any C version but not with C++20. For more obscure
* C/C++ compatibility details see commit c15f029a7108 and PR #69411.
Copy link
Member

Choose a reason for hiding this comment

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

please avoid referring to PRs in documentation

Copy link
Collaborator Author

@marc-hb marc-hb Mar 19, 2024

Choose a reason for hiding this comment

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

I usually do avoid this but this issue is really complex (even when the corresponding code is not) and that PR discussion is quite important.

Copy link
Member

Choose a reason for hiding this comment

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

PRs content is not part of Zephyr git history. Who knows if Github will stay Zephyr's VCS provider forever.

Copy link
Member

Choose a reason for hiding this comment

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

I'm with Gerard on this, just refer to the commit, one can find back the PR out of band but really the commit should have enough context regardless

If you really want to link a PR maybe you can do it on this comment using the Link: tag and the full URL?

Copy link
Collaborator Author

@marc-hb marc-hb Mar 20, 2024

Choose a reason for hiding this comment

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

Who knows if Github will stay Zephyr's VCS provider forever.

I'm aware and I always try to avoid references to PRs when the git history is enough. But I think there can be some exceptions. It's not because something may disappear one day that it should not be referenced. If Zephyr migrates away from Github one day, then it should definitely export all past review discussions and migrate or archive them somewhere and then PR numbers would still be useful. I've been performing such archeology in the past and any reference helps.

Of course documentation is even better but (1) it's not mutually exclusive (2) not obvious where in the docs this obscure issue belongs (3) more "overhead" :-)

PRs content is not part of Zephyr git history.

True but the git history does not exist in a complete vacuum either.

If you really want to link a PR maybe you can do it on this comment using the Link: tag and the full URL?

That would work for me.

Or I can just delete the PR number entirely if it's really important for you. I think that would be a loss but it's not that big of a deal for me.

Copy link
Member

Choose a reason for hiding this comment

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

Full link of external references in the commit I think are fine, Linux does it as well, it's more my opinion than a general rule but I think it's a good idea and I occasionally do it myself too.

}

/*
* Anonymous unions require C11. Some pre-C11 gcc versions have early
Copy link
Member

Choose a reason for hiding this comment

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

this is repeating information, can’t it be put somewhere and reference it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I tried to summarize it but I agree it's still a bit long and duplicated... any suggestion of a good place? I couldn't think of a really better way to document this sorry.

Copy link
Member

Choose a reason for hiding this comment

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

Maybe Zephyr coding guidelines? It looks like we'll need to apply this in other places if we want C++20 compatibility. An explanation there, plus a code snippet would be a solution, you could then just say "Refer to doc/xxx.rst"

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks, I'll take a look in the next couple weeks.

Copy link
Collaborator Author

@marc-hb marc-hb Jun 14, 2024

Choose a reason for hiding this comment

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

Copy link
Collaborator Author

@marc-hb marc-hb left a comment

Choose a reason for hiding this comment

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

Thx for the review! Answers below.

}

/*
* Anonymous unions require C11. Some pre-C11 gcc versions have early
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I tried to summarize it but I agree it's still a bit long and duplicated... any suggestion of a good place? I couldn't think of a really better way to document this sorry.

* support for anonymous unions but they require these braces when
* combined with C99 designated initializers. These braces are
* compatible with any C version but not with C++20. For more obscure
* C/C++ compatibility details see commit c15f029a7108 and PR #69411.
Copy link
Collaborator Author

@marc-hb marc-hb Mar 19, 2024

Choose a reason for hiding this comment

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

I usually do avoid this but this issue is really complex (even when the corresponding code is not) and that PR discussion is quite important.

@marc-hb marc-hb added this to the v3.7.0 milestone Jun 17, 2024
@marc-hb
Copy link
Collaborator Author

marc-hb commented Jun 17, 2024

Tentative v3.7.0 milestone because this PR is:

  • fixing C++ compatibility
  • adding tests.

Absolutely zero feature change.

@fabiobaltieri fabiobaltieri requested a review from aescolar June 18, 2024 00:45
stephanosio
stephanosio previously approved these changes Jun 18, 2024
@aescolar aescolar added the bug The issue is a bug, or the PR is fixing a bug label Jun 18, 2024
cfriedt
cfriedt previously approved these changes Jun 21, 2024
@marc-hb marc-hb removed the Enhancement Changes/Updates/Additions to existing features label Jun 26, 2024
@nashif
Copy link
Member

nashif commented Jun 27, 2024

@gmarull please review

# define Z_DEVICE_INIT_ENTRY_DEV(node_id, dev_id) Z_DEV_ENTRY_DEV(node_id, dev_id)
#endif

#define Z_DEV_ENTRY_DEV(node_id, dev_id) \
Copy link
Collaborator

Choose a reason for hiding this comment

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

Odd to find this macro defined after it was "used" above. Not strictly required, of course.

Copy link
Collaborator Author

@marc-hb marc-hb Jul 3, 2024

Choose a reason for hiding this comment

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

This places the macro closer to the two locations where it's used.

It's also a lower-level implementation detail, so I think it it reads better last - that's subjective of course.

EDIT: I wrote too fast, I was referring to Z_DEVICE_INIT_ENTRY_DEV(). Then I wanted to preserve the "top-down" order for the next macro.

I think it's "odd" only if you're tainted by C compilation which requires "forward" declarations. Maybe dating all the way back to when compilation was performed in a single pass? Funny how the pre-processor is in some respect more advanced that C itself... https://stackoverflow.com/questions/3136686/is-the-c99-preprocessor-turing-complete

* more details see https://docs.zephyrproject.org/latest/develop/languages/cpp/
*/
#if defined(__STDC_VERSION__) && (__STDC_VERSION__) < 201100
# define Z_DEVICE_INIT_PM_BASE(pm_) ({ .pm_base = (pm_),})
Copy link
Member

Choose a reason for hiding this comment

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

isn't this missing a trailing ,?

Copy link
Member

Choose a reason for hiding this comment

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

see #74970

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Great catch, thank you @gmarull for the fix in #74970. Note this regression is only 3 weeks old and independent of this PR. My bad though for not noticing it when I rebased on top of it.

So I just:

marc-hb added 4 commits July 2, 2024 23:34
Conditionally remove braces for designated initializers of anonymous
unions. This makes it compatible with C++20 while not breaking pre-C11
gcc.

This does for device.h what commit c15f029 ("init.h: restore
designated initializers in SYS_INIT_NAMED()") did for init.h

See https://docs.zephyrproject.org/latest/develop/languages/cpp/ and
long discussion in zephyrproject-rtos#69411 for more obscure C/C++ compatibility details.

Signed-off-by: Marc Herbert <[email protected]>
This provides C++ build test coverage for device.h (notably:
Z_DEVICE_INIT() fixed in the previous commit) and for some other Device
Tree macros.

Signed-off-by: Marc Herbert <[email protected]>
Fixes the following error appearing in the test coverage added by the
next commit:

In file included from zephyr/tests/lib/cpp/cxx/src/main.cpp:18:
```
zephyr/include/zephyr/pm/device.h:275:9: error: designator order for
  field 'pm_device_base::state' does not match declaration order
                        in 'pm_device_base'
  275 |         }
      |         ^
zephyr/include/zephyr/pm/device.h:315:17: note: in expansion of
                                                macro 'Z_PM_DEVICE_INIT'
  315 |              Z_PM_DEVICE_INIT(Z_PM_DEVICE_NAME(dev_id), node_id,
```

Note this failure is observed with any g++ -std=c++NN standard value -
even before C++20.

Signed-off-by: Marc Herbert <[email protected]>
Note CONFIG_PM_* affects device.h too. Even if not compiled, the more
code the pre-processor sees the better.

Signed-off-by: Marc Herbert <[email protected]>
@marc-hb marc-hb dismissed stale reviews from cfriedt, stephanosio, andyross, and fabiobaltieri via efa14ae July 2, 2024 23:42
marc-hb referenced this pull request in thesofproject/zephyr Jul 2, 2024
This option allows you to look up a struct device from any of the
node labels that were attached to the devicetree node used to create
the device, etc.

This is helpful because node labels are a much more human-friendly set
of unique identifiers than the node names we are currently relying on
for use with device_get_binding(). Adding this infrastructure in the
device core allows anyone to make use of it without having to
replicate node label storage and search functions in various places in
the tree. The main use case, however, is for looking up devices by
node label in the shell.

Since there is a footprint penalty associated with storing the node
label metadata, leave this option disabled by default.

Signed-off-by: Martí Bolívar <[email protected]>
Copy link
Collaborator Author

@marc-hb marc-hb left a comment

Choose a reason for hiding this comment

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

Just force-pushed:

NO OTHER CHANGE.

Please re-review this very minor update quickly before I have to rebase on top of another regression and then another fix :-)

Sorry for the inconvenience.

# define Z_DEVICE_INIT_ENTRY_DEV(node_id, dev_id) Z_DEV_ENTRY_DEV(node_id, dev_id)
#endif

#define Z_DEV_ENTRY_DEV(node_id, dev_id) \
Copy link
Collaborator Author

@marc-hb marc-hb Jul 3, 2024

Choose a reason for hiding this comment

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

This places the macro closer to the two locations where it's used.

It's also a lower-level implementation detail, so I think it it reads better last - that's subjective of course.

EDIT: I wrote too fast, I was referring to Z_DEVICE_INIT_ENTRY_DEV(). Then I wanted to preserve the "top-down" order for the next macro.

I think it's "odd" only if you're tainted by C compilation which requires "forward" declarations. Maybe dating all the way back to when compilation was performed in a single pass? Funny how the pre-processor is in some respect more advanced that C itself... https://stackoverflow.com/questions/3136686/is-the-c99-preprocessor-turing-complete

* more details see https://docs.zephyrproject.org/latest/develop/languages/cpp/
*/
#if defined(__STDC_VERSION__) && (__STDC_VERSION__) < 201100
# define Z_DEVICE_INIT_PM_BASE(pm_) ({ .pm_base = (pm_),})
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Great catch, thank you @gmarull for the fix in #74970. Note this regression is only 3 weeks old and independent of this PR. My bad though for not noticing it when I rebased on top of it.

So I just:

@marc-hb
Copy link
Collaborator Author

marc-hb commented Jul 8, 2024

[minor changes]
NO OTHER CHANGE.
Please re-review this very minor update quickly before I have to rebase on top of another regression and then another fix :-)
Sorry for the inconvenience.

Could I get just one of the previous approvers to take another, quick look? Thanks in advance!

@nashif nashif merged commit 65f6362 into zephyrproject-rtos:main Jul 8, 2024
23 checks passed
@marc-hb marc-hb deleted the c++device branch October 9, 2024 21:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: C++ area: Device Model area: Power Management area: Tests Issues related to a particular existing or missing test area: Toolchains Toolchains bug The issue is a bug, or the PR is fixing a bug
Projects
None yet
Development

Successfully merging this pull request may close these issues.