Review Board

1.0

Changes to make Etoile compile with Clang

Updated 5 months, 3 weeks ago

Truls Becken Reviewers
EtoileCore
TheRaven
None Etoile trunk (etoile/trunk/Etoile)
This rather huge patch makes Étoilé build with make CC=clang CXX=clang++.

David said four months ago that everything compiled, but development happened since, and Clang is not as forgiving as GCC.

Please see my comments in the patch, which explains some things and asks some questions.

 
Posted 5 months, 4 weeks ago (March 14th, 2010, 8:34 a.m.)

   

  
In a number of places, NSDebugLog() is called with an extra argument in front.
I guess this has always been wrong, but GCC does not warn you that the
arguments do not match up with the format string, like Clang does.
  1. David pointed out that the correct fix is to use NSDebugLLog(), which I have done in revision 2 of the diff.
Clang is very strict about the types of format parameters.
Here it has to be %@, not %x.
  1. This should actually be %p, fixed in revision 2 of the diff.
Clang is more picky about forward references, and needs to actually import the interface more often.
Since "next" is an unsigned long, %d is not good enough.
It actually has to be %ld, or Clang complains.
To please Clang, I could just have added the missing comma here,
but the log message does not make sense so I fixed that as well.
  1. And the reason it didn't make sense was that I misunderstood the error.
    In revision 3 of the diff, the only change is that argument scrName is added.
./Frameworks/CoreObject/COMultiValue.m (Diff revision 1)
 
 
 
 
 
 
 
 
 
 
The big issue here is that the code was comparing pointers to strings rather than comparing their content.
We can avoid using strcmp because we know we only need to check the first character.
./Frameworks/EtoileFoundation/Headers/EtoileCompatibility.h (Diff revision 1)
 
 
 
 
 
 
 
__builtin_truncf() does not exist for Clang, just removing this define worked for me on Linux.
I do not know if <math.h> always works, but it did for me, and it seems better to rely on that
than on the compiler being GCC, at least. This change was done in 3 places.
./Frameworks/EtoileFoundation/Source/NSObject+Prototypes.m (Diff revision 1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
This change has been sitting in my tree for a long time, but it was not as clean before because I had to copy
method_getTypeEncoding() and class_getInstanceMethod() from RuntimeAbstraction to use them here.

Thankfully, they are now exposed from libobjc2, and ObjectiveC2 when not using that.
Programs using EtoileSerialize got linker errors with missing symbols from EtoileXML.

Adding this direct linkage fixed the issue for me, although it seems a little strange
that this is necessary when EtoileFoundation already links in EtoileXML.
Types need to match, (const char *) is not the same as (char *).
  1. The change should be the other way around as done in revision 2 of the diff.
    
    ETSerializerBackend is a protocol, and should use (const char*).
    All the implementations had (char*) and are now changed to (const char*).
Need to cast to char*, which means macro STORE_FIELD cannot be used for this one :-/
  1. This ugly change goes away completely with the change above, since sig[i].type is (const char*).
I guess somebody forgot to decide which one to use of bzero() and memset().
With Clang, using bzero() requires an include.
Btw, doesn't this memset() fill the buffer with a non-zero character?
  1. The memset() statement is on the line below the bzero().
    
    It's been too long since I used the review board, I expected the comments to be visible together with the diff when I wrote them.
  2. A bird told me that the better fix here was to scratch the implementation of the stringWithLongLong: method and just make it;
    
      return [NSString stringWithFormat: @"%lld", v];
./Frameworks/ObjectiveC2/runtime.h (Diff revision 1)
 
 
Clang does not allow redefining macros, so #undef them first.
./Frameworks/OgreKit/GNUmakefile (Diff revision 1)
 
OgreKit uses some AppKit classes.
./Frameworks/OgreKit/Headers/OgreTextFindThread.h (Diff revision 1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Moved out in a separate header to be imported in OgreTextFindProgressSheet.h
./Frameworks/PopplerKit/bindings/GNUmakefile (Diff revision 1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

     

  
Please ignore my changes to this file, David has fixed the code I commented out.
  1. And the commenting out was removed in revision 2 of the diff.
Please ignore my changes to this file, David has fixed the code I commented out.
Moved to Runtime/BlockClosure.h
It was actually GCC, not Clang, that complained about uninitialized variables.
Clang does not allow conditionals without any code to execute when the test succeeds.
I don't know what this underscore was for, but Clang did not like it.
  1. I learned that _() does localization, and changed this in revision 3 of the diff to NSLog(@"%@", _(@"WARNING: blah"));
    The reason Clang did not like the original was that it expects the format string to be constant.
./Services/Private/System/SCTask.m (Diff revision 1)
 
 
Does GCC perform some concatenation here that Clang does not?
Is it better to add the comma and keep the short lines, or join the strings into one?
  1. This was me being confused. The error was a missing argument for the formatted string. Fixed in revision 3 of the diff.
NSObject declares (NSUInteger) hash;
which is the same as unsigned int, not unsigned long.
  1. Changed to actually using NSUInteger in revision 3 of the diff.
Posted 5 months, 4 weeks ago (March 14th, 2010, 8:39 a.m.)

   

  
Posted 5 months, 4 weeks ago (March 14th, 2010, 8:44 a.m.)

   

  
Review request changed
Updated 5 months, 4 weeks ago (March 14th, 2010, 10:05 a.m.)
Review request changed
Updated 5 months, 4 weeks ago (March 14th, 2010, 12:14 p.m.)
Ship it!
Posted 5 months, 3 weeks ago (March 16th, 2010, 7:51 a.m.)
I quickly checked the changes by reading the diff and the comments. Everything looks ok to me. I just have to do a test compilation with Clang now.