Bug 4195

Summary: Problem with generated code when using typedefs from different modules
Product: TAO Reporter: Daniel Garrido <dgarrido>
Component: IDL CompilerAssignee: DOC Center Support List (internal) <tao-support>
Status: NEW ---    
Severity: normal    
Priority: P3    
Version: 2.3.0   
Hardware: x86   
OS: Linux   
Attachments: IDL files where the problem happens.
Proposed patch for strings and arrays

Description Daniel Garrido 2014-12-09 04:15:16 CST
Created attachment 1513 [details]
IDL files where the problem happens.

Consider the following interfaces:

Module1.idl:

module Module1
{
  typedef string<1024> MyString;
};


Module2.idl:

#include <Module1.idl>

module Module2
{
  typedef Module1::MyString MyString2;

  interface Srv {
    void op(in MyString2 par);
  };
};

Module1 defines MyString which is used in Module2 with a new typedef 
(MyString2).

The code produced by tao_idl cannot be compiled. You can obtain something 
like (please note that some parts of the compiler output are in spanish):

Module2S.cpp: In member function ‘virtual void 
POA_Module2::op_Srv::execute()’:
Module2S.cpp:179: error: ‘MyString2_1024’ no es un miembro de ‘TAO’
Module2S.cpp:179: error: ‘MyString2_1024’ no es un miembro de ‘TAO’
Module2S.cpp:179: error: el argumento de plantilla 1 es inválido
Module2S.cpp:179: error: expected initializer before ‘arg_1’
Module2S.cpp:186: error: ‘arg_1’ no se declaró en este ámbito
Module2S.cpp: In static member function ‘static void 
POA_Module2::Srv::op_skel(TAO_ServerRequest&, 
TAO::Portable_Server::Servant_Upcall*, TAO_ServantBase*)’:
Module2S.cpp:210: error: ‘MyString2_1024’ no es un miembro de ‘TAO’
Module2S.cpp:210: error: ‘MyString2_1024’ no es un miembro de ‘TAO’
Module2S.cpp:210: error: el argumento de plantilla 1 es inválido
Module2S.cpp:210: error: expected initializer before ‘_tao_par’
Module2S.cpp:215: error: ‘_tao_par’ no se declaró en este ámbito
/home/dgarrido/ACE_wrappers/TAO/tao/PortableServer/PortableServer.h: At 
global scope:
/home/dgarrido/ACE_wrappers/TAO/tao/PortableServer/PortableServer.h:36: 
aviso: se define ‘TAO_Requires_POA_Initializer’ pero no se usa
make[1]: *** [.obj/Module2S.o] Error 1
make: *** [nombreunix_server] Error 2

Some definitions are missing: MyString2_1024 is not declared in any file.

However, if you include all the definitions in the same .idl file, it 
compiles:

module Module1
{
  typedef string<1024> MyString;
};

module Module2
{
  typedef Module1::MyString MyString2;

  interface Srv {
    void op(in MyString2 par);
  };
};

This problem also happens with other datatypes (arrays, sequences,structs, ...). For instance, if you use 
arrays instead of strings:

Module1.idl:

module Module1
{
  typedef short MyString[3];
};

Module2.idl:

#include <Module1.idl>

module Module2
{
  typedef Module1::MyString MyString2;

  interface Srv {
    void op(in MyString2 par);
  };
};

This time you get a linking error:

.obj/Module2S.o: In function 
`TAO::In_Fixed_Array_SArgument_T<TAO_Array_Forany_T<short [3], short, 
Module1::MyString_tag>, 
TAO::Any_Insert_Policy_Noop>::demarshal(TAO_InputCDR&)':
Module2S.cpp:(.text._ZN3TAO26In_Fixed_Array_SArgument_TI18TAO_Array_Forany_TIA3_ssN7Module112MyString_tagEENS_22Any_Insert_Policy_NoopEE9demarshalER12TAO_InputCDR[TAO::In_Fixed_Array_SArgument_T<TAO_Array_Forany_T<short 
[3], short, Module1::MyString_tag>, 
TAO::Any_Insert_Policy_Noop>::demarshal(TAO_InputCDR&)]+0x1b): undefined 
reference to `operator>>(TAO_InputCDR&, TAO_Array_Forany_T<short [3], short, 
Module1::MyString_tag>&)'
.obj/Module2C.o: In function `Module2::MyString2_free(short*)':
Module2C.cpp:(.text+0x291): undefined reference to 
`Module1::MyString_free(short*)'
.obj/Module2C.o: In function `Module2::MyString2_copy(short*, short 
const*)':
Module2C.cpp:(.text+0x2a1): undefined reference to 
`Module1::MyString_copy(short*, short const*)'
.obj/Module2C.o: In function `Module2::MyString2_dup(short const*)':
Module2C.cpp:(.text+0x2b1): undefined reference to 
`Module1::MyString_dup(short const*)'
.obj/Module2C.o: In function `Module2::MyString2_alloc()':
Module2C.cpp:(.text+0x2c1): undefined reference to 
`Module1::MyString_alloc()'
.obj/Module2C.o: In function 
`TAO::In_Fixed_Array_Argument_T<TAO_Array_Forany_T<short [3], short, 
Module1::MyString_tag>, 
TAO::Any_Insert_Policy_Noop>::marshal(TAO_OutputCDR&)':
Module2C.cpp:(.text._ZN3TAO25In_Fixed_Array_Argument_TI18TAO_Array_Forany_TIA3_ssN7Module112MyString_tagEENS_22Any_Insert_Policy_NoopEE7marshalER13TAO_OutputCDR[TAO::In_Fixed_Array_Argument_T<TAO_Array_Forany_T<short 
[3], short, Module1::MyString_tag>, 
TAO::Any_Insert_Policy_Noop>::marshal(TAO_OutputCDR&)]+0xb): undefined 
reference to `operator<<(TAO_OutputCDR&, TAO_Array_Forany_T<short [3], 
short, Module1::MyString_tag> const&)'
collect2: ld devolvió el estado de salida 1
make[1]: *** [server] Error 1
make: *** [nombreunix_server] Error 2



    SAMPLE FIX/WORKAROUND:
[If available ]

The problem seems related to "imported" definitions. If you examine 
be_visitor_arg_traits.cpp you will find the following code:

int
be_visitor_arg_traits::visit_string (be_string *node)
{
  if (node->imported ())
    {
      // Arg traits will presumably already be generated, but
      // perhaps from another compilation unit. We mark it
      // generated because if we get here from a typedef in
      // the main file, we should skip it.
      this->generated (node, true);
      return 0;
    }


If we comment the "if" sentence it seems to work.

This solution does not resolve the problem when using arrays. In addition, 
this "code pattern" (if (node->imported())...return 0, appears in many parts 
of TAO and we think this problem can appear again when using other data types.

Best regards,
Daniel.
Comment 1 Daniel Garrido 2014-12-09 04:20:26 CST
Created attachment 1514 [details]
Proposed patch for strings and arrays

These files provide a patch for two different cases:
- Strings
- Arrays.