PC-Lint complains about this code, but I don't know what's wrong withit (PC-Lint error #145)

D

David Sudolcan

I can't figure out why PC-Lint complains about the following code.
Can you help? I have the following code in a header file.

#ifndef _THIS_HEADER_FILE
#define _THIS_HEADER_FILE

typedef enum
{
RESULT_ERROR = -1,
RESULT_PASS = 0,
RESULT_BUSY = 1,
RESULT_FAIL = 2
}result_t;

#endif

And I have a different header file that has this in it.

#ifndef _THAT_HEADER_FILE
#define _THAT_HEADER_FILE

typedef struct
{
result_t (*function1)(void);
result_t (*function2)(int);
}interface_t;

#endif

And I have a source file that includes the above header files (first
'this', then 'that'), and PC-Lint complains about the lines in the 2nd
header file, as shown below.

typedef struct
{
result_t (*function1)(void); <-- message 145 = type expected before
operator, void assumed

result_t (*function2)(int); <-- message 145 = type expected before
operator, void assumed
}interface_t;


If I change the return type of function1 and function2 to int, the
problem goes away.

If I change the name of the typedef in the 1st header file, both GCC
and PC-Lint complain that they don't know what result_t is anymore.

If I move the result_t definition to the 2nd header file, the problem
goes away (but that breaks the design, because I need to include both
the result_t and the interface_t in several other source files.

GCC doesn't complain about the code, and it seems to work just fine.
I'm trying to make a structure that's an interface to something, where
the interface functions return a predefined type (things like busy,
pass, fail, error, etc.).

Is there something wrong with the way I'm trying to make this work?
Shouldn't PC-Lint know that that result_t is a valid type because the
1st header file is always included before the 2nd one is included?

I'm confused... help... please.
 
B

Ben Bacarisse

David Sudolcan said:
I can't figure out why PC-Lint complains about the following code.
Can you help? I have the following code in a header file.

#ifndef _THIS_HEADER_FILE
#define _THIS_HEADER_FILE

typedef enum
{
RESULT_ERROR = -1,
RESULT_PASS = 0,
RESULT_BUSY = 1,
RESULT_FAIL = 2
}result_t;

#endif

And I have a different header file that has this in it.

#ifndef _THAT_HEADER_FILE
#define _THAT_HEADER_FILE

typedef struct
{
result_t (*function1)(void);
result_t (*function2)(int);
}interface_t;

#endif

And I have a source file that includes the above header files (first
'this', then 'that'), and PC-Lint complains about the lines in the 2nd
header file, as shown below.

typedef struct
{
result_t (*function1)(void); <-- message 145 = type expected before
operator, void assumed

result_t (*function2)(int); <-- message 145 = type expected before
operator, void assumed
}interface_t;

I can't explain it but when I paste your code into PC-lint's online
demonstration there is no error. Maybe it's a old and buggy PC-lint?

<snip>
 
D

David Sudolcan

Thanks. I see that there's a patch for V9 of PC-Lint, which is what I
use. Maybe I should install it.

Coincidentally... after struggling with this [alleged] problem for
some time this afternoon and then restarting my PC (I had to take a
break), PC-Lint stopped complaining about that piece of code. Sigh.
I appreciate you taking the time to try that out on my behalf. I
didn't know you could paste snippets of code into the online version
of the tool. I'll have to check that out.

Thanks again.
 
R

Rich Webb

[snippety snip]
I can't explain it but when I paste your code into PC-lint's online
demonstration there is no error. Maybe it's a old and buggy PC-lint?

Just ran it on the snippets above, arranged in three files as per the
OP's description, and did not get the error messages. Changing one of
the result_t types to be result_x did throw:

result_x (*function2)(int);
theother.c 7 Error 145: Type expected before operator, void assumed
theother.c 7 Warning 601: No explicit type for symbol 'result_x', int
assumed
theother.c 7 Error 43: Vacuous type for variable 'result_x()'

So 145 isn't suppressed in any of the upstream lint configs. This is
with the current patch level (9.00f).

If the OP is using a reasonably current version, then my guess would be
that somewhere in a std.lnt or lint.lnt or ... something has been set
that causes this unexpected behavior.

An option would be to have that.h explicitly include this.h to pick up
the typedef. That's good practice anyway, rather than depending on the
ordering of the #include lines in the .c file.

I tend not to put #includes in .h files myself and depend (as here) on
the .c file to sequence the includes in the right order. That's probably
not A Good Thing To Do. Ought to get in the habit of making the header
files more stand-alone.
 
M

Morris Keesan

I can't figure out why PC-Lint complains about the following code.
Can you help? I have the following code in a header file.

#ifndef _THIS_HEADER_FILE
#define _THIS_HEADER_FILE

typedef enum
{
RESULT_ERROR = -1,
RESULT_PASS = 0,
RESULT_BUSY = 1,
RESULT_FAIL = 2
}result_t;

#endif

And I have a different header file that has this in it.

#ifndef _THAT_HEADER_FILE
#define _THAT_HEADER_FILE

typedef struct
{
result_t (*function1)(void);
result_t (*function2)(int);
}interface_t;

#endif

And I have a source file that includes the above header files (first
'this', then 'that'), and PC-Lint complains about the lines in the 2nd
header file, as shown below. ....

Is there something wrong with the way I'm trying to make this work?

I don't know PC-Lint, but in my opinion, there are two things wrong with
the way you're trying to make this work.

1: Instead of requiring other source files to always include this and that
in the correct order, you should simply have

#include "this.h"

at the beginning of "that.h". That way, you're guaranteed that result_t
is defined before you try to use it. And because you have the contents
of this.h protected with the #ifndef, there's no harm done if source.c
does #include this.h, whether it's before or after that.h

2: Get rid of the underscores at the beginning of THIS_HEADER_FILE and
THAT_HEADER_FILE. Identifiers beginning with an underscore followed by an
uppercase letter are reserved (see ISO C99 7.1.3, which also says that if
a program "defines a reserved identifier as a macro name, the behavior is
undefined." You're probably using these underscores because you've seen
other people do it, and/or because you or they have seen macros like this
in system header files. These macros in system (or compiler) header files
begin with underscores specifically because those names are reserved, and
the underscores keep those identifiers from conflicting with macros
defined in properly-written programs. By beginning your own macro names
with leading underscores, you're explicitly removing that protection from
your program.
 
D

David Sudolcan

Well I'll be... I checked 'The C Standard', and you are indeed
correct. Just goes to show that you can learn something new every
day. Thanks for pointing that out. And you're right about me seeing
that in other folks code. I'll have to share that at work, and change
the way we do our include file guards.

About including include files in include files, our coding standard
says not to do that. Nor sure why. But, I've seen it both ways. Is
there any drawbacks to including include files in include files?

Dave.
 
P

Peter Nilsson

David Sudolcan said:
Well I'll be... I checked 'The C Standard', and you are indeed
correct.

Who is correct? About what?! Please quote what you're replying to!
I assume it's:
 Just goes to show that you can learn something new every
day.

Beware that EXXX is also reserved in contexts, so ESOTERIC_H
can be problematic. I tend to use H_XXXX_H.

About including include files in include files, our coding
standard says not to do that.

Well, your karma just ran over your dogma. ;)
 Nor sure why.  But, I've seen it both ways.  Is there any
drawbacks to including include files in include files?

Since the mid 80's, none.
 
E

Eric Sosman

Well I'll be... I checked 'The C Standard', and you are indeed
correct. Just goes to show that you can learn something new every
day. Thanks for pointing that out. And you're right about me seeing
that in other folks code. I'll have to share that at work, and change
the way we do our include file guards.

About including include files in include files, our coding standard
says not to do that. Nor sure why. But, I've seen it both ways. Is
there any drawbacks to including include files in include files?

In the Days of Yore when machines had maybe 32-64KB of memory
and a hard upper limit of about 16 simultaneous open files, a rule
that said "No header may #include another" was useful. Such a rule
could make the difference between a file that compiled and a file
that broke the compiler.

Nowadays I cannot see that such a rule makes sense. In fact,
I think it makes anti-sense: Instead of telling the programmer
"You must #include foo.h to use the fooRoutines()," you have to
say "You must #include foo.h, and before that you must #include
bar.h and baz.h, and before baz.h you must #include gorp.h and
<string.h>, and ..." That is, the rule lightens the burden on
the computer (a little) and increases the burden on the programmer
(a lot). When computers were small and slow and CPU cycles were
scarce and expensive and programmer time was cheap, this shift of
responsibility was perhaps justifiable. Today, when we've got more
memory and more cycles than we know what to do with -- and when
engineering time is the single biggest cost in producing software! --
the antiquated rule is hard to defend.

(Data point: My current employer has exactly the opposite rule.
Every header is *required* to #include everything it needs. We are
officially encouraged to see to it that every header appears as the
very first #include in at least one compilation, to ensure that it
has omitted nothing essential. I do not claim that my employer does
everything right at all times, but the company has been fairly
successful by most measures, and the coding tactics followed by
successful companies are perhaps worthy of your consideration.)

But if your company is stuck in the 1970's, that's life. If you
can't change the rules, you must either obey them or find somewhere
else to work.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,534
Members
45,008
Latest member
Rahul737

Latest Threads

Top