TRIQS / cpp2py

Reflection tools based on clang
Apache License 2.0
22 stars 14 forks source link

Wrap instantiation of template class #13

Open Wentzell opened 6 years ago

Wentzell commented 6 years ago

I tried to wrap to following minimal example to test the wrapping of an instantiated template class

/// Template
template <typename T> class toto {
  public:
  T i;
};

/// Instantiate
template class toto<double>;

/// Normal
class totoro {
  public:
  double i;
};

As expected both classes appear in the desc file. However, for the toto class the members are not wrapped at all.

# The class toto                                                                                                                                                                                                                                                                          
c = class_(                                                                                                                                                                                                                                                                               
        py_type = "Toto",  # name of the python class                                                                                                                                                                                                                                     
        c_type = "toto<double>",   # name of the C++ class                                                                                                                                                                                                                                
        doc = """Instantiate""",   # doc of the C++ class                                                                                                                                                                                                                                 
        hdf5 = False,                                                                                                                                                                                                                                                                     
)                                                                                                                                                                                                                                                                                         

module.add_class(c)                                                                                                                                                                                                                                                                       

# The class totoro                                                                                                                                                                                                                                                                        
c = class_(                                                                                                                                                                                                                                                                               
        py_type = "Totoro",  # name of the python class                                                                                                                                                                                                                                   
        c_type = "totoro",   # name of the C++ class                                                                                                                                                                                                                                      
        doc = """Normal""",   # doc of the C++ class                                                                                                                                                                                                                                      
        hdf5 = False,                                                                                                                                                                                                                                                                     
)                                                                                                                                                                                                                                                                                         

c.add_member(c_name = "i",                                                                                                                                                                                                                                                                
             c_type = "double",                                                                                                                                                                                                                                                           
             read_only= False,                                                                                                                                                                                                                                                            
             doc = """""")                                                                                                                                                                                                                                                                

module.add_class(c)    

I had a brief look at the AST I got from the clang.cindex by iterating recursively over the children of all the nodes and found

   CursorKind.TRANSLATION_UNIT
     CursorKind.CLASS_TEMPLATE
           CursorKind.TEMPLATE_TYPE_PARAMETER
           CursorKind.CXX_ACCESS_SPEC_DECL
           CursorKind.FIELD_DECL
                             CursorKind.TYPE_REF
     CursorKind.CLASS_DECL        # Instantiation of template class toto
     CursorKind.CLASS_DECL        # Non-template class totoro
           CursorKind.CXX_ACCESS_SPEC_DECL
           CursorKind.FIELD_DECL

i.e. the instantiation has no children in the cindex AST. I suppose this is the reason why no members are added by cpp2py?

The strange thing is that the AST using clang -cc1 -ast-dump looks different and does indeed specify all the information necessary

TranslationUnitDecl 0x55c3efbda0e0 <<invalid sloc>> <invalid sloc>
|-TypedefDecl 0x55c3efbda670 <<invalid sloc>> <invalid sloc> implicit __int128_t '__int128'
| `-BuiltinType 0x55c3efbda350 '__int128'
|-TypedefDecl 0x55c3efbda6e0 <<invalid sloc>> <invalid sloc> implicit __uint128_t 'unsigned __int128'
| `-BuiltinType 0x55c3efbda370 'unsigned __int128'
|-TypedefDecl 0x55c3efbdaa28 <<invalid sloc>> <invalid sloc> implicit __NSConstantString 'struct __NSConstantString_tag'
| `-RecordType 0x55c3efbda7d0 'struct __NSConstantString_tag'
|   `-CXXRecord 0x55c3efbda738 '__NSConstantString_tag'
|-TypedefDecl 0x55c3efbdaac0 <<invalid sloc>> <invalid sloc> implicit __builtin_ms_va_list 'char *'
| `-PointerType 0x55c3efbdaa80 'char *'
|   `-BuiltinType 0x55c3efbda170 'char'
|-TypedefDecl 0x55c3efc0fdf0 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list 'struct __va_list_tag [1]'
| `-ConstantArrayType 0x55c3efbdada0 'struct __va_list_tag [1]' 1 
|   `-RecordType 0x55c3efbdabb0 'struct __va_list_tag'
|     `-CXXRecord 0x55c3efbdab18 '__va_list_tag'
|-ClassTemplateDecl 0x55c3efc0ffc8 <test.cpp:2:1, line:5:1> line:2:29 toto
| |-TemplateTypeParmDecl 0x55c3efc0fe78 <col:11, col:20> col:20 referenced typename depth 0 index 0 T
| |-CXXRecordDecl 0x55c3efc0ff30 <col:23, line:5:1> line:2:29 class toto definition
| | |-FullComment 0x55c3efc10a50 <line:1:4, col:12>
| | | `-ParagraphComment 0x55c3efc10a20 <col:4, col:12>
| | |   `-TextComment 0x55c3efc109f0 <col:4, col:12> Text=" Template"
| | |-CXXRecordDecl 0x55c3efc10240 <line:2:23, col:29> col:29 implicit class toto
| | |-AccessSpecDecl 0x55c3efc102d8 <line:3:3, col:9> col:3 public
| | `-FieldDecl 0x55c3efc10310 <line:4:3, col:5> col:5 i 'T'
| |-ClassTemplateSpecialization 0x55c3efc103c0 'toto'
| `-FullComment 0x55c3efc10b20 <line:1:4, col:12>
|   `-ParagraphComment 0x55c3efc10af0 <col:4, col:12>
|     `-TextComment 0x55c3efc10ac0 <col:4, col:12> Text=" Template"
|-ClassTemplateSpecializationDecl 0x55c3efc103c0 <line:8:1, col:27> col:16 class toto definition
| |-TemplateArgument type 'double'
| |-FullComment 0x55c3efc10bf0 <line:7:4, col:15>
| | `-ParagraphComment 0x55c3efc10bc0 <col:4, col:15>
| |   `-TextComment 0x55c3efc10b90 <col:4, col:15> Text=" Instantiate"
| |-CXXRecordDecl 0x55c3efc105c0 prev 0x55c3efc103c0 <line:2:23, col:29> col:29 implicit class toto
| |-AccessSpecDecl 0x55c3efc10658 <line:3:3, col:9> col:3 public
| `-FieldDecl 0x55c3efc106b8 <line:4:3, col:5> col:5 i 'double':'double'
`-CXXRecordDecl 0x55c3efc10748 <line:11:1, line:14:1> line:11:7 class totoro definition
  |-FullComment 0x55c3efc10cc0 <line:10:4, col:10>
  | `-ParagraphComment 0x55c3efc10c90 <col:4, col:10>
  |   `-TextComment 0x55c3efc10c60 <col:4, col:10> Text=" Normal"
  |-CXXRecordDecl 0x55c3efc10868 <line:11:1, col:7> col:7 implicit class totoro
  |-AccessSpecDecl 0x55c3efc10900 <line:12:3, col:9> col:3 public
  `-FieldDecl 0x55c3efc10940 <line:13:3, col:10> col:10 i 'double'
parcollet commented 6 years ago

Ok, we discussed, we found that there is a fix in lib clang. Was it a fix in the cindex.py only ? At some point, we might want to include cindex.py in our code, also to make python 2 and 3 transition easier and not depends on packaging systems to have this file or not ...

parcollet commented 6 years ago

PS : if yes, we could simply add cindex.py and fix the bug now.