Question about a splint diagnostic

Discussion in 'C Programming' started by spibou@gmail.com, Jul 30, 2006.

  1. Guest

    I have two identical files , u1.c and u2.c which only contain
    the line
    typedef int Q ;
    When I issue "splint u1.c u2.c" I get

    u2.c:1:13: Datatype Q defined more than once
    A function or variable is redefined. One of the declarations should
    use
    extern. (Use -redef to inhibit warning)
    u1.c:1:13: Previous definition of Q

    Finished checking --- 1 code warning

    Is this warning justified ? I thought that typedef's have file scope.

    Spiros Bousbouras
     
    , Jul 30, 2006
    #1
    1. Advertising

  2. jacob navia Guest

    a écrit :
    > I have two identical files , u1.c and u2.c which only contain
    > the line
    > typedef int Q ;
    > When I issue "splint u1.c u2.c" I get
    >
    > u2.c:1:13: Datatype Q defined more than once
    > A function or variable is redefined. One of the declarations should
    > use
    > extern. (Use -redef to inhibit warning)
    > u1.c:1:13: Previous definition of Q
    >
    > Finished checking --- 1 code warning
    >
    > Is this warning justified ? I thought that typedef's have file scope.
    >
    > Spiros Bousbouras
    >


    typedef's have compilation unit scope, OK. BUT
    splint flags this as an error very probably because
    TWO definitions of the same type are a disaster
    waiting to happen...

    It is very difficult to remember which is which
    if they are different, and it is a bad practice.

    This is of course my opinion only.

    jacob
     
    jacob navia, Jul 30, 2006
    #2
    1. Advertising

  3. Guest

    jacob navia wrote:

    > a écrit :
    > > I have two identical files , u1.c and u2.c which only contain
    > > the line
    > > typedef int Q ;
    > > When I issue "splint u1.c u2.c" I get
    > >
    > > u2.c:1:13: Datatype Q defined more than once
    > > A function or variable is redefined. One of the declarations should
    > > use
    > > extern. (Use -redef to inhibit warning)
    > > u1.c:1:13: Previous definition of Q
    > >
    > > Finished checking --- 1 code warning
    > >
    > > Is this warning justified ? I thought that typedef's have file scope.
    > >
    > > Spiros Bousbouras
    > >

    >
    > typedef's have compilation unit scope, OK. BUT
    > splint flags this as an error very probably because
    > TWO definitions of the same type are a disaster
    > waiting to happen...
    >
    > It is very difficult to remember which is which
    > if they are different, and it is a bad practice.


    How should I write it to avoid the warning ? Following splint's
    advice I tried
    typedef extern int Q ;
    in the file u2.c splint is ok with that but lint gives

    (1) error: only one storage class allowed
    lint: errors in u2.c; no output created
    lint: pass2 not run - errors in u2.c

    The motto "you can't please everyone" seems to be
    true for code checking utilities too !

    Let me explain how I first encountered the problem.
    I was writing a function in its own file ; let's call
    it foo.c The file included a typedef. Then I wrote
    a short testing programme , test.c The test programme
    needed of course the same datatype so I put an identical
    typedef inside test.c It compiles fine but as an extra
    precaution I also put it through splint and that's when
    I got the warning about the same datatype being defined
    more than once.

    This function will be part of my own library and I plan
    to use it with more than one programmes. The headers of
    standard library functions do not contain "extern" next
    to typedef and one does not get any warnings. I take it
    that this happens because one only links with the libraries
    rather than compiling them with one's own programme. But
    with my own libraries I tend to go for the simpler option
    and just write
    cc my-programme.c my-library.c
    rather than create a linkable object file from my-library.c
    Off the top of my head I don't even know how to do that.
    So if I compile with
    cc my-programme.c my-library.c
    I also want to write
    splint my-programme.c my-library.c
    and get as little warnings as possible. As far as I can see
    I have 2 options:
    1) Continue to write splint my-programme.c my-library.c
    and accept that I will get warnings when my-programme.c
    duplicates the typedef's from my-library.c
    2) Create linkable object files for my libraries and only
    link with those.

    Is there another option that I'm missing ?

    Spiros Bousbouras
     
    , Jul 30, 2006
    #3
  4. jacob navia Guest

    a écrit :
    > jacob navia wrote:
    >
    >
    >> a écrit :
    >>
    >>>I have two identical files , u1.c and u2.c which only contain
    >>>the line
    >>>typedef int Q ;
    >>>When I issue "splint u1.c u2.c" I get
    >>>
    >>>u2.c:1:13: Datatype Q defined more than once
    >>> A function or variable is redefined. One of the declarations should
    >>>use
    >>> extern. (Use -redef to inhibit warning)
    >>> u1.c:1:13: Previous definition of Q
    >>>
    >>>Finished checking --- 1 code warning
    >>>
    >>>Is this warning justified ? I thought that typedef's have file scope.
    >>>
    >>>Spiros Bousbouras
    >>>

    >>
    >>typedef's have compilation unit scope, OK. BUT
    >>splint flags this as an error very probably because
    >>TWO definitions of the same type are a disaster
    >>waiting to happen...
    >>
    >>It is very difficult to remember which is which
    >>if they are different, and it is a bad practice.

    >
    >
    > How should I write it to avoid the warning ? Following splint's
    > advice I tried
    > typedef extern int Q ;
    > in the file u2.c splint is ok with that but lint gives
    >
    > (1) error: only one storage class allowed
    > lint: errors in u2.c; no output created
    > lint: pass2 not run - errors in u2.c
    >
    > The motto "you can't please everyone" seems to be
    > true for code checking utilities too !
    >
    > Let me explain how I first encountered the problem.
    > I was writing a function in its own file ; let's call
    > it foo.c The file included a typedef. Then I wrote
    > a short testing programme , test.c The test programme
    > needed of course the same datatype so I put an identical
    > typedef inside test.c It compiles fine but as an extra
    > precaution I also put it through splint and that's when
    > I got the warning about the same datatype being defined
    > more than once.
    >
    > This function will be part of my own library and I plan
    > to use it with more than one programmes. The headers of
    > standard library functions do not contain "extern" next
    > to typedef and one does not get any warnings. I take it
    > that this happens because one only links with the libraries
    > rather than compiling them with one's own programme. But
    > with my own libraries I tend to go for the simpler option
    > and just write
    > cc my-programme.c my-library.c
    > rather than create a linkable object file from my-library.c
    > Off the top of my head I don't even know how to do that.
    > So if I compile with
    > cc my-programme.c my-library.c
    > I also want to write
    > splint my-programme.c my-library.c
    > and get as little warnings as possible. As far as I can see
    > I have 2 options:
    > 1) Continue to write splint my-programme.c my-library.c
    > and accept that I will get warnings when my-programme.c
    > duplicates the typedef's from my-library.c
    > 2) Create linkable object files for my libraries and only
    > link with those.
    >
    > Is there another option that I'm missing ?
    >
    > Spiros Bousbouras
    >


    Normally you put your typedefs in a common header file like
    u2.h

    Then, both files
    #include "u2.h"

    and you have the same effect, with only ONE definition.

    jacob
     
    jacob navia, Jul 30, 2006
    #4
  5. Guest

    jacob navia wrote:

    > Normally you put your typedefs in a common header file like
    > u2.h
    >
    > Then, both files
    > #include "u2.h"
    >
    > and you have the same effect, with only ONE definition.
    >
    > jacob


    But then the typedef will appear in both files and I will have
    two (identical) definitions. I'm using identical definitions
    now and I get the warning.
     
    , Jul 30, 2006
    #5
  6. Skarmander Guest

    wrote:
    > jacob navia wrote:
    >
    >> Normally you put your typedefs in a common header file like
    >> u2.h
    >>
    >> Then, both files
    >> #include "u2.h"
    >>
    >> and you have the same effect, with only ONE definition.
    >>
    >> jacob

    >
    > But then the typedef will appear in both files and I will have
    > two (identical) definitions. I'm using identical definitions
    > now and I get the warning.
    >

    Have you actually tried it? This is so common that splint ought to detect it
    and not warn about it. To the compiler, it's the same thing; to splint it
    may not be.

    S.
     
    Skarmander, Jul 30, 2006
    #6
  7. Guest

    Skarmander wrote:

    > wrote:
    > > jacob navia wrote:
    > >
    > >> Normally you put your typedefs in a common header file like
    > >> u2.h
    > >>
    > >> Then, both files
    > >> #include "u2.h"
    > >>
    > >> and you have the same effect, with only ONE definition.
    > >>
    > >> jacob

    > >
    > > But then the typedef will appear in both files and I will have
    > > two (identical) definitions. I'm using identical definitions
    > > now and I get the warning.
    > >

    > Have you actually tried it? This is so common that splint ought to detect it
    > and not warn about it. To the compiler, it's the same thing; to splint it
    > may not be.


    It works ! Thanks.
     
    , Jul 30, 2006
    #7
  8. Chris Torek Guest

    In article <>
    <> wrote:
    >I have two identical files , u1.c and u2.c which only contain
    >the line
    >typedef int Q ;
    >When I issue "splint u1.c u2.c" I get
    >
    >u2.c:1:13: Datatype Q defined more than once
    > A function or variable is redefined. One of the declarations should use
    > extern. (Use -redef to inhibit warning)
    > u1.c:1:13: Previous definition of Q
    >
    >Finished checking --- 1 code warning
    >
    >Is this warning justified ? I thought that typedef's have file scope.


    A "typedef" has the same scope as any ordinary declaration: if
    it appears inside a function, for instance, it has block scope.
    A typedef at file scope thus has file scope (as you noted).

    It seems likely that splint is complaining because the typedef is
    in different *source files*, rather than different translation
    units. That is, splint is tracing the "typedef" line to a specific
    file, and if multiple compilation units get the same typename from
    *separate* files, it gripes. This is presumably to prevent you
    from doing something like this:

    % cat foo.h
    Temperature measure(void);
    % cat foo.c
    typedef int Temperature;
    #include "foo.h"
    Temperature measure(void) { return 42; }
    % cat main.c
    typedef double Temperature;
    #include "foo.h"
    int main(void) {
    printf("it's %f degrees\n", measure());
    return 0;
    }

    These code fragments will most likely compile, yet when run, will
    produce nonsense: main.c believes that measure() returns a double,
    while foo.c's measure() actually returns an "int". The header
    foo.h is shared between foo.c and main.c, but refers to a typedef
    that is defined *differently* in the two .c files. If the typedef
    line were also in the .h file, it would be impossible to get it
    wrong in one of the .c files.

    As for the "explanation" below the warning, it is just wrong. The
    "extern" keyword is a storage-class-specifier, as is the typedef
    keyword (even though the latter is an s-c-specifier purely for
    syntactic reasons), and only one s-c-specifier keyword is allowed
    in any declaration. (Probably splint has just one command line
    option -- "-redef" -- that affects both ordinary, non-"typedef"
    identifiers -- where you *can* use extern -- and "typedef" identifiers,
    where you cannot.)
    --
    In-Real-Life: Chris Torek, Wind River Systems
    Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
    email: forget about it http://web.torek.net/torek/index.html
    Reading email is like searching for food in the garbage, thanks to spammers.
     
    Chris Torek, Jul 30, 2006
    #8
  9. writes:
    > I have two identical files , u1.c and u2.c which only contain
    > the line
    > typedef int Q ;
    > When I issue "splint u1.c u2.c" I get
    >
    > u2.c:1:13: Datatype Q defined more than once
    > A function or variable is redefined. One of the declarations should
    > use
    > extern. (Use -redef to inhibit warning)
    > u1.c:1:13: Previous definition of Q
    >
    > Finished checking --- 1 code warning
    >
    > Is this warning justified ? I thought that typedef's have file scope.


    Having typedefs with the same name in two different *.c files is ok.

    Typically you would invoke the compiler separately for each *.c file.
    For example, you might do something like:

    gcc -c u1.c
    gcc -c u2.c
    gcc u1.o u2.o -o main_program

    but the manner in which you invoke the compiler to compile multiple
    source files is implementation-specific. I see that "gcc u1.c u2.c"
    does work, but that doesn't guarantee that "splint u1.c u2.c" will
    mean the same thing.

    The documentation for splint would likely be instructive.

    As a matter of program design, having the same typedef (assuming it's
    intended to be the same) in two separate source files is a bad idea,
    even if it's legal. Put it in a header file included by both .c
    files, with include guards so the compiler sees the typedef only once
    per translation unit.

    <OT>
    For a large project, you should probably use some system that figures
    out how to invoke the compiler for you, such as a Makefile or an IDE.
    This would probably invoke the compiler once for each .c file; you
    should probably invokes splint the same way, possibly under control of
    your Makefile.
    </OT>

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Jul 30, 2006
    #9
  10. Guest

    Keith Thompson wrote:

    > The documentation for splint would likely be instructive.
    >
    > As a matter of program design, having the same typedef (assuming it's
    > intended to be the same) in two separate source files is a bad idea,
    > even if it's legal. Put it in a header file included by both .c
    > files, with include guards so the compiler sees the typedef only once
    > per translation unit.
    >
    > <OT>
    > For a large project, you should probably use some system that figures
    > out how to invoke the compiler for you, such as a Makefile or an IDE.
    > This would probably invoke the compiler once for each .c file; you
    > should probably invokes splint the same way, possibly under control of
    > your Makefile.
    > </OT>


    out_of_topic {
    I just did a quick experiment with splint. I used it
    on a source file without main and it didn't produce
    any sort of "object" file so I think that in order to
    detect various discrepancies between different source
    files it needs to be invoked with all the files together.

    I do need to read the manual eventually.
    }

    By the way why is advice on how to handle large projects in C
    out of topic ?

    Spiros Bousbouras
     
    , Jul 30, 2006
    #10
  11. said:

    <snip>
    >
    > By the way why is advice on how to handle large projects in C
    > out of topic ?


    The C part of it isn't, but the C part is not difficult, and does not lend
    itself to particularly involved discussions. In fact, it can be described
    in about three words - "do it properly". :)

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at above domain (but drop the www, obviously)
     
    Richard Heathfield, Jul 30, 2006
    #11
  12. writes:
    > Keith Thompson wrote:
    >> The documentation for splint would likely be instructive.
    >>
    >> As a matter of program design, having the same typedef (assuming it's
    >> intended to be the same) in two separate source files is a bad idea,
    >> even if it's legal. Put it in a header file included by both .c
    >> files, with include guards so the compiler sees the typedef only once
    >> per translation unit.
    >>
    >> <OT>
    >> For a large project, you should probably use some system that figures
    >> out how to invoke the compiler for you, such as a Makefile or an IDE.
    >> This would probably invoke the compiler once for each .c file; you
    >> should probably invokes splint the same way, possibly under control of
    >> your Makefile.
    >> </OT>

    >
    > out_of_topic {
    > I just did a quick experiment with splint. I used it
    > on a source file without main and it didn't produce
    > any sort of "object" file so I think that in order to
    > detect various discrepancies between different source
    > files it needs to be invoked with all the files together.


    Of course it didn't produce an object file. It's a static source code
    checker; that's not its job. If by "object" file you meant something
    that splint can use to do checking across translation units, that's a
    good point; if splint doesn't do that, either it can't do cross-unit
    checks or it uses some other method to do them. You'll undoubtedly
    find that information in the splint manual.

    Quite possibly it's going to warn about things that are perfectly
    legal. In your original example, you had the same typedef in two
    different translation units. This is quite legal, but it could be a
    maintenance headache; if you change it, you'll have to make sure it
    remains consistent across all the multiple definitions. Perhaps this
    is what splint is warning you about. As we've mentioned, writing the
    typedef exactly once in a header is a much better approach.

    > I do need to read the manual eventually.


    Yep.

    > }
    >
    > By the way why is advice on how to handle large projects in C
    > out of topic ?


    Because the C standard doesn't provide a way to do it. Even how a
    compiler is invoked is outside the scope of the language; different
    compilers are invoked in different ways. Makefiles, for example, are
    one way to manage large projects -- and there are a number of tools
    built on top of that, tools that generate Makefiles from some even
    higher-level description. All these tools are system-specific.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Jul 30, 2006
    #12
  13. On Sun, 30 Jul 2006 20:34:12 UTC, wrote:

    >
    > out_of_topic {
    > I just did a quick experiment with splint. I used it
    > on a source file without main and it didn't produce
    > any sort of "object" file so I think that in order to
    > detect various discrepancies between different source
    > files it needs to be invoked with all the files together.


    It is NOT the job of splint to produce object files. Its job is "only"
    to check the source for errors and complain against them.

    > I do need to read the manual eventually.
    > }



    > By the way why is advice on how to handle large projects in C
    > out of topic ?


    There is no standard defined
    - how to invoke a compiler
    - how to invoke a linker
    - how to invoke another tools (like make)
    - how to get multiple source files bounded to an executeable

    As this group is only to handle C in a compatible way you has to ask
    in a group relevant to your OS, your specific compiler, your specific
    linker, your specific tool you use to come from different sources to a
    single executeable. The ways to get it are so incomatible and
    different that there is simple no common possibility.

    The standard describes exactly how to write C in an compatible way
    each and any compiler has to translate fine - but how to get from the
    output a compiler produces when it has to compile multiple translation
    units to get them bouned to a single executeable are at least system
    specific or a bit harder specific to a specific compiler.

    --
    Tschau/Bye
    Herbert

    Visit http://www.ecomstation.de the home of german eComStation
    eComStation 1.2 Deutsch ist da!
     
    Herbert Rosenau, Jul 31, 2006
    #13
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Greg Roberts

    Using splint on C files under MS VC6

    Greg Roberts, Jan 23, 2004, in forum: C Programming
    Replies:
    0
    Views:
    485
    Greg Roberts
    Jan 23, 2004
  2. Guy Eschemann

    "Implicitly only" splint warnings

    Guy Eschemann, Jan 12, 2005, in forum: C Programming
    Replies:
    2
    Views:
    1,462
    Guy Eschemann
    Jan 13, 2005
  3. Henry Fr?d?ric

    Ignore include header files with Splint

    Henry Fr?d?ric, Mar 23, 2005, in forum: C Programming
    Replies:
    8
    Views:
    1,258
    Tor Rustad
    Mar 29, 2005
  4. Replies:
    1
    Views:
    1,056
    Clever Monkey
    Jul 7, 2006
  5. Peter Bencsik
    Replies:
    2
    Views:
    881
Loading...

Share This Page