Bool reported as undefined. When typedef added; error that Bool is already defined - c

I'm writing embedded software for the ti C5515 in ccstudio, using the CSL libraries. I'm having trouble with type definitions. In specific, I get this error:
#20 identifier "Bool" is undefined in csl_intc.h
Taking a look at the header, I find the bool definition in tistdtypes.h; within scope, as far as I can tell. In desperation, I add a typedef to the top of the file. However, then it complains that bool is already defined.
I've made sure that the case is the same, and that there isn't another tistdtypes.h somewhere overriding the definition. How is it possible that it complains that there is no typedef, but when I add one, it says that there is one already?
Here are the two errors, one after the other:
#20 identifier "Bool" is undefined TMS320C5515 line 992, external location: ... csl_intc.h
#102 "Bool" has already been declared in the current scope TMS320C5515 line 914, external location: ... csl_intc.h
The file path is exactly the same. I can also paste the lines between 992 and 914 if necessary. There isn't much.

There is a #ifndef STD_ around the definition. Do you know what defines are passed by your compiler/other includes ?
One way to find out it to turn up the verbosity of the preprocessor to see all the code which is parsed. Maybe that will give you some insight why that is being skipped.
With gcc that would be gcc -E to stop after preprocessing and dump the parsed content. You might want to find the option for your compiler if you use a different one.

When I use the file in question:
#include "tistdtypes.h"
int main(){
Bool something = 0;
and run this program via gcc -Werror -Wall, I'm not seeing any such errors. So unless your version is different from the one I linked to, I'd say there's something wrong with how it's being compiled into your program.
Could you add some more details regarding how it's included, if your version of tistdtypes.h is different than when I linked to, and how the target is being compiled?
As a "worst case" backup at least you know that a Bool is really a unsigned short, so you could always modify your code to just not use the typedef.
EDIT:
I just took a look at csl_intc.h. It uses Bool in that file without including the definition of it. What happens if you include tistdtypes.h in this file?

Related

clang error: unsupported: anonymous type given name for linkage purposes by typedef declaration after its linkage was computed

Someone knows what does this error mean?
My piece of code is shown below:
// test.c
inline void fun() {
typedef struct {
int i;
} S;
}
GCC could compile without an error while clang (clang 12.0.0) claims an error:
root:~/test # clang -c test.c
test.c:2:19: error: unsupported: anonymous type given name for linkage purposes by typedef declaration after its linkage was computed; add a tag name here to establish linkage prior to definition
typedef struct {
^
S
test.c:4:7: note: type is given name 'S' for linkage purposes by this typedef declaration
} S;
^
1 error generated.
According to the error text from clang, it looks like I need to add a tag name for the anonymous typedef. After adding a tag name, it won’t show an error. However, this piece of code from a team work program in my department so I need a strong reason to modify it. Someone knows what’s this error mean?
UPDATE: In the comments below someone mentioned, The code could compile but fail to link with GCC. Actually that because the GCC optimization is not turned on. Use -O2 to compile and link will pass.
I mentioned this in a comment, but I think I might be able to expand it to a proper answer. The problem here is in how the inline keyword works in C. Quite frankly, I don't know what the C standards committee was smoking when they came up with this ridiculous concept, and it's probably best not to know. Don't ask why the rules are this way: I don't know.
There is an important difference between extern inline and static inline functions, as well as ones declared simply inline.
inline functions may be defined in a header and included in multiple compilation units. This is because they aren't considered "real" definitions. No symbol for them is emitted, thus there is no multiple-definition error. However, the compiler is not required to actually inline the function call. It may instead try to call it. Since no symbol exists, there will be an error at link time. Never use inline functions in C. They make no sense at all.
extern inline functions provide the definition for an inline function. If the above case happens, and the compiler tries to call the function, so long as some file includes an extern inline definition, there won't be an error because it emits a symbol. This making sense? No? Good.
static inline functions are the only one that make any sense whatsoever. Because they're static and therefore local, no symbol need exist. If the compiler decides to inline it, it does. If not, it calls the function. No problems. Declare your function static inline and it will compile.
But that wasn't your question. Why is clang complaining about the struct? Why doesn't gcc complain? The answer is "idunnoman". Best guess is that clang is taking the rules very seriously, in which case because there is no "real" definition for fun, there is also no real definition for your anonymous struct, and therefore can't be typedef'd.
But that would also be the case if it were a named struct. And why does the linker care whether the structure has a name? Once again, I can only guess it has to do with the fact that there can be numerous definitions for an inline function, and clang wants the structure to have a constant name between them. But different compilation units can have different structures with the same name, so that doesn't make sense either.
Ugh. I thought I had an answer for you but now I'm even more confused than when I started. I'll still post this but it probably ought to be downvoted. Oh well.

is the purpose of header files in C only warning to users?

I'm a beginner into Linking, sorry if my questions are too basic. lets say I have two .c files
file1.c is
int main(int argc, char *argv[])
{
int a = function2();
return 0;
}
file2.c is
int function2()
{
return 2018;
}
I know the norm is, create a file2.h and include it in file1.c, and I have some questions:
Q1. #include in file1.c doesn't make too much difference or improve much to me, I can still compile file1.c without file2.h correctly, the compiler will just warn me 'implicit declaration of function 'function2', but does this warning help a lot? Programmers might know that function2 is defined in other .c file(if you use function2 but don't define it, you certainly know the definition is somewhere else) and linker will do its job to produce the final executable file? so the only purpose of include file2,c to me is, don't show any warning during compilation, is my understanding correct.
Q2. Image this scenario, a programmer define function2 in file1.c, he doesn't know that his function2 in conflict with the one in file2.c until the linker throws the error(obvious he can compile his file1.c alone correctly. But if we want him to know his mistake when he compiles his file1.c, adding file2.h still don't help, so what's the purpose of adding header file?
Q3. What should we add to let the programmer know he should choose a different name for function2 rather then be informed the error by linker in the final stage.
Per C89 3.3.2.2 Function calls emphasis mine:
If the expression that precedes the parenthesized argument list in a function call consists solely of an identifier, and if no declaration is visible for this identifier, the identifier is implicitly declared exactly as if, in the innermost block containing the function call, the declaration
extern int identifier();
appeared
Now, remember, empty parameter list (declared with nothing inside the () braces) declares a function that takes unspecified type and number of arguments. Type void inside braces to declare that a function takes no arguments, like int func(void).
Q1:
does this warning help a lot?
Yes and no. This is a subjective question. It helps those, who use it. As a personal note, always make this warning an error. Using gcc compiler use -Werror=implicit-function-declaration. But you can also ignore this warning and make the simplest main() { printf("hello world!\n"); } program.
linker will do its job to produce the final executable file? so the only purpose of include file2,c to me is, don't show any warning during compilation, is my understanding correct.
No. In cases the function is called using different/not-compatible pointer type. It invokes undefined behavior. If the function is declared as void (*function2(void))(int a); then calling ((int(*)())function2)() is UB as is calling function2() without previous declaration. Per Annex J.2 (informative):
The behavior is undefined in the following circumstances:
A pointer is used to call a function whose type is not compatible with the pointed-to type (6.3.2.3).
and per C11 6.3.2.3p8:
A pointer to a function of one type may be converted to a pointer to a function of another type and back again; the result shall compare equal to the original pointer. If a converted pointer is used to call a function whose type is not compatible with the referenced type, the behavior is undefined.
So in your lucky case int function2() indeed this works. It also works for example for atoi() function. But calling atol() will invoke undefined behavior.
Q2:
the linker throws the error
This should happen, but is really linker dependent. If you compile all sources using a single stage with the gcc compiler it will throw an error. But if you create static libraries and then link them using gcc compiler without -Wl,-whole-archive then it will pick the first declaration is sees, see this thread.
what's the purpose of adding header file?
I guess simplicity and order. It is a convenient and standard way to share data structures (enum, struct, typedefs) and declarations (function and variable types) between developers and libraries. Also to share preprocessor directives. Image you are writing a big library with over 1000+ files that will work with over 100+ other libraries. In the beginning of each file would you write struct mydata_s { int member1; int member2; ... }; int printf(const char*, ...); int scanf(const char *, ...); etc. or just #include "mydata.h" and #include <stdio.h>? If you would need to change mydata_s structure, you would need to change all files in your project and all the other developers which use your library would need to change the definition too. I don't say you can't do it, but it would be more work to do it and no one will use your library.
Q3:
What should we add to let the programmer know he should choose a different name for function2 rather then be informed the error by linker in the final stage.
In case of name clashes you will by informed (hopefully) by the linker that it found two identifiers with the same name. You would need to create a tool to check your sources exactly for that. I don't know why the need for this, the linker is specifically made to resolve symbols so it naturally handles the cases when two symbols with the same identifier exists.
Short answer:
Take away: the earlier the compiler alert the better.
Q1: meaning of .h: consistency and early alerts. Alerting early on common ways of going wrong improves reliability of code and adds up to less debugging and production crashes.
Q2: Clashing Names bring early alerts to developers, which are usually easier to fix.
Q3: Early duplicate definition alerts are not baked into the C standard.
Exercises:
1. Define a function in one file that printf("%d\n",i) an int argument then call that function in another file with a float of 42.0.
2. Call with (double)42.0.
3. Define function with char *str argument printed under %.s then call with int argument.
Longer answers:
Popular convention: in typical use the name of the .h file is derived from the .c file, or files, it is associated with. file.h and file.c. For .h files with many definitions, say string.h, derive the file name from a hither perspective of what's within (as in the str... functions).
My big rule: it’s always better to structure your code so compilers can immediately alert on bugs at compile time rather than letting them slide through to debug or run time where they depend on code actually running in just the right way to find. Run time errors can be very difficult to diagnose, especially if they hit long after the program is in production, and expensive in maintenance and brings down your customer experience. See "yoda notation".
Q1: meaning of .h: consistency and early alerts and improved reliability of code.
C .h files allow developers of .c files compiled at different times to share common declarations. No duplicate code. .h files also allow functions to be consistently called from all files while identifying improper argument signatures (argument counts, bad clashes, etc.). Having.c files defining functions also #include the .h file helps assure the arguments in the definition are consistent with the calls; this may sound elementary, but without it all the human errors of signature clashes can sneak through.
Omitting .h files only works if the argument signatures of all callers perfectly match those in the definitions. This is often not the case so without .h files any clashing signatures would produce bad numbers unless you also had parallel externs in the calling file (bad bad bad). Things like int vs float can produce spectacularly wrong argument values. Bad pointers can produce segment faults and other total crashes.
Advantage: with externs in .h files compilers can correctly cast mismatching arguments to the correct type, assuring better calls. While you can still botch arguments it’s much less likely. It also helps avoid conditions where the mismatches work on one implementation but not another.
Implicit declaration warnings are hugely helpful to me as they usually indicate I’ve forgotten a .h file or spelled the name an external name wrong.
Q2: Clashing Names. Early alerts.
Clashing names are bad and it is the developers responsibility to avoid problems. C++ solves the issue with name spaces, which C, being a lower level language, does not have.
Use of .h files can allow can let compiler diagnostics alert developers where clashes care are early in the game. If compiler diagnostics don’t do this hopefully linkers will do so on multidefined symbol errors, but this is not guaranteed by the standard.
A common way to fake name spaces is by starting all potentially clashing definitions in a .h with some prefix (extern int filex_function1(int arg, char *string) or #define FILEX_DEF 42).
What to do if two different external libraries being used share the same names is beyond the scope of this answer.
Q3: early duplicate alerts. Sorry… early alerts are implementation dependent.
This would be difficult for the C standard to define. As C is an old language there are many creative different ways C programs are written and stored.
Hunting for clashing names before using them is up to the developer. Tools like cross reference programs can help. Even something stupid like ctags associated with vim or emacs can help.
you misunderstand usage of header files and function prototypes.
header files are needed to share common information between multiple code files. such information includes macro definition, data types, and, possibly, function prototypes.
function protoypes are needed for the compiler to correctly handle return data types and to give you early warnings of misuse of function return types and arguments.
function prototypes can be declared in header files or can be declared in the files which use them (more typing).
you have a very simple example, with just 2 files. Now imagine a project with hudreds of files and thousands of functions. You will be lost in linker errors.
'c' allows you to use an undeclared function due to legacy reasons. In this situation it assumes that the function has a return type of 'int'. However, modern data types has a bigger veriety than in early days. The function can return pointers, 64-bit data, structures. To express that you must use prototypes or nothing will work. The compiler has to know how to handle function returns correctly.
Also, it can give you warnings about incorrect use of argument types. Due to leagacy, those are still warnings, but they got addressed in early c++ and converted to errors.
Those warnings give you early debugging capabilities. Type mismatch warnings can save you days of debugging in some cases.
So, in your example you do not need the header file. You can prototype the function in the 'main' file using the 'extern' syntax. You can even do without prototyping. However, in real modern programming world you cannot allow the latter. In particular when you work in a team or want your program to be maintainable.
It is a good idea to store you funcion protypes in header files. This would be a good documentation source, in particular with good comments. BTW, function names must make sense to be maintainable.
Q1. Yes. C is a low level language, and was historically used to bind low level constructs into higher level concepts. For example, traditionally the label _end is at the last address in a program. The label is typeless but you can declare it as any type that is convenient to you. A "properly typed" language would make this sort of abuse difficult.
Q2. By convention, both file1.c and file2.c would include file2.h; one as consumer, the other as producer. Following this simple idiom will catch declaration vs definition errors; although again, the "warning" is not necessarily enforced.
Q3. Many software organizations take a "warnings are errors" rule to socially control their programmers.

Eclipse editor not showing error on functions and enum values not included

I use Eclipse CDT for a C project. I only use the editor as the build environment is outside of Eclipse.
Error markers in the code are shwon as expected with a few exceptions:
When I make a function call it does not matter if the function exists or not. The editor will never show an error marker on the function call. I would expect an "Unresolved symbol" error, or similar.
I would expect misspelled function names to show up as error, and I would expect existing functions that are declared in header files that I forgot to include to show up as errors. But this is not the case.
When I enter the name of an enum member that does exist somewhere else (in a header file) in the project, then the editor recognizes it even if I do not include the header file where it is included. This will of course lead to a compiler error, but I would expect an error marker in the editor.
Is there some setting I am missing? Or is this just the way the eclipse editor works?
I have a faint memory of seeing those error markers long time ago, but memory may play tricks on me...
Resolving names whose definitions are in the project but not reachable through includes, is a known issue. It's tracked by bug 297690, and it's close to being fixed (with most of the hard work being done in bug 402498).
Resolving the name of a function which is not in the project at all, can happen in two situations.
In C code
The C language does not require that functions be declared prior to their use. A use without a preceding declaration is treated as an implicit declaration.
That is, the following C file is valid code:
void func() {
another_func(); // another_func is implicitly declared here
}
The linker will try to find a matching function definition at link time, and give an error if it cannot.
So, if you misspell another_func, the error will not be caught at compilation time (only at linking time), and similarly CDT cannot diagnose it.
In C++ template code
Unlike C, C++ does require that functions be declared prior to their use. However, there is one subtlety involving templates.
If a function call occurs inside a template and some of the arguments are dependent:
template <typename T>
void foo(T t) {
misspelt_function(t);
}
CDT can't diagnose the misspelt function at the point of foo's definition because of the way C++'s two-phase name lookup rules work: it would be valid to provide a definition of misspelt_function after the point of foo's definition (but before the point of instantiation) that's found by argument-dependent lookup (by being in a namespace associated with the type of t for this particular instantiation).
(CDT could in theory diagnose the misspelt function for particular instantiations of foo, the way a compiler does, but it currently doesn't type-check the bodies of instantiations at all.)

Function prototype in header file doesn't match definition, how to catch this?

(I found this question which is similar but not a duplicate:
How to check validity of header file in C programming language )
I have a function implementation, and a non-matching prototype (same name, different types) which is in a header file. The header file is included by a C file that uses the function, but is not included in the file that defines the function.
Here is a minimal test case :
header.h:
void foo(int bar);
File1.c:
#include "header.h"
int main (int argc, char * argv[])
{
int x = 1;
foo(x);
return 0;
}
File 2.c:
#include <stdio.h>
typedef struct {
int x;
int y;
} t_struct;
void foo (t_struct *p_bar)
{
printf("%x %x\n", p_bar->x, p_bar->y);
}
I can compile this with VS 2010 with no errors or warnings, but unsurprisingly it segfaults when I run it.
The compiler is fine with it (this I understand)
The linker did not catch it (this I was slightly surprised by)
The static analysis tool (Coverity) did not catch it (this I was very surprised by).
How can I catch these kinds of errors?
[Edit: I realise if I #include "header.h" in file2.c as well, the compiler will complain. But I have an enormous code base and it is not always possible or appropriate to guarantee that all headers where a function is prototyped are included in the implementation files.]
Have the same header file included in both file1.c and file2.c. This will pretty much prevent a conflicting prototype.
Otherwise, such a mistake cannot be detected by the compiler because the source code of the function is not visible to the compiler when it compiles file1.c. Rather, it can only trust the signature that has been given.
At least theoretically, the linker could be able to detect such a mismatch if additional metadata is stored in the object files, but I am not aware if this is practically possible.
-Werror-implicit-function-declaration, -Wmissing-prototypes or equivalent on one of your supported compilers. then it will either error or complain if the declaration does not precede the definition of a global.
Compiling the programs in some form of strict C99 mode should also generate these messages. GCC, ICC, and Clang all support this feature (not sure about MS's C compiler and its current status, as VS 2005 or 2008 was the latest I've used for C).
You may use the Frama-C static analysis platform available at http://frama-c.com.
On your examples you would get:
$ frama-c 1.c 2.c
[kernel] preprocessing with "gcc -C -E -I. 1.c"
[kernel] preprocessing with "gcc -C -E -I. 2.c"
[kernel] user error: Incompatible declaration for foo:
different type constructors: int vs. t_struct *
First declaration was at header.h:1
Current declaration is at 2.c:8
[kernel] Frama-C aborted: invalid user input.
Hope this helps!
Looks like this is not possible with C compiler because of its way how function names are mapped into symbolic object names (directly, without considering actual signature).
But this is possible with C++ because it uses name mangling that depends on function signature. So in C++ void foo(int) and void foo(t_struct*) will have different names on linkage stage and linker will raise error about it.
Of course, that will not be easy to switch a huge C codebase to C++ in turn. But you can use some relatively simple workaround - e.g. add single .cpp file into your project and include all C files into it (actually generate it with some script).
Taking your example and VS2010 I added TestCpp.cpp to project:
#include "stdafx.h"
namespace xxx
{
#include "File1.c"
#include "File2.c"
}
Result is linker error LNK2019:
TestCpp.obj : error LNK2019: unresolved external symbol "void __cdecl xxx::foo(int)" (?foo#xxx##YAXH#Z) referenced in function "int __cdecl xxx::main(int,char * * const)" (?main#xxx##YAHHQAPAD#Z)
W:\TestProjects\GenericTest\Debug\GenericTest.exe : fatal error LNK1120: 1 unresolved externals
Of course, this will not be so easy for huge codebase, there can be other problems leading to compilation errors that cannot be fixed without changing codebase. You can partially mitigate it by protecting .cpp file contents with conditional #ifdef and use only for periodical checks rather than for regular builds.
Every (non-static) function defined in every foo.c file should have a prototype in the corresponding foo.h file, and foo.c should have #include "foo.h". (main is the only exception.) foo.h should not contain prototypes for any functions not defined in foo.c.
Every function should prototyped exactly once.
You can have .h files with no corresponding .c files if they don't contain any prototypes. The only .c file without a corresponding .h file should be the one containing main.
You already know this, and your problem is that you have a huge code base where this rule has not been followed.
So how do you get from here to there? Here's how I'd probably do it.
Step 1 (requires a single pass over your code base):
For each file foo.c, create a file foo.h if it doesn't already exist. Add "#include "foo.h" near the top of foo.c. If you have a convention for where .h and .c files should live (either in the same directory or in parallel include and src directories, follow it; if not, try to introduce such a convention).
For each function in foo.c, copy its prototype to foo.h if it's not already there. Use copy-and-paste to ensure that everything stays consistent. (Parameter names are optional in prototypes and mandatory in definitions; I suggest keeping the names in both places.)
Do a full build and fix any problems that show up.
This won't catch all your problems. You could still have multiple prototypes for some functions. But you'll have caught any cases where two headers have inconsistent prototypes for the same function and both headers are included in the same translation unit.
Once everything builds cleanly, you should have a system that's at least as correct as what you started with.
Step 2:
For each file foo.h, delete any prototypes for functions that aren't defined in foo.c.
Do a full build and fix any problems that show up. If bar.c calls a function that's defined in foo.c, then bar.c needs a #include "foo.h".
For both of these steps, the "fix any problems that show up" phase is likely to be long and tedious.
If you can't afford to do all this at once, you can probably do a lot of it incrementally. Start with one or a few .c files, clean up their .h files, and remove any extra prototypes declared elsewhere.
Any time you find a case where a call uses an incorrect prototype, try to figure out the circumstances in which that call is executed, and how it causes your application to misbehave. Create a bug report and add a test to your regression test suite (you have one, right?). You can demonstrate to management that the test now passes because of all the work you've done; you really weren't just messing around.
Automated tools that can parse C are likely to be useful. Ira Baxter has some suggestions. ctags may also be useful. Depending on how your code is formatted, you can probably throw together some tools that don't require a full C parser. For example, you might use grep, sed, or perl to extract a list of function definitions from a foo.c file, then manually edit the list to remove false positives.
Its obvious ("I have a huge code base") you cannot do this by hand.
What you need is an automated tool that can read your source files as the compiler sees them, collect all function prototypes and definitions, and verify that all definitions/prototypes match. I doubt you'll find such a tool lying around.
Of course, this match much check the signature, and this requires something like the compiler's front end to compare the signatures.
Consider
typedef int T;
void foo(T x);
in one compilation unit, and
typedef float T;
void foo(T x);
in another. You can't just compare the signature "lines" for equality; you need something that can resolve the types when checking.
GCCXML may be able to help, if you are using a GCC dialect of C; it extracts top-level declarations from source files as XML chunks. I don't know if it will resolve typedefs, though. You obviously have to build (considerable) support to collect the definitions in a central place (a database) and compare them. Comparing XML documents for equivalents is at least reasonably straightforward, and pretty easy if they are formatted in a regular way. This is likely your easiest bet.
If that doesn't work, you need something that has a full C front end that you can customize. GCC is famously available, and famously hard to customize. Clang is available, and might be pressed into service for this, but AFAIK only works with GCC dialects.
Our DMS Software Reengineering Toolkit has C front ends (with full preprocessing capability) for many dialects of C (GCC, MS, GreenHills, ...) and builds symbol tables with complete type information. Using DMS you might be able (depending on the real scale of your application) to simply process all the compilation units, and build just the symbol tables for each compilation unit. Checking that symbol table entries "match" (are compatible according to compiler rules including using equivalent typedefs) is built-into the C front ends; all one needs to do is orchestrate the reading, and calling the match logic for all symbol table entries at global scope across the various compilation units.
Whether you do this with GCC/Clang/DMS, it is a fair amount of work to cobble together a custom tool. So you have decide how critical you need for fewer suprises is, compared to the energy to build such a custom tool.

How to track down cause of missing struct from include files in C?

I have a rather large project I'm porting, and in one of the MANY headers I've included a file that contains a struct definition for pmc_mdep. (prior in the file its just declared, but later its actually defined).
Trying to compile it gives me errors about that struct being an incomplete type (which I believe means that it's lacking a definition).
When I run the preprocessor over this project, it does include that file, but the preprocessor output does not have the struct definition (but does include enum's from that file).
Is there a method to figure out why some of a header file gets to the preprocessor output, and some does not?
TIA
(Also, this is not the only compile error, the port is half done but it should be at least getting past this part)
I usually just track back from the structure to find all the enclosing "#ifdef" and "#if" lines that the preprocessor will encounter and see which one is controlling the removal of the structure from the input stream into the compiler.
That generally works pretty quickly for all but the hairiest of header files (i.e., those with a great many nested conditional compile statements). For those, I generally have a look at the preprocessor output to identify the last line in the header file that made it to the compiler input stream.
Almost certainly the next line will be a conditional compile statement where you haven't met the condition for inclusion.
For example, if this is the header file, you would need to track back to see that _KERNEL should be defined in order to get the declaration and definition.
I'm afraid not; you will have to look for #ifdefs that surround your area of interest and track down why those symbols are not defined. If it's porting to Linux/UNIX and you are missing things from the standard headers, you might have not defined the right _XOPEN_SOURCE or _BSD_SOURCE in your Makefile or config.h .
The most likely reason is there's a #define somewhere around the definition. Since the corresponding symbol is not defined or defined to some other value the definition is not included even when the header itself is included. You'll have to inspect this manually.
Raymond Chen has a blog post about this.
You may find yourself in a twisty maze of #ifdefs. Or you may be wondering why your macros aren't working.
I have these lines in my header file:
#define MM_BUSY 0x0001
#define MM_IDLE 0x0002
but when I try to use them, I get errors.
sample.cpp(23): error C2065: 'MM_BUSY': undeclared identifier
sample.cpp(40): error C2065: 'MM_IDLE': undeclared identifier
Any idea why this is happening?
Solution: Use #error to track down the problem the same way you'd scatter printf around to track down a regular bug.
Source: Use the #error directive to check whether the compiler even sees you
I do not think that there is a better way beside checking the preprocessor output to know why one file is included or not. Here is the gcc's preprocessor's output format that may help you understand the preprocessor's ouput.
Also, another way you may have a try to compare the outputs between that you are porting and the existing one.
You said:
I have a rather large project I'm porting, and in one of the MANY headers I've included a file that contains a struct definition for pmc_mdep. (Prior in the file its just declared, but later its actually defined).
Trying to compile it gives me errors about that struct being an incomplete type (which I believe means that it's lacking a definition).
This error can occur if you try to embed a pmc_mdep into some other structure before you have defined a pmc_mdep fully. Note that you can embed pointers to incomplete types into structures, but not actual instances of the incomplete type.
You also discuss running the preprocessor over the file that should define the structure, and you see enums form the header, but not the structure definition. That suggests that maybe you have a stray comment that is removing the structure unintentionally, or perhaps you have the structure definition embedded between #ifdef XXX and #endif but XXX is not defined when you do the compilation. It could even be #if 0.
I'd run the C preprocessor on just the header that contains the structure definition to see what that produces; it will be shorter than trying to look at the output for the entire program (source file). If I couldn't spot the issue swiftly, I'd mark parts with something like stray enums to see which ones get through and which ones don't.

Resources