mbl
mbl

Reputation: 925

Why is this output of the preprocessor seemingly not making sense?

Sorry for the bad title, hopefully my explanation is clearer.

I have the following c program:

clang_test.c

#include "clang_test2.c"
int main()
{
    somefunc();
    return 0;
}

clang_test2.c

int somefunc()
{
    return 5;
}

I then compile it using clang with the -E parameter in order to see the result of the preprocessor.

clang.exe -std=c99 -pedantic-errors -E .\clang_test.c

The preprocessor output is this:

# 1 ".\\clang_test.c"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 324 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 ".\\clang_test.c" 2

# 1 "./clang_test2.c" 1
int somefunc()
{
 return 5;
}
# 3 ".\\clang_test.c" 2

int main()
{
 somefunc();
 return 0;
}

This works as expected and I get no compilation error if I try to compile it regularly without -E.

For the sake of experimentation I modified clang_test.c to not #include clang_test2.c:

int main()
{
     somefunc();
     return 0;
}

I then tried to compile using:

clang.exe -std=c99 -pedantic-errors .\clang_test2.c .\clang_test.c

And I get a compiler error saying:

.\clang_test.c:13:2: error: implicit declaration of function 'somefunc' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
somefunc();

But if I look at the output of the preprocessor, it seems like it should work because somefunc() is still declared above the main function where it's used:

# 1 ".\\clang_test2.c"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 324 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 ".\\clang_test2.c" 2
int somefunc()
{
 return 5;
}
# 1 ".\\clang_test.c"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 324 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 ".\\clang_test.c" 2

int main()
{
 somefunc();
 return 0;
}

So based on this observation, is it not reliable to look at the output of the preprocessor in order to diagnose problems related to function definitions/declarations? And also since the only difference between the 2 preprocessor outputs is this block of text:

# 1 ".\\clang_test.c"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 324 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 ".\\clang_test.c" 2

What could it be doing to prevent somefunc() from being properly forward declared?

Upvotes: 0

Views: 84

Answers (1)

Gene
Gene

Reputation: 46990

The line

clang.exe -std=c99 -pedantic-errors .\clang_test2.c .\clang_test.c

does not just concatenate the two files and compile them. It compiles each of the C files separately to object (.o) files and then links them. You get the error because compiled alone,

int main()
{
    somefunc();
    return 0;
}

doesn't define somefunc. You'll need a prototype to tell the compiler its type:

int somefunc(void);

int main(void)
{
    somefunc();
    return 0;
}

Note that you should be using proper prototypes throughout. Functions with no arguments should be be declared with void argument lists. Old style function interfaces (e.g. with arg lists ()) allow many kinds of errors that prototypes allow the compiler to detect.

On the other hand the output of the compiler with -E

clang.exe -std=c99 -pedantic-errors -E .\clang_test2.c .\clang_test.c

does concatenate the two files and send them through the C preprocessor. The difference - compiling to object and liking vice concatenating - explains the behaviors you see.

Upvotes: 1

Related Questions