3

I'm trying to compile Objective-C code on Ubuntu 12 Linux.

main.m looks like this:

#import <Foundation/Foundation.h>
#import "CEFoo/CEFoo.h"

int main (int argc, const char * argv[])
 {
  NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
  NSLog (@"hello world");
  [pool drain];
  return 0;
 }

In CEFoo.h, I have the definition:

struct StructName{  // line 86
 BOOL first; 
 ...
 ...
};

@interface StructName :NSObject  // line 92
BOOL first; // line 93
...
...
@end  // 96

When I go to compile with

gcc main.m  `gnustep-config --objc-flags` -lgnustep-base -o main.bin

I get this message:

Foo/CEFoo.h:93:1: error: redefinition of ‘struct StructName’
Foo/CEFoo.h:86:8: note: originally defined here

I've read this can be caused by either redefining the struct twice, or by recursive import when using include instead of import.

grep -r "struct StructName" *

Only shows one occurrence of the definition.

I've also searched every include statement in the project, and have found no apparent uses of include vs import, or otherwise dual include/imports of CEFoo.h (the file which contains the structure which is being defined / imported more than once).

How can I further hunt down the cause of this? I assume that I am importing it twice -- if I am, is there a way to watch it via verbose or logs defined for the first time?

Any other ideas what I can do to troubleshoot this?

TIA

Geremy
  • 2,415
  • 1
  • 23
  • 27

2 Answers2

3

Defining a class means creating a struct for it, among other things. And you happen to have a struct named exactly like your class. For example, check the following code "live" at http://ideone.com/7kvFa

#import <objc/objc.h>

struct name {};

@interface name
@end

int
main() {
    return 0;
}
sidyll
  • 57,726
  • 14
  • 108
  • 151
1

That's because of the way GCC handles Objective-C objects. GCC (in version 4.2.1 ; I don't know for more recent versions) treats objects as pointers to opaque structures.

When you declare a class named StructName, GCC implicitly does the following:

struct StructName;
typedef struct StructName StructName;

You can see that behavior when you try to initialize a NSArray object pointer with a NSString object pointer:

NSArray *array = @"Hello world";

GCC emits the following warning:

warning: incompatible Objective-C types initializing ‘struct NSString *’, expected ‘struct NSArray *’

So, even if you declared struct StructName only once, GCC sees two declarations and fails to compile the file for that reason.

I suggest you rename your structure or use another compiler (e.g. LLVM).

Nicolas Bachschmidt
  • 6,475
  • 2
  • 26
  • 36
  • So it should be legal to have a struct and an object with the same name, and this is just a gcc-specific behavior I'm seeing? – Geremy Jul 11 '12 at 19:08
  • 1
    There is no formal written standard for Objective-C but as far as I know, nothing in the C standard nor in GNUStep or Apple Objective-C documentations prohibit the use of `struct StructName` and `StructName` as two distinct types. So I think, GCC should allow this. – Nicolas Bachschmidt Jul 11 '12 at 19:29