I have a relatively unique project layered with file types (top to bottom) SwiftUI, Swift, Objective C, and C. The purpose of this layering is that I have a C language firmware application framework for development of firmware on custom electronic boards.
Specifically, I use the standard C preprocessor in specific ways to make data driven structures, not code. There are header files shared between the firmware project and the Xcode iPhone app to set things like the BLE protocol and communication command/reply protocols, etc. The app is forced to adhere to that defined by the firmware, rather than rely a design to get it right.
The Objective C code is mainly to utilize the Bluetooth stack provided by iOS. I specifically use this approach to allow C files to be compiled. Normally, everything has worked perfectly, but a serious and obtuse problem just surfaced a couple days ago.
My important project was created long ago. More recently, I started a new project using most of the same technology, but its project is newer. Ironically, it continues to work perfectly, but ironically the older project stopped working. (Talking about the Xcode iOS side.)
Essentially, the Objective C handling of the C preprocessor is not fully adhering to the standard C preprocessing in one project. It's very confusing because there is no code change. It seems Xcode was updated, but looks like the project was not updated, accordingly? I'm guessing there is some setting that forces Objective C to adhere to the standard C preprocessor rules.
I did see a gnu compiler version that did not get updated compared to the newer project, but updating that in the Build Settings did not fix the problem.
The error is in the title: Token is not a valid binary operator in a preprocessor subexpression.
The offending macro appears in a header file, included in several implementation files. Compiling a single implementation files isolates the issue somewhat. An implementation with no Objective C objects compiles just fine. If there are Objective C objects then I get the errors. Both cases include the same header.
It seems like the Objective C compiler, being invoked, uses a different C preprocessor parser, rather than the standard. I guess I should mention the bridging header file where these headers exist, as well. The offending header with the problem macro appears as an error in the bridging header if a full build is initiated.
Is there an option somewhere, that forces the Objective C compiler to honor the standard C processor? Note, one project seems to.
#define BLE_SERVICE_BLANK( enumTag, uuid, serviceType )
#define BLE_CHARACTERISTIC_BLANK( enumTag, uuid, properties, readPerm, writePerm, value)
#define BLE_SERVICE_ENUM_COUNTER( enumTag, uuid, serviceType) +1
#define BLE_CHARACTERISTIC_ENUM_COUNTER( enumTag, uuid, properties, readPerm, writePerm, value) +1
#if 0 BLE_SERVICE_LIST(BLE_SERVICE_ENUM_COUNTER, BLE_CHARACTERISTIC_BLANK) > 0
#define USING_BLE_SERVICE
...
#if 0 BLE_SERVICE_LIST(BLE_SERVICE_BLANK, BLE_CHARACTERISTIC_ENUM_COUNTER) > 0
#define USING_BLE_CHARACTERISTIC
...
token is not a valid binary operator in a preprocessor subexpression refers to the comparison. BLE_SERVICE_LIST() does a +1 for each item in the list. There is no further expansion. One counts services. The other counts characteristics. The errors are associated with the comparisons.