1

I have a iOS framework that contains .c, .mm source files. For convenience let's call these two files A.c and B.mm.

In both files, I defined a function with the same function protocol like the following.

// A.c

uint32_t get_file(const char *path)
{
    ...
}

// B.mm

uint32_t get_file(const char *path)
{
    ...
}

As far as I know, I thought this would throw an error at compile time because there's duplicate symbol, but it successfully compiles the framework without any error. What am I missing here?

Note: This will be a duplicate symbol linker error if it was .c and .m because Objective-C doesn't undergo name mangling.

slow
  • 805
  • 3
  • 13
  • 27
  • 1
    Just for the fun of nit-picking. Duplicate symbols in two different compile units would be a linker error, not compile error. – HAL9000 Feb 05 '19 at 09:38

1 Answers1

5

Objective-C++ files (.mm) are C++ files, so they undergo name mangling. If you run nm on the output, you'll see something along the lines of:

$ nm a.out | grep get_file
0000000100000fa0 T __Z8get_filePKc
0000000100000f70 T _get_file

If you applied extern "C" in the C++ version to remove name mangling, you'd see the collision you're expecting:

// B.mm
extern "C" uint32_t get_file(const char *path)
{
    return 0;
}


$ clang A.c B.mm
duplicate symbol _get_file in:
    /var/folders/j3/32xftcp56c12hqz7y8rl4f600000gn/T/A-d00e10.o
    /var/folders/j3/32xftcp56c12hqz7y8rl4f600000gn/T/B-d853af.o
ld: 1 duplicate symbol for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Rob Napier
  • 286,113
  • 34
  • 456
  • 610