Compiler error using arm-none-eabi-gcc and bool variables - c

I am trying to compile a usb loopback example for STM32 using arm-none-eabi-gcc but am stuck on a compiler error for bool variables. The error is error: expected ';', identifier or '(' before '_Bool' and the offending lines are
typedef enum
{
FALSE = 0, TRUE = !FALSE
}
bool;
From what I've read, it seems bool is an alias for _Bool while gcc transitions to bool being an actual type. Unfortunately I have no idea how to fix this. With some googling I've read that similar problems are sometimes related to having TRUE and FALSE defined elsewhere but I'm using largely unchanged code from STM and don't know of anywhere else they might be defined. I've also read that it could be due to linking against libc but get the same error when compiling with -nostdlib. Is there anything I can do to narrow down this problem? Thanks.

Since this typedef was trying to define a bool type and my compiler was trying to use the _Bool type, what I ended up doing was commenting out the typedef all together and just using
#define TRUE 1
#define FALSE 0
I'm not positive this solved the problem since I still can't get the usb device to enumerate, but the program now compiles.

Related

GNUC for ARM. Why would a #define need a defined type?

I'm trying to build the WolfSSL, using GNU-C 7.3.1 for ARMv7.
I am getting an error where I've never seen one before. In this code fragment for Wolfio.h:
#ifndef WOLFSSL_NO_SOCK
#ifndef XSOCKLENT
#ifdef USE_WINDOWS_API
#define XSOCKLENT int
#else
#define XSOCKLENT socklen_t
#endif
#endif
/* Socket Addr Support */
#ifdef HAVE_SOCKADDR
#ifndef HAVE_SOCKADDR_DEFINED
The 6th line in the above fragment:
#define XSOCKLENT socklen_t
Gives the error:
wolfio.h:383:31: error: unknown type name 'socklen_t'; did you mean '__socklen_t'?
Huh...?? why would a #define assignment need a type that exists?
I tried an alternate test in a dummy file of a different project, with the following. Neither of which are defined:
#define MYTYPE SOMETHING
And I received no error.
Because for decades I've believed that #defines are just preprocessor replacements. And doesn't analyze any of the source. My test in the dummy file confirms that belief.
So, somehow inside this large project, the GNU compiler got into it's head that a #define is really just a typedef?? And the RHS of the #define is required to be a defined type?
Is there a compiler or #pragma setting that makes it think this?
The project is for a TI ARM device, using their Code Composer studio
For reference, the compile args are (without my includes):
-mcpu=cortex-a8
-march=armv7-a
-mtune=cortex-a8
-marm
-mfloat-abi=hard
-mfpu=neon
-Dam3359
-Dam335x
-Dxdc_target_types__=gnu/targets/std.h
-Dxdc_target_name__=gnu/targets/arm/A8F
{includes}
-Ofast
-Wall
-specs="nosys.specs"
Any advice is appreciated.
#define does not care about any types as preprocessor only textually replaces strings (more precise tokens) and does not know anything about the C language and types.
The error is generated by the C compiler when the C file after the preprocessing was compiled (ie all XSOCKLENT tokens were replace by the socklen_t token).
I think this is just a misunderstanding caused by the compiler's error message format.
You are quite right that there is nothing wrong per se with defining a macro that expands to a nonexistent type. The issue is almost certainly that some other part of your program includes this header and declares a XSOCKLENT my_var; without having included <sys/socket.h> to get the socklen_t type defined. That would account for the unknown type name error.
What's confusing you is that the line number referenced by the error message is the definition of the XSOCKLENT macro. This is a feature; the idea being that when code resulting from macro expansion causes an error, then more often than not, the bug is in the way the macro was defined. Here, that happens to not be the case. But if you look at the next bit of the compiler output, you ought to see the file and line where the macro was used. That should be the file that needs to be including <sys/socket.h>. (Or maybe you want Wolfio.h to include it; you'll have to see what makes the most sense.)
Example: with the file
#define FOO djewiodjwoidjeiwojdiwe
FOO x;
GCC 11 outputs:
foo.c:1:13: error: unknown type name ‘djewiodjwoidjeiwojdiwe’
1 | #define FOO djewiodjwoidjeiwojdiwe
| ^~~~~~~~~~~~~~~~~~~~~~
foo.c:3:1: note: in expansion of macro ‘FOO’
3 | FOO x;
| ^~~
Note the first message points to line 1, where the macro is defined, and the second part of the message points to line 3, where it is used. If one isn't what you are looking for, then try the other.

Why is 'bool' keyword syntax highlighted in Xcode configured for C89?

I read that booleans in C first came with C99. Now I wonder why bool nevertheless gets colored by Xcode's syntax highlighting, or what you call it...
When one searches "dial" in the build settings in Xcode, the "Language Dialect" pops up, and there I "dial-in" the C89 standard, and still bool gets colored.
Why is that?
I also read this:
Using boolean values in C
and I see how they did it, but I also don't understand how Example 3 and 4 works...
Option 3
typedef int bool;
enum { false, true };
Option 4
typedef int bool;
#define true 1
#define false 0
Note: I don't understand how the typedef int bool; could in anyway be connected with the line enum { false, true };.
Why is xcode with C89 not ignoring the bool keyword?
How do the examples work?
The syntax highlighting is an approximation used by XCode; it's not guaranteed to follow any standard. Not to say the syntax highlighting in XCode is not fairly advanced, but it would be very difficult to tell without compiling for a specific standard, what the symbols mean exactly, in real-time.
In the case of Option 3, it's performing an implicit conversion from an anonymous enum to an int. Since they are compatible types, it is "always a no-op and does not change the representation." The default enum values for { false, true } are { 0, 1 }, so this should result in the same assembler output. This answer has the order of preference when one doesn't know what to pick.

Does C compiler distinguish type defined in user's code and library code?

#include <sys/types.h>
//Line 2: typedef unsigned int uint;
//Line 3: typedef unsigned int uint;
int main() {
uint a;
return 0;
}
Given the above C code, it's compiled successfully, for uint is defined in <sys/types.h>. Even though it's not standardized, it's added there for Sys V compatibility, commented in the code.
Uncomment the second line of the above code still results successful compiling. As I understand it's not allowed to redefine one type, confirmed by uncommenting the second and third lines, which will result in one compiling error.
How come the compiler is smart enough to know uint is defined in standard library or user's code? Both gcc and clang give consistent behavior.
Edit:
Linking is not part of the game in this case. The error is reproduced with compile only, i.e (-c option).
Line number is added to reduce confusion.
Edit:
Uncomment the second line of the above code still results successful compiling. As I understand it's not allowed to redefine one type, confirmed by uncommenting the second and third lines, which will result in one compiling error.
I have no idea why I wrote this. Apparently, uncommenting Line 2 and Line 3 doesn't result in compilation error for gcc. Clang gives error for the default compiling options is much more strict and could be tuned by passing some parameters.
Here describes whether multiple typedef is allowed or not, which turns out to be quite complicated. Anyway just try to avoid duplicate typedef.
Repeating a declaration is perfectly valid in C, so if you uncomment both lines as you describe you will not see any error, contrary to what you say.
Having two different declarations for a name would be an error.
Repeating a definition is an error as well, but a typedef is not a definition (despite the def), it is a declaration.
Standard library is also user code, usually written by another user.
Uncomment the second line of the above code still results successful compiling. As I >understand it's not allowed to redefine one type, confirmed by uncommenting the second and third lines, which will result in one compiling error.
On my gcc it does not. (version 4.5.3)
How come the compiler is smart enough to know uint is defined in standard library or user's code? Both gcc and clang give consistent behavior.
The compiler knows no distinction between user code and the one in the standard library. Although the compiler can distinguish between standard library files and user code, I really do not see any reason to do so. All it sees is textual data that it can lex/parse/codegen.

XC8 compiler error "no identifier in declaration"

I recently took over some C and firmware responsibilities at work, and am having trouble with what seems like a basic issue but one that I can't find the answer to. I'm not very experienced with C, but I've had many years of experience with higher level languages.
The firmware is written for a PIC18F4865 and I can't get it to compile and program correctly. It was originally written on MPLAB IDE 8 using the HI-TECH PICC18 compiler, but I moved up to MPLAB X IDE and have been having problems.
First, I was using the same HI-TECH PICC18 compiler and it appeared to program successfully, but the device was not reading correctly. I then switched to the XC8 compiler and began to get an error message during compile that I can't get around.
C:/_Sable/Firmware_C/lib\eeprom.h:10: error: no identifier in declaration
C:/_Sable/Firmware_C/lib\eeprom.h:10: error: ";" expected
The eeprom.h file is
#ifndef _EEPROM_H_
#define _EEPROM_H_
#define EE_ADDR(member) (offsetof(struct ee_map_s, (member)))
extern unsigned char eeprom_read(unsigned int); // this is line 10
extern void eeprom_write(unsigned int, unsigned char);
extern void ee_read(unsigned char, void *vp, unsigned char);
extern void ee_write(unsigned char, void *vp, unsigned char);
#endif
I looked around online and saw that this error can occur in a previous included file, and I checked that file and all appeared to be fine. I even rearranged the include order, think that the error message would change if that was the case, but the error still complains about this line.
I then thought maybe the function declaration was invalid because none of the parameters are named, so I changed line 10 to:
extern unsigned char eeprom_read(unsigned int addr)
This didn't change anything. But I did have a weird feeling that when I cleaned and built again, it was not re-compiling eeprom.h. I don't know if that happens or how to force it to recompile.
I don't know if fixing this will fix the firmware issues I'm having or if I need to go back to MPLAB IDE 8, but it is still something I'd like to fix.
Some header file is using a macro to #define eeprom_read into something else, possibly the empty string. If you use a different function name, #undef eeprom_read, or do something else to cause the header to no longer make that macro, it should work.

multiple definition of 'true' - but its not?

I have a double type bool so have added to a header:
typedef double bool;
extern bool true;
extern bool false;
with:
bool true = 1.0;
bool false = 0.0;
in the corresponding C file.
However I now have the errors multiple definition of true, and the same for false, pointing to the first line of the first function in the C file. the error that says 'previous declaration was here' points to the same line... it doesnt make any difference which function is placed first in the file it always points to it.
My header files, though included via a common header file, do have include guards so I hopefully shouldn't have multiple declaration of true and false there.
I have changed the typedef to tBool with vars tTrue and tFalse, which solves the problem, but I don't get why it occurred in the first place? As there are still some bool types using true and false in the code it seems like the compiler may have a definition for true and false as ints already... though I didn't think C did this
Im using dev-c++ 4.9.9.2 IDE that uses mingw, though Im not sure which version mingw.
Anyone know why this happened?
It sounds to me like your parameter is not really a Boolean value at all. You have a floating point parameter with special cases for the discrete numbers 0.0 and 1.0. Create two double constants instead of a type.
C99 added definitions for the type _Bool, a macro bool, a macro true, and a macro false. Try inserting the following in your header:
#if __bool_true_false_are_defined
# error "stdbool.h has been included"
#endif
#ifdef bool
# error "bool is already DEFINED"
#endif
#ifdef true
# error "true is already DEFINED"
#endif
#ifdef false
# error "false is already DEFINED"
#endif
If any of these fire, then you are including stdbool.h somewhere. You should be able to #undef the three macros and then set up your types safely. Of course, this will probably break if someone else expects bool to be a small integer value and has more style problems that you can shake a stick at.
ISO/IEC 9899:1999 does make a concession to the fact that many groups have already defined their own Boolean types before it was added to the Standard. This is the rationale for defining bool, true, and false as macros instead of new keywords. However, the following warning is explicitly included:
7.26.7 Boolean types and values <stdbool.h>
The ability to undefine and then perhaps redefine the macros bool, true, and false is an obsolescent feature.

Resources