Why does this compile?

void loop() {

 boolean myBool;

 myBool = 10000000;
 myBool = "this is plain silly";
 myBool = 3.1415;

}

I had to laugh and then cry that that something as basic as type-checking is not performed in the IDE.
Other C compilers will give error messages, so I wondered what is the problem here and imagine all the noob mistakes that would be caught and prevented.

Is this due to C++ Overloading or Polymorphism?
I think it's terrible there is no type-checking happening.

it does not compile...this would compile

void setup() {
  boolean myBool;
  myBool = 10000000;
  myBool = "this is plain silly";
  myBool = 3.1415;
}
void loop() {}

you would get a warning

warning: variable 'myBool' set but not used [-Wunused-but-set-variable]

the reason you don't get more warning is that C++ has Implicit conversions to the bool type that is defined by the standard. Anything evaluating to 0 is false, the rest is true. (in C++ boolean is an effective truth type, not a fake type as in C)

Boolean conversions
A prvalue of integral, floating-point, unscoped enumeration, pointer, and pointer-to-member types can be converted to a prvalue of type bool.

The value zero (for integral, floating-point, and unscoped enumeration) and the null pointer and the null pointer-to-member values become false. All other values become true.

The other reason the code won't be a problem is that the optimiser will notice you don't use myBool and thus it will likely be just tossed away and there will be no code generated for it. You can try compiling this code

void setup() {}
void loop() {}

and you'll see the very same memory usage as the code above

prairiemystic:
I had to laugh and then cry that that something as basic as type-checking is not performed in the IDE.
Other C compilers will give error messages, so I wondered what is the problem here and imagine all the noob mistakes that would be caught and prevented.

Before criticizing the compiler, you should spend some time reading the language specification, which defines what is, and it not, legal. The compiler follows the language specification, not the assumptions of random uninformed people.

prairiemystic:
Other C compilers will give error messages

No they don't: Compiler Explorer

prairiemystic:
Is this due to C++ Overloading or Polymorphism?

No, this is an implicit conversion taking place, see the link posted by J-M-L.

prairiemystic:
I think it's terrible there is no type-checking happening.

There is type-checking, the conversions you're talking about are simply allowed by the type system.

I agree that these conversions shouldn't be implicit, but for the sake of backwards compatibility, this is unlikely to change in C and C++.

For your own types, you should always make the conversion to bool explicit: explicit specifier - cppreference.com

As a side note, don't use boolean, it's non-standard, use bool.

Pieter

Preferences->Compiler Warnings->All
will show the warning "In function 'void loop()': warning: variable 'myBool' set but not used [-Wunused-but-set-variable]"

Thanks to everyone for clarifying - I understand now it's the C++ language doing implicit conversions. I did not know they magically happen when making an assignment, as opposed to evaluating a conditional expression.

I consider the C++ language for embedded systems extra dangerous because mixing types causes unexpected conversions and results, well and other aspects. How do you learn and find out how a string gets assigned to a boolean? No, don't tell me - the issue is how a person can learn this without rummaging through the compiler-generated code and playing around and wasting your day.

A person can learn these things by reading the language specification, or any of the thousands of books that teach the C language, or taking a class, or dozens of other ways. How those expressions get evaluated is quite simple, IF you take the time to learn the basics. There is NO need to look at the generated code. The precise conversions are VERY well documented.

I re-read K&R 2.7 Type Conversions which refers to Appendix A Section 6 pg.142
The type conversions given are straightforward, I guess it's like the compiler doing a Cast() without telling you.
I only use explicit type conversion to prevent sneaky code and keep it straightforward.

"When an operator has operands of different types, they are converted to a common type according to a small number of rules. In general, the only automatic conversions are those that convert a ‘‘narrower’’ operand into a ‘‘wider’’ one without losing information, such as converting an integer into floating point in an expression like f + i. Expressions that don’t make sense, like using a float as a subscript, are disallowed. Expressions that might lose information, like assigning a longer integer type to a shorter, or a floating-point type to an integer, may draw a warning, but they are not illegal."

edit: URL is to older K&R but seems unchanged

prairiemystic:
I consider the C++ language for embedded systems extra dangerous because mixing types causes unexpected conversions and results, well and other aspects. How do you learn and find out how a string gets assigned to a boolean? No, don't tell me - the issue is how a person can learn this without rummaging through the compiler-generated code and playing around and wasting your day.

That is why some industries have coding standards that have additional rules for developers. A often used standard is MISRA C which was originally targeted for automotive applications. And then companies can have their own coding guidelines or rules on top of that.

Companies like LDRA provide tools that enforce compliance with these rules. So, even when you write code that is legal under the C/C++ standard the tools will create errors and warnings to tell the developer which line of the code needs to be modified and what rules where violated.

I consider the C++ language for embedded systems extra dangerous

what strong typed language do you propose for embedded system and firmware development when you need register access, direct memory management, precise timing etc...

I've seen some attempts at real time languages but poor adoption (for example Oracle has disbanded the JavaRTS team) and heavy requirements on the underlying architecture capabilities. C and C++ remains largely used in the industry with coding rules and norms and code reviews etc to avoid pitfalls...

IMHO there's a need for a programming language that has safe handling of variables.
We've had decades of trojans thanks to C/C++ buffer overflows, heap overrun vulnerabilities and the like. Relying on the humans to code perfectly as well is unrealistic and a compiler doing things in the background you can't figure out or know about, and ignoring common programming mistakes (such as mixing up types, wrong size arrays) just makes it worse.

Range-checking, (array) bounds checking and type-checking are absolutely needed in embedded systems. I think Computing Science went in a bad direction abandoning these notions.

In the context of Arduino, I see noobs spend too much time trying to figure out the language and what is going on with their code. No single-stepping to help debug, it's just try something and re-compile and run, over and over again. It doesn't need to be so hard. ARM-core MCU's have loads of extra computing power to support run-time checking or an interpreter.

Dennis Ritchie lamented that C had to be backwards compatible with B. So we have a programming language from the very early days of computing carrying over legacy syntax and concepts from the 1970's. Programming languages are in the realm of academics- who "owns" the language or is the parent looking after it- it seems very difficult to create or fix or change a programming language, as if they are made of cement. They have to be backwards compatible, which is their doom, a clean slate you can't have. I appreciate C, love the Wild West cowboy flexibility it has but not the excessive dangers. It's old and nothing has been the update it needs, for embedded systems. Unless you have suggestions.

I'm not advocating any programming language here, that would just start a religious war.
Python has momentum, Adafruit is investing heavily in Circuit Python. Microsoft created C# for some reason.
C++ seems to have fallen into academic's circle-jerking, just look at the papers about adding the spaceship <=> operator, the language is not about readability, clarity, it seems to be some kind of monster now.

Yet, c & c++ have been, for over 40 years, consistently among the most-used programming languages in the world, while thousands of others have had their day as "flavor of the month", but long since been discarded. Perhaps that's because when used properly, c/c++ gets the job done quite nicely.

OK, to add some levity to this conversation...

Why don’t we all just use the VARIANT type.
Everything is compatible with everything !

J-M-L:
what strong typed language do you propose for embedded system and firmware development when you need register access, direct memory management, precise timing etc...

Rust.

prairiemystic:
Microsoft created C#

aka "I can't believe it''s not Java"

Rust is of interest, you can still access memory directly (Unsafe Rust) so prone to array bounds error, but you have strong typing.

Another reason Rust has an unsafe alter ego is that the underlying computer hardware is inherently unsafe. If Rust didn’t let you do unsafe operations, you couldn’t do certain tasks. Rust needs to allow you to do low-level systems programming, such as directly interacting with the operating system or even writing your own operating system. Working with low-level systems programming is one of the goals of the language.

J-M-L:
...so prone to array bounds error...

You fail to understand the benefit. If done correctly, those unsafe things are isolated to the smallest possible amount of code which allows them to be hand-verified. That allows those unsafe things to be proven safe. Building on those proven-to-be-safe things allows the entire rest of the application to be proven safe.

That process, quite literally, eliminates your "array bounds error".

thx for clarifying this

There is an interesting benefit in this world (processor controlling a physical device) that's not often mentioned. Rust supports a form of compile-time state machine. Let's say we're building a controller for a jet engine. Our jet engine has a starter motor. While the jet engine is running that starter motor can never be engaged. Doing so would be catastrophic. We can design our software such that the on/off for the starter motor is unreachable while our application is in the jet-engine-running state. Literally, the compiler can enforce that at compile time.

In the late 80s there was a great academic hullabaloo about a formally proved processor design (Viper? Intended for very high integrity systems, like weapons or aviation) that was later found to be flawed.

I know we're 30-odd years on from then, but human hubris never seems to make that much progress.

C has been long regarded as the original full-stack language, but whilst it truly is great at the low-level register-rattling stuff down in the device drivers, it really does suck further up the stack, even at the level of filesystems.

I know some companies that also rely on mathematical proof of a program's behavior against requirements (Formal verification). it makes writing requirements an interesting exercise.