Issue 890 in include-what-you-use: Suggest <cstdint> instead of <stdint.h>

316 views
Skip to first unread message

notifi...@include-what-you-use.org

unread,
Mar 26, 2021, 10:02:59 AM3/26/21
to include-wh...@googlegroups.com
New issue 890 by carlosgalvezp: Suggest <cstdint> instead of <stdint.h>
https://github.com/include-what-you-use/include-what-you-use/issues/890

Hi,

I want to use this amazing tool in our C++ project. We want to use C++ headers, so cstdint instead of stdint.h.
However the tool is suggesting to include stdint.h for uint32_t (for example).

I see in the code written:
https://github.com/include-what-you-use/include-what-you-use/blob/master/iwyu_include_picker.cc#L471

```
(If you *did* want to replace
// assert.h with cassert, you'd change it to a public->private
// mapping.)
```

Can you clarify how to implement this in practice? I've tried adding a mapping from stdint.h to <cstdint>, making stdint.h private, but then it complains that stdint.h has dual visibility (public and private).

Thanks!

notifi...@include-what-you-use.org

unread,
Mar 31, 2021, 4:43:16 AM3/31/21
to include-wh...@googlegroups.com
Comment #1 on issue 890 by Krzmbrzl: Suggest <cstdint> instead of <stdint.h>
https://github.com/include-what-you-use/include-what-you-use/issues/890

Looking at e.g.
https://github.com/include-what-you-use/include-what-you-use/blob/c5f3b0fe4c5407d6379626d946dc67089c0d3844/qt5_11.imp#L3
it seems that the `.h` version should actually be listed without the `.h` file extension in the mapping.

Did you do that?

(Warning: I don't actually have a clue about all this - this is just my first thought on this and I figured I might as well share it with you)

notifi...@include-what-you-use.org

unread,
Mar 31, 2021, 4:54:19 AM3/31/21
to include-wh...@googlegroups.com
Comment #2 on issue 890 by carlosgalvezp: Suggest <cstdint> instead of <stdint.h>
https://github.com/include-what-you-use/include-what-you-use/issues/890

I don't think that's the case here. Qt doesn't have `.h` headers. Just like `cstdint.h` doesn't exist. There exists:

* C headers: `<stdint.h>`
* C++ headers: `<cstdint>`

I just have trouble understanding the sentence:
> you'd change it to a public->private mapping.

Change it where? Do I need to hack the source code, or can I do it in an .imp file? Change what? It would be nice with the exact line of code that accomplishes what the comment is suggesting.

notifi...@include-what-you-use.org

unread,
Apr 5, 2021, 8:45:47 AM4/5/21
to include-wh...@googlegroups.com
Comment #3 on issue 890 by kimgr: Suggest <cstdint> instead of <stdint.h>
https://github.com/include-what-you-use/include-what-you-use/issues/890

@carlosgalvezp I think that may be a typo/thinko in the comment. It seems to me a private->public mapping would be more suitable.

Here's how IWYU works with mappings:

* There are the original, compiled-in mappings for libstdc++ and gnu libc (that's where you found the comment)
* There are external mappings in .imp files that can be applied on top of these built-in mappings. These are primarily meant to allow extensions for third-party libraries
* But there are also mirrors of the compiled-in mappings in external .imp files

So I think if you want to experiment with this, you can add `-Xiwyu --no_default_mappings` to the IWYU command line to avoid using the compiled-in mappings.

Then you need to use `-Xiwyu --mapping_file=xyzxyz.imp` for each mapping file you want to apply.

It sounds like you want to change the mapping for some of the files from:

{ "<assert.h>", kPublic, "<cassert>", kPublic },

to

{ "<assert.h>", kPrivate "<cassert>", kPublic },

(the spelling is a little different in .imp files, but I'm sure you can figure that out).

Save your changes to a distinct .imp file and use that instead of the provided one.

That _should_ work, but is pretty cumbersome.

notifi...@include-what-you-use.org

unread,
Apr 7, 2021, 7:31:33 AM4/7/21
to include-wh...@googlegroups.com
Comment #4 on issue 890 by carlosgalvezp: Suggest <cstdint> instead of <stdint.h>
https://github.com/include-what-you-use/include-what-you-use/issues/890

Hi,

Thanks for the feedback! I tried that, but it doesn't work because either the pre-build mappings or the `gcc.symbols.imp` mapping is defining [this](https://github.com/include-what-you-use/include-what-you-use/blob/master/gcc.symbols.imp#L52):

```
{ symbol: [ "int16_t", private, "<stdint.h>", public ] },
```

So it's saying that `<stdint.h>` is `public`, and now I want to turn it into `private`. The tool doesn't like that :)

Of course I could start from the very scratch and create a `gcc.symbols.imp` myself to point to `cstdint` instead, but I was hoping I could reuse the amazing work already done.

This would still not quite solve the issue - if a project contains both .c and .cpp files, I want the .c files to include `stdint.h`, and the .cpp files `cstdint`. I could of course code some script that passes a different configuration file depending on what file it's analyzing, but again it feels like something that should be supported by the tool.

notifi...@include-what-you-use.org

unread,
Apr 8, 2021, 11:17:52 AM4/8/21
to include-wh...@googlegroups.com
Comment #5 on issue 890 by carlosgalvezp: Suggest <cstdint> instead of <stdint.h>
https://github.com/include-what-you-use/include-what-you-use/issues/890

By the way, adding `--no_default_mappings` leads to the following error:

```
ERROR: include-what-you-use failure, -6
ERROR: include-what-you-use stderr: Cycle in include-mapping:
<limits.h> ->
<limits.h> ->
<limits.h>
iwyu_include_picker.cc:960: Assertion failed: Cycle in include-mapping
```

notifi...@include-what-you-use.org

unread,
Apr 8, 2021, 11:18:11 AM4/8/21
to include-wh...@googlegroups.com
Comment #5 on issue 890 by carlosgalvezp: Suggest <cstdint> instead of <stdint.h>
https://github.com/include-what-you-use/include-what-you-use/issues/890

By the way, adding `--no_default_mappings` leads to the following error:

```

notifi...@include-what-you-use.org

unread,
Apr 11, 2021, 7:59:14 AM4/11/21
to include-wh...@googlegroups.com
Comment #5 on issue 890 by kimgr: Suggest <cstdint> instead of <stdint.h>
https://github.com/include-what-you-use/include-what-you-use/issues/890

@carlosgalvezp We don't have a way of predicating mappings on things like language mode. Generally, I think that's up to the buildsystem (assuming it's possible to put separate `CFLAGS` for C and C++ files), but I can see how it's inconvenient.

> So it's saying that <stdint.h> is public, and now I want to turn it into private. The tool doesn't like that :)

That asserts somewhere, right? I wonder if that assertion should be removed, so we can use .imp files to override built-in behavior. The support for external .imps was added after the built-in mappings, so I suspect the assertion is there to catch bugs with conflicting mappings inside IWYU. External mappings should probably be trusted to override built-in, as an escape hatch, but I'm not sure what the downstream consequences of something like that would be.

notifi...@include-what-you-use.org

unread,
Apr 12, 2021, 4:53:23 AM4/12/21
to include-wh...@googlegroups.com
Comment #7 on issue 890 by carlosgalvezp: Suggest <cstdint> instead of <stdint.h>
https://github.com/include-what-you-use/include-what-you-use/issues/890

@kimgr That's a great suggestion, I think I can update my buildsystem to pass different mapping files depending on whether it's analyzing C or C++ files.

Being able to override default behavior on a more granular level without the tool failing the assertion would be awesome I think. Otherwise I need to override the whole default configuration, which seems a bit of a waste. Plus I get the error mentioned above that I don't quite know how to solve. Should I put up a new ticket for that one?

notifi...@include-what-you-use.org

unread,
Apr 12, 2021, 5:11:15 AM4/12/21
to include-wh...@googlegroups.com
Comment #8 on issue 890 by kimgr: Suggest <cstdint> instead of <stdint.h>
https://github.com/include-what-you-use/include-what-you-use/issues/890

> Plus I get the error mentioned above that I don't quite know how to solve. Should I put up a new ticket for that one?

@carlosgalvezp Already tracked, see issue 424.

notifi...@include-what-you-use.org

unread,
Apr 12, 2021, 7:35:09 AM4/12/21
to include-wh...@googlegroups.com
Comment #9 on issue 890 by carlosgalvezp: Suggest <cstdint> instead of <stdint.h>
https://github.com/include-what-you-use/include-what-you-use/issues/890

So I've tried the following:

- Comment out the assert for existing visibility: https://github.com/include-what-you-use/include-what-you-use/blob/master/iwyu_include_picker.cc#L1134
- Copy-paste https://github.com/include-what-you-use/include-what-you-use/blob/master/stl.c.headers.imp and replace `public` with `private` for the C headers.
- Run the tool with `-Xiwyu --mapping_file=std.c.headers.private.imp`

Still I get the following:

```
test/bar.cpp should add these lines:
#include <stdint.h> // for int32_t
```

How come?

notifi...@include-what-you-use.org

unread,
Apr 12, 2021, 7:35:33 AM4/12/21
to include-wh...@googlegroups.com
Comment #9 on issue 890 by carlosgalvezp: Suggest <cstdint> instead of <stdint.h>
https://github.com/include-what-you-use/include-what-you-use/issues/890

So I've tried the following:

- Comment out the assert for existing visibility: https://github.com/include-what-you-use/include-what-you-use/blob/master/iwyu_include_picker.cc#L1134
- Copy-paste https://github.com/include-what-you-use/include-what-you-use/blob/master/stl.c.headers.imp and replace `public` with `private` for the C headers.

- Run the tool with `-Xiwyu --mapping_file=stl.c.headers.private.imp`

notifi...@include-what-you-use.org

unread,
Apr 12, 2021, 8:26:51 AM4/12/21
to include-wh...@googlegroups.com
Comment #10 on issue 890 by kimgr: Suggest <cstdint> instead of <stdint.h>
https://github.com/include-what-you-use/include-what-you-use/issues/890

If you add `-Xiwyu -v7`, IWYU will output a painful amount of debug logs. Usually toward the end there's a step-by-step decision making process for which header is selected.

notifi...@include-what-you-use.org

unread,
Apr 12, 2021, 9:17:31 AM4/12/21
to include-wh...@googlegroups.com
Comment #11 on issue 890 by carlosgalvezp: Suggest <cstdint> instead of <stdint.h>
https://github.com/include-what-you-use/include-what-you-use/issues/890

Hmm, I set it to verbosity 10 and when grepping for "int32_t" I get only:

```
Found using-decl: /usr/include/c++/7.5.0/cstdint:50-50: 0x182e690 std::int32_t
...
Clang AST stuff
...
Mapped /usr/include/x86_64-linux-gnu/bits/stdint-intn.h to <stdint.h> for int32_t (set cover)
...
test/bar.cpp:12:10: warning: int32_t is defined in <stdint.h>, which isn't directly #included.
```

Funny thing is that there's nowhere in the IWYU repo any mention of `stdint-inth.h`. How can it be mapped to `stdint.h`?

notifi...@include-what-you-use.org

unread,
Apr 12, 2021, 9:17:57 AM4/12/21
to include-wh...@googlegroups.com

Funny thing is that there's nowhere in the IWYU repo any mention of `stdint-intn.h`. How can it be mapped to `stdint.h`?

notifi...@include-what-you-use.org

unread,
Apr 12, 2021, 9:19:42 AM4/12/21
to include-wh...@googlegroups.com

Adding these 2 mappings to my mapping file also doesn't have any effect:

```
{ include: [ "<bits/stdint-intn.h>", private, "<cstdint>", public ] },
{ include: [ "<stdint.h>", private, "<cstdint>", public ] },
```

notifi...@include-what-you-use.org

unread,
Apr 12, 2021, 9:33:57 AM4/12/21
to include-wh...@googlegroups.com
Comment #12 on issue 890 by kimgr: Suggest <cstdint> instead of <stdint.h>
https://github.com/include-what-you-use/include-what-you-use/issues/890

Could be a dynamic mapping based on libc annotations...? IIRC, gnu libc has comments that say "ay ay ay, this file is private, use this other one instead" and there's code in IWYU to interpret that and generate mappings.

notifi...@include-what-you-use.org

unread,
Apr 12, 2021, 9:35:56 AM4/12/21
to include-wh...@googlegroups.com
Comment #13 on issue 890 by kimgr: Suggest <cstdint> instead of <stdint.h>
https://github.com/include-what-you-use/include-what-you-use/issues/890

I realize I'm not sure how mapping lookups work there. I think maybe if one lookup succeeds, no others are attempted. So since your code has already triggered the first one, your additional mappings are never seen.

notifi...@include-what-you-use.org

unread,
Apr 13, 2021, 3:38:33 AM4/13/21
to include-wh...@googlegroups.com
Comment #14 on issue 890 by carlosgalvezp: Suggest <cstdint> instead of <stdint.h>
https://github.com/include-what-you-use/include-what-you-use/issues/890

I'll need to dig deeper into the code then :) Will comment back if/when I find some workaround!

Reply all
Reply to author
Forward
0 new messages