Token is not a valid binary operator in a preprocessor subexpression

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.

Just to be clear about what is supposed to happen, the macros are supposed to be iteratively expanded. In the working project, this can be emitted for illustration.

enum { testServiceCount = 0 +1 +1 +1 , testCharacteristicCount = 0 +1 +1 +1 +1 +1 +1 +1 +1 }; Perfectly acceptable in a comparison for conditional compilation.

This works in header inclusion when the compilation is an Objective C implementation.

Totally working in one project, but not the other.

Can you boil this down to a tiny test project? If so, please post it here and I’ll take a look.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Honestly, no. I have no idea what the problem is. I have a newer project with much of the identical code and that works fine. It's this somewhat larger but more important project that is older and suddenly stopped working. I have no promise of reproducing the problem in some random example.

I was hoping for some reply with knowledge of Objective C compiler settings, but didn't happen. I will open a ticket with Apple. That will allow me to privately share the actual project.

Cheers.

I did just try to create a new project and added all the same files and got the same error. Have not yet gotten a response to my issue beyond the auto-response.

Ensure that both projects are using the same C language dialect in their build settings. Look for C Language Dialect and C++ Language Dialect settings under Build Settings. They should be set to the same version (e.g., GNU99, GNU11).


I did do that for both C and C++, although I do not use C++. It had no effect. I think the important part is there is no such setting in the Objective C section.

Two files, in particular, use the .m extension and I assume that invokes the Objective C compiler. Both files include the same problematic header files. If I compile them individually using the Build/Perform Action menu then one succeeds and the other fails.

The one that succeeds has no Objective C objects coded. It does reference OS objects like NSArray, NSData. The one that fails has Objective C classes and objects that I coded.

Does the Objective C compiler have different paths of compilation based on the contents of the file? Could that lead to different implications of the C Processor? Note that the header includes are right up top in both cases.

Token is not a valid binary operator in a preprocessor subexpression
 
 
Q