Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

strong types in c - (safety samples)

279 views
Skip to first unread message

Thiago Adams

unread,
Feb 11, 2024, 2:28:15 PMFeb 11
to
Consider:

void f(int i);

enum E {A};

int main(){
f(A); //cake will have a warning here
}


I will create a diagnostic in cake for this and others.
Basically I will respect the standard where it says enumerators are int,
but I will create a strict mode where this and other types of conversion
happens.


int main(){
f(true); //cake will have a warning here
f('A'); //not sure this one..
}

the same for enums.

Thiago Adams

unread,
Feb 11, 2024, 2:43:26 PMFeb 11
to
This is also part of "is C prepared to be safer language"?
This can breaks code, or it can be a diagnostic..
If it breaks code it needs to work as "warning profile" where
programmers can opt in or out.

With "warning profiles" the new semantics can be added without breaking
compatibility.




Kaz Kylheku

unread,
Feb 11, 2024, 3:37:23 PMFeb 11
to
On 2024-02-11, Thiago Adams <thiago...@gmail.com> wrote:
> Consider:
>
> void f(int i);
>
> enum E {A};
>
> int main(){
> f(A); //cake will have a warning here
> }

Why bother with enums that are stronger than in C++.

Mainly, you don't want this:

void f(enum E);
f(42);

--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @Kazi...@mstdn.ca

Thiago Adams

unread,
Feb 11, 2024, 4:20:01 PMFeb 11
to
Em 2/11/2024 5:37 PM, Kaz Kylheku escreveu:
> On 2024-02-11, Thiago Adams <thiago...@gmail.com> wrote:
>> Consider:
>>
>> void f(int i);
>>
>> enum E {A};
>>
>> int main(){
>> f(A); //cake will have a warning here
>> }
>
> Why bother with enums that are stronger than in C++.
>
> Mainly, you don't want this:
>
> void f(enum E);
> f(42);
>

In C++ this also compiles without errors.

https://godbolt.org/z/fYz4zqY3Y

(not sure if I understood you)

and

enum E {A};
void f(enum E e);

int main(){
f(1);
}

it an error in c++.
none in C

https://godbolt.org/z/7fqnv47dM



Keith Thompson

unread,
Feb 11, 2024, 5:09:07 PMFeb 11
to
Thiago Adams <thiago...@gmail.com> writes:
> Em 2/11/2024 5:37 PM, Kaz Kylheku escreveu:
>> On 2024-02-11, Thiago Adams <thiago...@gmail.com> wrote:
>>> Consider:
>>>
>>> void f(int i);
>>>
>>> enum E {A};
>>>
>>> int main(){
>>> f(A); //cake will have a warning here
>>> }
>> Why bother with enums that are stronger than in C++.
>> Mainly, you don't want this:
>> void f(enum E);
>> f(42);
>>
>
> In C++ this also compiles without errors.
>
> https://godbolt.org/z/fYz4zqY3Y
>
> (not sure if I understood you)

C++ has both C-style enums and "enum class" types, that have stricter
type checking (fewer implicit conversions).

--
Keith Thompson (The_Other_Keith) Keith.S.T...@gmail.com
Working, but not speaking, for Medtronic
void Void(void) { Void(); } /* The recursive call of the void */

Tim Rentsch

unread,
Feb 11, 2024, 11:38:51 PMFeb 11
to
This is comp.lang.c. Please take any discussions of languages
other than C to a venue where those discussions are topical,
such as comp.lang.misc.

Thiago Adams

unread,
Feb 11, 2024, 11:48:53 PMFeb 11
to
Not sure what you mean.
This is about C and diagnostics.

For instance:

void f(int i);
int main()
{
f(true);
}

If a compiler emit a diagnostic "warning passing _Bool to integer" do
you think this is not C any more?

Blue-Maned_Hawk

unread,
Feb 13, 2024, 2:59:11 AMFeb 13
to

Clang has an existing system for this with its
[[clang::enum_extensibility(open)]] and
[[clang::enum_extensibility(closed)]] attributes.


--
Blue-Maned_Hawk│shortens to
Hawk│/
blu.mɛin.dʰak/
│he/him/his/himself/Mr.
blue-maned_hawk.srht.site
Looks like it could explode at any moment!

Malcolm McLean

unread,
Feb 13, 2024, 4:09:26 AMFeb 13
to
On 11/02/2024 20:37, Kaz Kylheku wrote:
> On 2024-02-11, Thiago Adams <thiago...@gmail.com> wrote:
>> Consider:
>>
>> void f(int i);
>>
>> enum E {A};
>>
>> int main(){
>> f(A); //cake will have a warning here
>> }
>
> Why bother with enums that are stronger than in C++.
>
> Mainly, you don't want this:
>
> void f(enum E);
> f(42);
>
The problem is that enums often have to go through things which are
external to the program. For example they might be stored in a database
which is read by a parser which isn't written in C. So they can't be
treated as entirely opaque and sometimes you do need to manipulate the
values.

--
Check out Basic Algorithms and my other books:
https://www.lulu.com/spotlight/bgy1mm

Ben Bacarisse

unread,
Feb 13, 2024, 9:05:07 AMFeb 13
to
Malcolm McLean <malcolm.ar...@gmail.com> writes:

> On 11/02/2024 20:37, Kaz Kylheku wrote:
>> On 2024-02-11, Thiago Adams <thiago...@gmail.com> wrote:
>>> Consider:
>>>
>>> void f(int i);
>>>
>>> enum E {A};
>>>
>>> int main(){
>>> f(A); //cake will have a warning here
>>> }
>> Why bother with enums that are stronger than in C++.
>> Mainly, you don't want this:
>> void f(enum E);
>> f(42);
>>
> The problem is that enums often have to go through things which are
> external to the program. For example they might be stored in a database
> which is read by a parser which isn't written in C.

That's "a problem" (though not usually a hard one) but it's not got
anything to do with the current discussion about how C does, or should,
limit the use of implicit type conversions for enums.

Typically, "the problem" would be solved by the build system. It would
ensure that the names and values in the DB match (or correspond to)
those used in the C program, probably by generating a header file and/or
a DB table as part of the build.

> So they can't be
> treated as entirely opaque and sometimes you do need to manipulate the
> values.

But no one is suggesting that. The discussion is about what implicit
type conversions are, or should, be allowed without any diagnostic.

--
Ben.

Tim Rentsch

unread,
Feb 16, 2024, 11:23:51 AMFeb 16
to
The language you're talking about may have the same syntax
as C, but it has different semantic rules, and that is the
point of your discussion. What you're talking about is not
about C. I know you like to pretend that it's the same,
but it isn't.

Thiago Adams

unread,
Feb 17, 2024, 7:28:27 AMFeb 17
to
Perhaps you got a bad first impression. However, Cake is indeed 100% C.
The modes I am discussing here have not been implemented yet. Even when
implemented, they are not fundamentally different from, for instance,
gcc's -werror option.

I am not pretending Cake is C. I am following the C23 standard and other
compilers like gcc, clang and msvc. Cake have some extensions, like any
other C compiler and the extensions are documented.




Thiago Adams

unread,
Feb 18, 2024, 11:49:48 AMFeb 18
to
Em 2/11/2024 4:43 PM, Thiago Adams escreveu:
> Em 2/11/2024 4:27 PM, Thiago Adams escreveu:
>> Consider:
>>
>> void f(int i);
>>
>> enum E {A};
>>
>> int main(){
>>      f(A); //cake will have a warning here
>> }
>>
>>
>> I will create a diagnostic in cake for this and others.
>> Basically I will respect the standard where it says enumerators are
>> int, but I will create a strict mode where this and other types of
>> conversion happens.



In MISRA the concept is called "essential type"

a == b

The essential type of this expression is boolean.





Keith Thompson

unread,
Feb 18, 2024, 5:25:34 PMFeb 18
to
Thiago Adams <thiago...@gmail.com> writes:
[...]
> In MISRA the concept is called "essential type"
>
> a == b
>
> The essential type of this expression is boolean.

I don't have access to the MISRA guidelines (they're not free),
but if that's what they say, it sounds like they're badly written.

(It's available for £15.00 from misra.org.uk. I'm almost, but not
quite, tempted to buy a copy.)

There's no C type called "boolean" unless you define it yourself.
The "essential type" they call "boolean" obviously isn't bool or
_Bool. It's not even a type in the C sense. And other posts here
have suggested that MISRA never actually defines what "essential
type" means.

Do the guidelines use the term "essential type" for "types" other
than "boolean"?

It just seems that the authors failed to think of the word
"condition", which would be a much clearer and more precise
description of what I presume they're trying to say. For example,
they could have written than any expression used as a condition
shall not be an assignment and shall not have an assignment as
any of its subexpressions, and anyone familiar with C would know
exactly what they mean. (The C standard doesn't define "condition",
but it would be easy to enumerate the contexts in which expressions
are treated as conditions, i.e., where a decision is made based on
whether the expression compares unequal to zero.)

David Brown

unread,
Feb 18, 2024, 5:40:49 PMFeb 18
to
On 18/02/2024 23:25, Keith Thompson wrote:
> Thiago Adams <thiago...@gmail.com> writes:
> [...]
>> In MISRA the concept is called "essential type"
>>
>> a == b
>>
>> The essential type of this expression is boolean.
>
> I don't have access to the MISRA guidelines (they're not free),
> but if that's what they say, it sounds like they're badly written.

They were £10, last I bought a copy, so it's not /that/ expensive. But
IMHO the "essential type" stuff is not at all good.

>
> (It's available for £15.00 from misra.org.uk. I'm almost, but not
> quite, tempted to buy a copy.)

I'll probably buy a current version, because it is somewhat relevant to
my work. (Or I could get the office to buy it.)

>
> There's no C type called "boolean" unless you define it yourself.
> The "essential type" they call "boolean" obviously isn't bool or
> _Bool. It's not even a type in the C sense. And other posts here
> have suggested that MISRA never actually defines what "essential
> type" means.
>
> Do the guidelines use the term "essential type" for "types" other
> than "boolean"?

Oh, yes. They use it for lots of things, without good definitions,
without accurate consideration for things like integer promotion rules,
and in ways that somewhat differ from the actual C rules.

>
> It just seems that the authors failed to think of the word
> "condition", which would be a much clearer and more precise
> description of what I presume they're trying to say. For example,
> they could have written than any expression used as a condition
> shall not be an assignment and shall not have an assignment as
> any of its subexpressions, and anyone familiar with C would know
> exactly what they mean. (The C standard doesn't define "condition",
> but it would be easy to enumerate the contexts in which expressions
> are treated as conditions, i.e., where a decision is made based on
> whether the expression compares unequal to zero.)
>

They were trying to think of a way to say that things like the 0 or 1
int result of a comparison is not really the same thing as a normal
"int", and that the enumeration constants for an enumerated type are not
the same "essential type" as "int", and various other such things. They
are trying to invent their own type system that they think is better
than C's (and in some ways it /is/ better), and then say you should
write your C code as though it followed /their/ type system and not C's
type system.


Keith Thompson

unread,
Feb 18, 2024, 5:59:29 PMFeb 18
to
David Brown <david...@hesbynett.no> writes:
[...]
> They were trying to think of a way to say that things like the 0 or 1
> int result of a comparison is not really the same thing as a normal
> "int", and that the enumeration constants for an enumerated type are
> not the same "essential type" as "int", and various other such things.
> They are trying to invent their own type system that they think is
> better than C's (and in some ways it /is/ better), and then say you
> should write your C code as though it followed /their/ type system and
> not C's type system.

And then they don't clearly define their own type system, or distinguish
C types from MISRA types.

I suspect it's easy enough to get through the vague wording and figure
out what the guidelines actually mean, but it sounds like the whole
thing would benefit from a rewrite.

Thiago Adams

unread,
Feb 19, 2024, 6:35:00 AMFeb 19
to
On 18/02/2024 19:25, Keith Thompson wrote:
> Thiago Adams <thiago...@gmail.com> writes:
> [...]
>> In MISRA the concept is called "essential type"
>>
>> a == b
>>
>> The essential type of this expression is boolean.
>
> I don't have access to the MISRA guidelines (they're not free),
> but if that's what they say, it sounds like they're badly written.

Searching for MISRA "essential type" we can find something.

For instance:

https://stackoverflow.com/questions/44131637/misra-c-2012-rule-10-1-boolean-operand-to-be-used-in-case-where-expression-is-of


Thiago Adams

unread,
Feb 19, 2024, 1:21:45 PMFeb 19
to
On 11/02/2024 16:27, Thiago Adams wrote:
> Consider:
>
> void f(int i);
>
> enum E {A};
>
> int main(){
>     f(A); //cake will have a warning here
> }
>
>
> I will create a diagnostic in cake for this and others.
> Basically I will respect the standard where it says enumerators are int,
> but I will create a strict mode where this and other types of conversion
> happens.

It is interesting to note that treating warnings as errors is not
something new.


"The initial ISO C standard and its 1999 revision removed support for
many C language features that were widely known as sources of
application bugs due to accidental misuse. For backwards compatibility,
GCC 13 and earlier diagnosed use of these features as warnings only.
Although these warnings have been enabled by default for many releases,
experience shows that these warnings are easily ignored, resulting in
difficult to diagnose bugs. In GCC 14, these issues are now reported as
errors, and no output file is created, providing clearer feedback to
programmers that something is wrong. "

https://gcc.gnu.org/gcc-14/porting_to.html#c


Keith Thompson

unread,
Feb 19, 2024, 1:40:05 PMFeb 19
to
I wouldn't call that "treating warnings as errors". I'd call it "no
longer treating errors[*] as mere warnings".

[*] The C standard never requires anything other than a #error directive
as a fatal error, but it does define constraints and syntax rules,
violations of which require a diagnostic. gcc has traditionally treated
certain violations as non-fatal errors by default. With gcc 14 (not yet
released), they're apparently changing at least some of these from
warnings to fatal errors (which IMHO they should have been already).

Thiago Adams

unread,
Feb 19, 2024, 2:03:29 PMFeb 19
to
The interesting part is that it stop compilation. In this aspect the new
compiler is assuming a safer approach.

The other approach could be settings then if someone wants to update the
compiler and keeps the old code compiler it is just a matter of changing
settings. But new compiler has new defaults.



Thiago Adams

unread,
Feb 19, 2024, 2:06:48 PMFeb 19
to
Something related

https://embeddedartistry.com/blog/2017/05/22/werror-is-not-your-friend/

"Different vendors have different warning sets and warning detection
logic, even if they support a common array of warning settings (such as
with GCC and Clang). Code that compiles with one toolchain warning-free
may not do so with another toolchain. We often see this with our
open-source projects. We primarily use Clang, and it is a common
occurrence that our CI server will report a warning when compiling our
“warning-free” code with GCC."

Safety is not portable.

Keith Thompson

unread,
Feb 19, 2024, 2:31:35 PMFeb 19
to
Yes, that's pretty much what I said.

>> The other approach could be settings then if someone wants to update
>> the compiler and keeps the old code compiler it is just a matter of
>> changing settings. But new compiler has new defaults.
>
> Something related
>
> https://embeddedartistry.com/blog/2017/05/22/werror-is-not-your-friend/
>
> "Different vendors have different warning sets and warning detection
> logic, even if they support a common array of warning settings (such
> as with GCC and Clang). Code that compiles with one toolchain
> warning-free may not do so with another toolchain. We often see this
> with our open-source projects. We primarily use Clang, and it is a
> common occurrence that our CI server will report a warning when
> compiling our “warning-free” code with GCC."
>
> Safety is not portable.

The problem with -Werror is that it treats *all* warnings as fatal
errors. (Which an also be an advantage if you're aware of the issues).

But that's not directly related. The changes in gcc-14 have to do with
treating some constraint violations as fatal errors rather than warnings
by default. You can use -pedantic-errors to do the same thing.

David Brown

unread,
Feb 19, 2024, 3:36:19 PMFeb 19
to
On 19/02/2024 20:06, Thiago Adams wrote:
>
> Something related
>
> https://embeddedartistry.com/blog/2017/05/22/werror-is-not-your-friend/
>
> "Different vendors have different warning sets and warning detection
> logic, even if they support a common array of warning settings (such as
> with GCC and Clang). Code that compiles with one toolchain warning-free
> may not do so with another toolchain. We often see this with our
> open-source projects. We primarily use Clang, and it is a common
> occurrence that our CI server will report a warning when compiling our
> “warning-free” code with GCC."
>
> Safety is not portable.
>


The blog's reasoning is flawed.

A project build is dependent on three main things. The source code is
one. The toolchain is another. And the build instructions - including
toolchain flags and options, linker scripts, and perhaps things like the
order of files passed to the linker. (It may also depend on things like
the time and day, if you use macros like __DATE__ and __TIME__, which is
an extraordinarily silly thing to have as a dependency.)

If you are making code that is important enough to be using CI tools,
and you have random mixtures of toolchains for different developers,
your CI server, and other parts of the system, then your development
process is badly broken. You are doing your CI and testing on a
different project from the one developers are working on, and the
projects being shipped to customers can be different again.

It can be a different matter if the deliverable for the project is just
the source code. But if it is a binary, then everything that goes into
the binary is part of the source for it, and needs to be kept under
tight control in the development process.

You might feel that it is useful to build multiple binaries using
different toolchains, perhaps to take advantage of static checks that
are available in a range of tools, or to ensure wider compatibility.
But then all those toolchains are part of the development process.

If you have not reached the stage of getting reproducible builds that
give the same binary every build for every developer, you are not ready
for tools like CI.


This is all IMHO, needless to say.

bart

unread,
Feb 19, 2024, 5:13:38 PMFeb 19
to
On 19/02/2024 20:36, David Brown wrote:
> On 19/02/2024 20:06, Thiago Adams wrote:
>>
>> Something related
>>
>> https://embeddedartistry.com/blog/2017/05/22/werror-is-not-your-friend/
>>
>> "Different vendors have different warning sets and warning detection
>> logic, even if they support a common array of warning settings (such
>> as with GCC and Clang). Code that compiles with one toolchain
>> warning-free may not do so with another toolchain. We often see this
>> with our open-source projects. We primarily use Clang, and it is a
>> common occurrence that our CI server will report a warning when
>> compiling our “warning-free” code with GCC."
>>
>> Safety is not portable.
>>
>
>
> The blog's reasoning is flawed.
>
> A project build is dependent on three main things.  The source code is
> one.  The toolchain is another.  And the build instructions - including
> toolchain flags and options, linker scripts, and perhaps things like the
> order of files passed to the linker.  (It may also depend on things like
> the time and day, if you use macros like __DATE__ and __TIME__, which is
> an extraordinarily silly thing to have as a dependency.)

I often use DATE and TIME in my products to help indicate version.

It's not silly at all.

But it means the binary produced will be slightly different to one
generated 5 minutes earlier.

Thiago Adams

unread,
Feb 19, 2024, 7:59:29 PMFeb 19
to
I have a better sample

Consider the literal string

u8"maçã"

if the source code is not UTF8 encoded then the result of compilation
u8"maçã" will depend where (locale) the source code is compiled because
the compiler will encode the bytes from the file according with the
locale. This happens all the time with visual studio where the default
for new files is not utft8 (fortunately the compiler have a warning now,
but not default it needs to be added)

for this reason, source code should be standardised to be UTF8. (I guess
C++ has a proposal for that)




Thiago Adams

unread,
Feb 19, 2024, 8:03:50 PMFeb 19
to
Em 2/19/2024 9:59 PM, Thiago Adams escreveu:
...
> for this reason, source code should be standardised to be UTF8. (I guess
> C++ has a proposal for that)
>

https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2295r6.pdf

Kaz Kylheku

unread,
Feb 19, 2024, 9:48:37 PMFeb 19
to
On 2024-02-19, bart <b...@freeuk.com> wrote:
> I often use DATE and TIME in my products to help indicate version.
>
> It's not silly at all.
>
> But it means the binary produced will be slightly different to one
> generated 5 minutes earlier.

The problem is that it's possible that the only difference is the
date and time. In which case it's the same program. Just the binary is
gratuitously different.

Some GNU/Linux distros nowadays are obsessed with reproducibility:
meaning that whenver the same version of the same thing is built, all
the deliverables such as executables, PDF files or whatever else is bit
for bit identical to the previous runs.

This works even if if __DATE__ and __TIME__ are used; those get frozen.

Chris M. Thomasson

unread,
Feb 20, 2024, 12:16:31 AMFeb 20
to

Keith Thompson

unread,
Feb 20, 2024, 1:23:15 AMFeb 20
to
Can you clarify the relevance? It doesn't say much about bool or
booleans and doesn't mention "essential type" at all.

David Brown

unread,
Feb 20, 2024, 3:37:44 AMFeb 20
to
This refers to a small number of specific warnings, not warnings in
general, and it /is/ new - gcc 14 is not yet released.

It's a good change, IMHO - and long overdue.


David Brown

unread,
Feb 20, 2024, 3:43:56 AMFeb 20
to
It is definitely a silly thing to do if you are looking for tight
control of your builds - precisely because it means your binaries differ
on different builds. When you are running a more sophisticated
development setup - such as one where CI is appropriate - reproducible
builds are important. __DATE__ and __TIME__ guarantee that you can't do
that.

Not all development has to be with such builds, of course, and __DATE__
and __TIME__ can be helpful if you are going through a lot of changes
quickly and want to compare runs. But it means you can never go back to
your previous source and get exactly the same binary.

Janis Papanagnou

unread,
Feb 22, 2024, 7:01:11 AMFeb 22
to
On 20.02.2024 03:48, Kaz Kylheku wrote:
> On 2024-02-19, bart <b...@freeuk.com> wrote:
>> I often use DATE and TIME in my products to help indicate version.
>> It's not silly at all.
>> But it means the binary produced will be slightly different to one
>> generated 5 minutes earlier.

I recall our configuration management and version control systems
supported variables for release information[*] that got expanded by
the system as part of the defined software development processes...

>
> The problem is that it's possible that the only difference is the
> date and time. In which case it's the same program. Just the binary is
> gratuitously different.

...and it was a project's decision whether this information had an
accuracy of check-in level ("patch-level"), or minor release level,
or anything else. So binaries could vary in that attribute or not.

>
> Some GNU/Linux distros nowadays are obsessed with reproducibility:
> meaning that whenver the same version of the same thing is built, all
> the deliverables such as executables, PDF files or whatever else is bit
> for bit identical to the previous runs.
>
> This works even if if __DATE__ and __TIME__ are used; those get frozen.

Janis

[*] So there was no need to have an own mechanism for every language
or every type of source! - I don't think it's a good idea to have
for every type of item its own distinct and inconsistent mechanism
and format defined to support version and/or time/date information.

0 new messages