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

Improve C89 compliance #746

Conversation

real-or-random
Copy link
Contributor

@real-or-random real-or-random commented Apr 22, 2020

This PR

  • replaces ull constants by UINT64() constants because ull is strictly speaking not supported by C89.
  • does the same for UINT32() for the sake of consistency both with UINT64() but also in general with the uintXX_t types we use (if we use uintXX_t using the corresponding constant macros is the most natural thing to do)
  • makes gen_context.c C89 compliant. (It was not but we didn't notice because it has its own CFLAGS)

Please see the commit messages to see how to re-create the first commit. This will make reviewing this rather trivial.

edit: I know this touches > 300 lines but I think it will hardly annoy any existing PRs because the lines with constants are typically not touched.

This commit is the result of creating a file constants.sed with contents
```
s/(0x([A-F]|[0-9])+)ULL/UINT64_C(\1)/gi
s/(0x([A-F]|[0-9])+)UL/UINT32_C(\1)/gi
s/(([0-9])+)ULL/UINT64_C(\1)/gi
s/(([0-9])+)UL/UINT32_C(\1)/gi
s/(([0-9])+)LL/INT64_C(\1)/gi
```
and running `sed -E -i -f constants.sed src/*.[ch]` (and fixing custom
indentation in four affected lines).

Use `git grep -iE '([A-F]|[0-9])UL'` to verify the result.

Moreover, this commit removes `-Wno-long-long` from CFLAGS, which is no longer
needed then. It also removes `-Wno-overlength-strings`, which is apparently
not needed currently either.

The motivation for this change is compliance with C89 (bitcoin-core#745) for ULL/LL but also
reviewability: Even though it's not relevant in the current code, I think it's
confusing to use the portable uint32_t/uint64_t types but then constants of
the unsigned long (long) types, which differ across targets.

Fixes bitcoin-core#745.
@sipa
Copy link
Contributor

sipa commented Apr 22, 2020

I believe these macros, as well as stdint.h itself, only exist as of C99...

@real-or-random
Copy link
Contributor Author

@sipa
Well, it's true that only C >=99 requires the existence of stdint.h. But that does not prevent a C89 compiler from providing it. In fact, even C99 does not guarantee that uint32_t and uint64_t exist. So our working model is C89 with uint32_t/uint64_t support. That fits the wording in the README: "Intended to be portable to any system with a C89 compiler and uint64_t support." (if you add the very reasonable implicit assumption that such a C compiler will also provide uint32_t).This initially confused me too, see the discussion in #568 (comment) and https://stackoverflow.com/a/26502360/2725281.

Initially we left long long in, probably because noone cared. (#193). And I still think noone cares.

Another discussion is whether we want to give up the C89 requirement. If I were to start a new project, I wouldn't use C89. But here's a pragmatic view: given that made sure the entire codebase is C89 (modulo this PR), there's no reason to give this up now. It's sometimes annoying but I can live with it (and I prefer living it with over having the discussion). Things would change of course if a specific language feature not available in C89 would make the implementation of a new feature much easier for example.

But I think all of this misses the main point of this PR. I think it's simply cleaner code and the right thing(TM) to use uint32_t for uint32_t computations and long constants for long computations. If they turn out to be equivalent, fine, but everyone looking at the code needs to think about this every time.

@sipa
Copy link
Contributor

sipa commented May 20, 2020

This made me look up the rules for types of constants: https://en.cppreference.com/w/c/language/integer_constant

I think the majority of the constants here can simply lose all suffixes. I think only the uint64_t ones, and those where being less than 32 bits in size would be a problem.

With that in mind, concept ACK, but I think this can be simplified.

@elichai
Copy link
Contributor

elichai commented Jun 3, 2020

I honestly don't mind either way (either ditching C89 or being more strict with C89), I already got used to C89 (even though I don't like a lot of things there).
But I also don't know the effect of C99 on supporting embedded systems, so it feels to me the safer choice is to double down on C89, so I'm concept ACK

@elichai
Copy link
Contributor

elichai commented Jun 3, 2020

Just want to note that UINTN_C will expand to uint_leastN_t and not uintN_t according to: https://en.cppreference.com/w/c/types/integer

@real-or-random
Copy link
Contributor Author

With that in mind, concept ACK, but I think this can be simplified.

Yeah. I want to do this but I'll probably say this on a lot of PRs, and this is not a high priority... Let's close this one for now. Open for grabs if anyone wants to have it.

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.

3 participants