1

When I run my C code with gcc (with -Wall -Werror flags) in terminal, it didn't give me any errors. However, when I run my code in Xcode, it gives me the above error on only two functions. What is going on?

main.c

#include "canvas.h"
#include "paint.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

void program_loop(Canvas * canvas) {
    // ...
}

int main(int argc, char ** argv) {
    // ...
    return 0;
}

canvas.h

#ifndef CANVAS_H
#define CANVAS_H

typedef struct {
    // ...
} Canvas;

void create_canvas(Canvas * canvas, int row_num, int col_num);
void print_canvas(Canvas * canvas);
void write(Canvas * canvas); // "Previous overload of function is here."
void write_horizontal(Canvas * canvas, int row, int start_column, int end_column);
void write_vertical(Canvas * canvas, int start_row, int end_row, int column);
void write_right_diagonal(Canvas * canvas, int start_row, int end_row, int start_column, int end_column);
void write_left_diagonal(Canvas * canvas, int start_row, int end_row, int start_column, int end_column);
void erase(Canvas * canvas); // "Previous overload of function is here."
void resize(Canvas * canvas);
void add(Canvas * canvas);
void del(Canvas * canvas);
void clear_canvas(Canvas * canvas);

#endif

canvas.c

#include "canvas.h"
#include <stdio.h>
#include <stdlib.h>

void create_canvas(Canvas * canvas, int row_num, int col_num) {
    // ...
}

void print_canvas(Canvas * canvas) {
    // ...
}

void write(Canvas * canvas) { // Error here.
    // ...
}

void write_horizontal(Canvas * canvas, int row, int start_column, int end_column) {
    // ...
}

void write_vertical(Canvas * canvas, int start_row, int end_row, int column) {
    // ...
}

void write_right_diagonal(Canvas * canvas, int start_row, int end_row, int start_column, int end_column) {
    // ...
}

void write_left_diagonal(Canvas * canvas, int start_row, int end_row, int start_column, int end_column) {
    // ...
}

void erase(Canvas * canvas) { // Error here.
    // ...
}

void resize(Canvas * canvas) {
    // ...
}

void add(Canvas * canvas) {
    // ...
}

void del(Canvas * canvas) {
    // ...
}

void clear_canvas(Canvas * canvas) {
    // ...
}

paint.h

#ifndef PAINT_H
#define PAINT_H

#include "canvas.h"

// ...

#endif

paint.c

#include "paint.h"
#include <stdio.h>
#include <stdlib.h>

// ...

The errors are happening at the void write(Canvas * canvas) and void erase(Canvas * canvas) functions. Any help would be greatly appreciated!

astrocat1997
  • 187
  • 3
  • 14
  • 1
    From the code comments you must have considered that `write` and `erase` or other functions may already have a definition? I don't see why you are getting "overload" errors from a C compiler. – Weather Vane Dec 20 '16 at 19:03

2 Answers2

2

First, note that write (and likely erase) are already defined in some system headers. Specifically, in unistd.h, there is:

ssize_t write(int __fd, const void * __buf, size_t __nbyte)

In this question, we find that overloading does not work out of the box in C. So, here you have two different functions named write with different types, which plain C doesn't support.

Now, we have the peculiar case that it works when you compile via clang at command line:

clang -c canvas.c

you don't get the error, but via Xcode you do. Well, in Xcode you can view the actual compilation command which Xcode executes, which for me looks like:

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang
-x c -arch x86_64 -fmessage-length=0
-fdiagnostics-show-note-include-stack -fmacro-backtrace-limit=0
-std=gnu99 -fmodules -gmodules
-fmodules-cache-path=/Users/donaldpinckney/Library/Developer/Xcode/DerivedData/ModuleCache
-fmodules-prune-interval=86400 -fmodules-prune-after=345600
-fbuild-session-file=/Users/donaldpinckney/Library/Developer/Xcode/DerivedData/ModuleCache/Session.modulevalidation
-fmodules-validate-once-per-build-session
-Wnon-modular-include-in-framework-module
-Werror=non-modular-include-in-framework-module -Wno-trigraphs
-fpascal-strings -O0 -fno-common -Wno-missing-field-initializers
-Wno-missing-prototypes -Werror=return-type -Wdocumentation
-Wunreachable-code -Werror=deprecated-objc-isa-usage
-Werror=objc-root-class -Wno-missing-braces -Wparentheses -Wswitch
-Wunused-function -Wno-unused-label -Wno-unused-parameter
-Wunused-variable -Wunused-value -Wempty-body
-Wconditional-uninitialized -Wno-unknown-pragmas -Wno-shadow
-Wno-four-char-constants -Wno-conversion -Wconstant-conversion
-Wint-conversion -Wbool-conversion -Wenum-conversion
-Wshorten-64-to-32 -Wpointer-sign -Wno-newline-eof -DDEBUG=1 -isysroot
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk
-fasm-blocks -fstrict-aliasing -Wdeprecated-declarations
-mmacosx-version-min=10.12 -g -Wno-sign-conversion
-Winfinite-recursion -iquote
/Users/donaldpinckney/Library/Developer/Xcode/DerivedData/paint-fovqgkhrrknzbxemgzpydqtwbtge/Build/Intermediates/paint.build/Debug/paint.build/paint-generated-files.hmap
-I/Users/donaldpinckney/Library/Developer/Xcode/DerivedData/paint-fovqgkhrrknzbxemgzpydqtwbtge/Build/Intermediates/paint.build/Debug/paint.build/paint-own-target-headers.hmap
-I/Users/donaldpinckney/Library/Developer/Xcode/DerivedData/paint-fovqgkhrrknzbxemgzpydqtwbtge/Build/Intermediates/paint.build/Debug/paint.build/paint-all-target-headers.hmap
-iquote
/Users/donaldpinckney/Library/Developer/Xcode/DerivedData/paint-fovqgkhrrknzbxemgzpydqtwbtge/Build/Intermediates/paint.build/Debug/paint.build/paint-project-headers.hmap
-I/Users/donaldpinckney/Library/Developer/Xcode/DerivedData/paint-fovqgkhrrknzbxemgzpydqtwbtge/Build/Products/Debug/include
-I/Users/donaldpinckney/Library/Developer/Xcode/DerivedData/paint-fovqgkhrrknzbxemgzpydqtwbtge/Build/Intermediates/paint.build/Debug/paint.build/DerivedSources/x86_64
-I/Users/donaldpinckney/Library/Developer/Xcode/DerivedData/paint-fovqgkhrrknzbxemgzpydqtwbtge/Build/Intermediates/paint.build/Debug/paint.build/DerivedSources
-F/Users/donaldpinckney/Library/Developer/Xcode/DerivedData/paint-fovqgkhrrknzbxemgzpydqtwbtge/Build/Products/Debug
-MMD -MT dependencies -MF
/Users/donaldpinckney/Library/Developer/Xcode/DerivedData/paint-fovqgkhrrknzbxemgzpydqtwbtge/Build/Intermediates/paint.build/Debug/paint.build/Objects-normal/x86_64/canvas.d
--serialize-diagnostics
/Users/donaldpinckney/Library/Developer/Xcode/DerivedData/paint-fovqgkhrrknzbxemgzpydqtwbtge/Build/Intermediates/paint.build/Debug/paint.build/Objects-normal/x86_64/canvas.dia
-c /Users/donaldpinckney/Stack/paint/canvas.c -o
/Users/donaldpinckney/Library/Developer/Xcode/DerivedData/paint-fovqgkhrrknzbxemgzpydqtwbtge/Build/Intermediates/paint.build/Debug/paint.build/Objects-normal/x86_64/canvas.o

This tells us that while Xcode uses Clang, it also uses Clang with a ton more options than just -Wall -Werror. The important flag for this case is -fmodules, which enables the Clang language feature of modules. This will change how Xcode includes system libraries. I don't know why this in particular causes the error, but it does. You can test this by running:

clang -fmodules -c canvas.c

And you will get the same errors.

To fix it, you can do one of 2 things:

  1. Rename those functions to something else.
  2. Use the Clang overloadable attribute, which would look like:

canvas.h:

// ...
void __attribute__((overloadable)) write(Canvas * canvas);
// ...

canvas.c:

// ...
void __attribute__((overloadable)) write(Canvas * canvas) {
  // ...
}
// ..
Community
  • 1
  • 1
0

In addition to the solutions in Donald Pinckney's answer, you can tell Xcode to turn off -fmodules by turning off "Enable Modules (C and Objective-C)" in the project build settings (the setting can be found by searching for "fmodules").

Community
  • 1
  • 1
Kyle
  • 307
  • 2
  • 9