This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

ARM Compiler complains about incompatible type during linking

Genius 5820 points

I'm compiling from within CCS using TI's ARM compiler version v5.1.8 with optimisation level 4 (whole program optimisation) and --opt_for_speed 5.

This worked well for a longer time and until I added some new source files. Now I get a linker error (failed linktime optimisation) complaining about some incompatible redefinitions. The funny thing: the linker error message gives me the original definition and the redefinition - and both are completely identical! That looks like this for a lot of definitions:

error: symbol "ufb_empty" redeclared with incompatible type:
   "unsigned char(struct ufb_data *)"
   in "../buffer.c" at line 12 and:
   "unsigned char(struct ufb_data *)"
   in "../buffer.h" at line 53)
error: symbol "ufb_push" redeclared with incompatible type:
   "unsigned char(struct ufb_data *, struct uframe *)"
   in "../buffer.c" at line 18 and:
   "unsigned char(struct ufb_data *, struct uframe *)"
   in "../buffer.h" at line 54)
error: symbol "uFrameBuffer" redeclared with incompatible type:
   "struct ufb_data 
   head            off:  0  (uint_fast32_t)
   tail            off: 32  (uint_fast32_t)
   buffer          off: 64  (struct uframe *)
   size            off: 96  (uint_fast32_t)"
   in "../buffer.c" at line 8 and:
   "struct ufb_data 
   head            off:  0  (uint_fast32_t)
   tail            off: 32  (uint_fast32_t)
   buffer          off: 64  (struct uframe *)
   size            off: 96  (uint_fast32_t)"
   in "../buffer.h" at line 61)
error: symbol "tcp_setprio" redeclared with incompatible type:
   "void(struct tcp_pcb *, u8_t)"
   in
   "/home/universe/AM335X_StarterWare_02_00_01_01/third_party/lwip-1.4.0/src/co
   re/tcp.c" at line 1066 and:
   "void(struct tcp_pcb *, u8_t)"
   in "../../../../../../../third_party/lwip-1.4.0/src/include/lwip/tcp.h" at
   line 362)

So...anybody an idea what could cause these wrong error messages and how to solve this problem?

Thanks!

  • Please try the latest version available on the 5.2.x branch.

    It is very likely that "struct uframe" is declared as an incomplete type in either buffer.h or tcp.h, or a header file included by one of those files. The linker algorithm to merge types can get confused when dealing with incomplete types. This bug tends to manifest only with large projects with nested structs. Try making sure that there is a complete definition of "struct uframe" in scope for each of those two files.
  • OK, great :-) Where can I download the 5.x ARM compiler?
  • Found the new compiler via "install new software" in CCS :-)

  • OK, v5.2.0 does NOT solve the problem.

    I checked the linker output, it does not complain about single structures but about a huge bunch of very different structures and functions defined within different files. Within my code nowhere a forward declaration (which may cause such an incomplete type?) is used. So...any other ideas?
  • There could be an actual mismatch in the declared type of a struct member. You have to use exactly the same type everywhere the declaration of the struct is seen. If that's not the problem, I may need to see a test case.

    Is any part of this program C++ code?
  • No .cpp files involved. I try to strip the project down until it works and then re-add my changes step by step to find out what the reason ist. I'll let you know as soon as I found something!
  • In test cases I've debugged which had this sort of problem, no one file was the problem. It was a collection of files which together formed an unfortunate chain of type references which confused the -o4 optimization type checker. You can potentially find a workaround where a few files can be removed from -o4 optimization, but it likely won't bring you much closer to knowing which declaration is the troublesome one.
  • Meanwhile I could strip down the problem: It was caused by an include file (or better parts of an include file) that was added newly. The funny thing: none of the structures or types the linker complained about have been defined or used in this header.

    Now that I have disabled parts of this header with a conditional switch it works smoothly :-)

  • I suspect I'm banging my head on the wall with this bug as well. Took me two days to strip down the scenario to a minimum configuration that I'm able to trigger the condition with. I have to say the chain to trigger this doesn't make any sense, but in the bigger project such a chain was formed anyway...

    Attached you can find my bare-minimum CCS project that compiled with opt=4, opt-for-speed=5 will cause:

    <Linking>
    error: symbol "func1" redeclared with incompatible type:
       "void(funcptr_t)"
       in "..\func1.h" at line 13 and:
       "void(funcptr_t)"
       in "../func1.c" at line 11)
    
    >> Compilation failure
    
    >> Compilation failure
    fatal error #10192: Failed linktime optimization

    Compiler version used: TI-ARM v5.2.5

    Posahdus.zip

    Can you reproduce it, confirm it is a compiler bug, and if so, any information on a possible fix?

    Thanks,

    Veikko

  • Thank you for the test case.  I can reproduce the same results.  I filed SDSCM00052257 in the SDOWP system to have this investigated.  Feel free to follow it with the SDOWP link below in my signature.  I can tell you this is not a new problem.  I cannot say anything about a possible fix.

    Thanks and regards,

    -George

  • Yes, this is a compiler bug.  The type checking is getting confused by the anonymous union member in struct2_t.  Give the union a name (see following), and the error will go away.  I'm still analyzing the issue.

    typedef struct {

           union {

                   uint32_t A;

                   uint32_t B;

           } a_fake_name;

    } struct2_t;

  • Thank you, this was it. I got the code of the bigger project to compile by either giving names to the offensive unions or removing the union altogether (where the purpose was just to provide a naming alias). I hope you find the root cause, though - having the aliases makes more sense from a code-readability viewpoint.