Menu

#429 Separate "tag" namespace (of ANSI C) is broken in CVS SWIG

None
closed-wont-fix
parsing (146)
5
2022-07-27
2004-04-27
No

Some recent change since the release of SWIG 1.3.21 has
broken the separate namespace in which union, struct,
enum tags live (in ANSI C, not in C++).

I have code that uses variables of the same name as some
union/struct/enum tag name. This used to work with
SWIG 1.3.21 and some later CVS versions, but now it is
broken. SWIG now warns that the variable is a
duplicate identifier and fails to wrap it.

This is my test case, which I have also put into the
test suite as
Examples/test-suite/tag_no_clash_with_variable.i:

------------------------------
/* This is a test case for -*- C -*- mode. */
%module tag_no_clash_with_variable

%inline %{

/* error_action is only a tag, not a type... */
enum error_action {
ERRACT_ABORT,
ERRACT_EXIT,
ERRACT_THROW
};

/* ... thus it does not clash with a variable of the
same name. */
enum error_action error_action;

/* Likewise for structs: */

struct buffalo {
int foo;
};

struct buffalo buffalo;

/* And for union */

union onion {
int cheese;
};

union onion onion;

%}
------------------------------

I think this is important to fix, because I have
frequently seen C code that depends on this separate
namespace. (Not only my own code.)

Discussion

  • Olly Betts

    Olly Betts - 2010-09-27

    This looks like parsing rather than codegen.

    I think r5847 may have introduced this issue, but I haven't checked behaviour before/after to verify this.

    This issue is still present in SVN trunk after 2.0.0 (r12229).

     
  • Olly Betts

    Olly Betts - 2010-09-27
    • labels: 505206 --> parsing
     
  • Olly Betts

    Olly Betts - 2017-10-08

    Actually, if r5847 revealled this, it seems it just uncovered a deliberate design decision - there's a comment in Source/Swig/symbol.c which describes this (and dates back to before version control started in 2002):

     * Structures and classes:
     *
     * C/C++ symbol tables are normally managed in a few different spaces.  The
     * most visible namespace is reserved for functions, variables, typedef, enum values
     * and such.  In C, a separate tag-space is reserved for 'struct name', 'class name',
     * and 'union name' declarations.   In SWIG, a single namespace is used for everything
     * this means that certain incompatibilities will arise with some C programs. For instance:
     *
     *        struct Foo {
     *             ...
     *        }
     *
     *        int Foo();       // Error. Name clash.  Works in C though 
     * 
     * Due to the unified namespace for structures, special handling is performed for
     * the following:
     *
     *        typedef struct Foo {
     *
     *        } Foo;
     * 
     * In this case, the symbol table contains an entry for the structure itself.  The
     * typedef is left out of the symbol table.
    

    This doesn't seem ideal (though it seems we aren't flooded with bug reports about it) and I feel it ought to get fixed, though we have a mountain of other bugs which ought to be too. If we're not going to fix it then it really ought to be documented in the user documentation.

     
  • Olly Betts

    Olly Betts - 2021-12-29

    Still present in git master 9e95f7f996c616a931253c0ab795f00feb499f0a (pre 4.1.0), tested with:

    $ cd Examples/test-suite/php
    $ make tag_no_clash_with_variable.ctest
    
     
  • Olly Betts

    Olly Betts - 2022-07-27
    • status: open --> closed-wont-fix
    • Group: -->
     
  • Olly Betts

    Olly Betts - 2022-07-27

    This doesn't seem ideal (though it seems we aren't flooded with bug reports about it) and I feel it ought to get fixed, though we have a mountain of other bugs which ought to be too. If we're not going to fix it then it really ought to be documented in the user documentation.

    It's now been more than 18 years since this was reported, without further reports and without anyone trying to fix it, so I think we should just document it in the manual and close this. I'll push 848cb3f95ec6f5f77f8ee28773d197d7035a8454 shortly.

    Related issues seem to affect C++ code to some extent. I didn't find documentation of the exact rules in C++ from a quick look, but for example:

    $ cat struct-tag.cxx 
    class Foo { int bar; };
    int Foo(void) { return 42; }
    Foo x;
    $ g++ -c -Wall -W struct-tag.cxx 
    struct-tag.cxx:3:1: error: ‘Foo’ does not name a type
        3 | Foo x;
          | ^~~
    $ cat struct-tag-ok.cxx
    class Foo { int bar; };
    Foo x;
    int Foo(void) { return 42; }
    $ g++ -c -Wall -W struct-tag-ok.cxx
    

    SWIG gets a name collision for both the above examples, and you get this for the function Foo:

    Warning 302: Identifier 'Foo' redefined (ignored),
    
     

Log in to post a comment.