Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Treat #define similarly to templates when used for types #1044

Open
RReverser opened this issue Sep 27, 2017 · 3 comments
Open

Treat #define similarly to templates when used for types #1044

RReverser opened this issue Sep 27, 2017 · 3 comments

Comments

@RReverser
Copy link

Input C Header

#define BUFFER_T(ITEM_T) struct { ITEM_T *data; size_t capacity; }
typedef BUFFER_T(char) char_buffer_t;
typedef BUFFER_T(int) int_buffer_t;

Actual Results

/* automatically generated by rust-bindgen */

pub type wchar_t = ::std::os::raw::c_int;
pub type max_align_t = f64;
#[repr(C)]
#[derive(Debug, Copy)]
pub struct char_buffer_t {
    pub data: *mut ::std::os::raw::c_char,
    pub capacity: usize,
}
#[test]
fn bindgen_test_layout_char_buffer_t() {
    // ...
}
impl Clone for char_buffer_t {
    fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct int_buffer_t {
    pub data: *mut ::std::os::raw::c_int,
    pub capacity: usize,
}
#[test]
fn bindgen_test_layout_int_buffer_t() {
    // ...
}
impl Clone for int_buffer_t {
    fn clone(&self) -> Self { *self }
}

Expected Results

Note that this is not a bug, but more of a feature request. Is there any chance to produce generic types for this case? (and maybe also for multiple-types case like covered in tests/headers/complex.h, but that's not so important)

Looking at handling of macro in var.rs, it should be doable, but I'm not sure if it's worth introducing separate handling / recognition just for macro or is it possible to somehow share the logic between C++ templates and C macro handling? The templates logic seems to be quite complex and scattered across bindgen, so I'm not sure how that would look like, but maybe there is an easy entry point that could be reused?

Currently I can workaround this by doing #ifdef __cplusplus magic that defines a template for C++ and macro then just instantiates that template, but this hack looks quite ugly and I don't really need it outside of the bindgen.

@fitzgen
Copy link
Member

fitzgen commented Sep 28, 2017

I don't think libclang's cursors really work inside of macros, so this would be fairly tricky. For example, here is a dump of clang's cursor AST for the given example:

(
 kind = macro definition
 spelling = "BUFFER_T"
 location = /home/fitzgen/scratch/macro-templates.h:3:9
 is-definition? false
 is-declaration? false
 is-inlined-function? false
 usr = "c:macro-templates.h@10@macro@BUFFER_T"

 type.kind = Invalid
)
(
 kind = macro expansion
 spelling = "BUFFER_T"
 location = /home/fitzgen/scratch/macro-templates.h:4:9
 is-definition? false
 is-declaration? false
 is-inlined-function? false

 referenced.kind = macro definition
 referenced.spelling = "BUFFER_T"
 referenced.location = /home/fitzgen/scratch/macro-templates.h:3:9
 referenced.is-definition? false
 referenced.is-declaration? false
 referenced.is-inlined-function? false
 referenced.usr = "c:macro-templates.h@10@macro@BUFFER_T"

 type.kind = Invalid
)
(
 kind = macro expansion
 spelling = "BUFFER_T"
 location = /home/fitzgen/scratch/macro-templates.h:5:9
 is-definition? false
 is-declaration? false
 is-inlined-function? false

 referenced.kind = macro definition
 referenced.spelling = "BUFFER_T"
 referenced.location = /home/fitzgen/scratch/macro-templates.h:3:9
 referenced.is-definition? false
 referenced.is-declaration? false
 referenced.is-inlined-function? false
 referenced.usr = "c:macro-templates.h@10@macro@BUFFER_T"

 type.kind = Invalid
)
(
 kind = StructDecl
 spelling = ""
 location = /home/fitzgen/scratch/macro-templates.h:4:9
 is-definition? true
 is-declaration? true
 is-inlined-function? false
 usr = "c:@SA@char_buffer_t"

 semantic-parent.kind = TranslationUnit
 semantic-parent.spelling = "/home/fitzgen/scratch/macro-templates.h"
 semantic-parent.location = builtin definitions
 semantic-parent.is-definition? false
 semantic-parent.is-declaration? false
 semantic-parent.is-inlined-function? false

 type.kind = Record
 type.cconv = 100
 type.spelling = "char_buffer_t"
 type.is-variadic? false

    (
     kind = FieldDecl
     spelling = "data"
     location = /home/fitzgen/scratch/macro-templates.h:4:9
     is-definition? true
     is-declaration? true
     is-inlined-function? false
     usr = "c:@SA@char_buffer_t@FI@data"

     semantic-parent.kind = StructDecl
     semantic-parent.spelling = ""
     semantic-parent.location = /home/fitzgen/scratch/macro-templates.h:4:9
     semantic-parent.is-definition? true
     semantic-parent.is-declaration? true
     semantic-parent.is-inlined-function? false
     semantic-parent.usr = "c:@SA@char_buffer_t"

     semantic-parent.semantic-parent.kind = TranslationUnit
     semantic-parent.semantic-parent.spelling = "/home/fitzgen/scratch/macro-templates.h"
     semantic-parent.semantic-parent.location = builtin definitions
     semantic-parent.semantic-parent.is-definition? false
     semantic-parent.semantic-parent.is-declaration? false
     semantic-parent.semantic-parent.is-inlined-function? false

     type.kind = Pointer
     type.cconv = 100
     type.spelling = "char *"
     type.is-variadic? false

     type.pointee.kind = Char_S
     type.pointee.cconv = 100
     type.pointee.spelling = "char"
     type.pointee.is-variadic? false
    )
    (
     kind = FieldDecl
     spelling = "capacity"
     location = /home/fitzgen/scratch/macro-templates.h:4:9
     is-definition? true
     is-declaration? true
     is-inlined-function? false
     usr = "c:@SA@char_buffer_t@FI@capacity"

     semantic-parent.kind = StructDecl
     semantic-parent.spelling = ""
     semantic-parent.location = /home/fitzgen/scratch/macro-templates.h:4:9
     semantic-parent.is-definition? true
     semantic-parent.is-declaration? true
     semantic-parent.is-inlined-function? false
     semantic-parent.usr = "c:@SA@char_buffer_t"

     semantic-parent.semantic-parent.kind = TranslationUnit
     semantic-parent.semantic-parent.spelling = "/home/fitzgen/scratch/macro-templates.h"
     semantic-parent.semantic-parent.location = builtin definitions
     semantic-parent.semantic-parent.is-definition? false
     semantic-parent.semantic-parent.is-declaration? false
     semantic-parent.semantic-parent.is-inlined-function? false

     type.kind = Int
     type.cconv = 100
     type.spelling = "int"
     type.is-variadic? false
    )
)
(
 kind = TypedefDecl
 spelling = "char_buffer_t"
 location = /home/fitzgen/scratch/macro-templates.h:4:24
 is-definition? true
 is-declaration? true
 is-inlined-function? false
 usr = "c:macro-templates.h@T@char_buffer_t"
 typedef-type = Elaborated

 semantic-parent.kind = TranslationUnit
 semantic-parent.spelling = "/home/fitzgen/scratch/macro-templates.h"
 semantic-parent.location = builtin definitions
 semantic-parent.is-definition? false
 semantic-parent.is-declaration? false
 semantic-parent.is-inlined-function? false

 type.kind = Typedef
 type.cconv = 100
 type.spelling = "char_buffer_t"
 type.is-variadic? false

 type.canonical.kind = Record
 type.canonical.cconv = 100
 type.canonical.spelling = "char_buffer_t"
 type.canonical.is-variadic? false

    (
     kind = StructDecl
     spelling = ""
     location = /home/fitzgen/scratch/macro-templates.h:4:9
     is-definition? true
     is-declaration? true
     is-inlined-function? false
     usr = "c:@SA@char_buffer_t"

     semantic-parent.kind = TranslationUnit
     semantic-parent.spelling = "/home/fitzgen/scratch/macro-templates.h"
     semantic-parent.location = builtin definitions
     semantic-parent.is-definition? false
     semantic-parent.is-declaration? false
     semantic-parent.is-inlined-function? false

     type.kind = Record
     type.cconv = 100
     type.spelling = "char_buffer_t"
     type.is-variadic? false

        (
         kind = FieldDecl
         spelling = "data"
         location = /home/fitzgen/scratch/macro-templates.h:4:9
         is-definition? true
         is-declaration? true
         is-inlined-function? false
         usr = "c:@SA@char_buffer_t@FI@data"

         semantic-parent.kind = StructDecl
         semantic-parent.spelling = ""
         semantic-parent.location = /home/fitzgen/scratch/macro-templates.h:4:9
         semantic-parent.is-definition? true
         semantic-parent.is-declaration? true
         semantic-parent.is-inlined-function? false
         semantic-parent.usr = "c:@SA@char_buffer_t"

         semantic-parent.semantic-parent.kind = TranslationUnit
         semantic-parent.semantic-parent.spelling = "/home/fitzgen/scratch/macro-templates.h"
         semantic-parent.semantic-parent.location = builtin definitions
         semantic-parent.semantic-parent.is-definition? false
         semantic-parent.semantic-parent.is-declaration? false
         semantic-parent.semantic-parent.is-inlined-function? false

         type.kind = Pointer
         type.cconv = 100
         type.spelling = "char *"
         type.is-variadic? false

         type.pointee.kind = Char_S
         type.pointee.cconv = 100
         type.pointee.spelling = "char"
         type.pointee.is-variadic? false
        )
        (
         kind = FieldDecl
         spelling = "capacity"
         location = /home/fitzgen/scratch/macro-templates.h:4:9
         is-definition? true
         is-declaration? true
         is-inlined-function? false
         usr = "c:@SA@char_buffer_t@FI@capacity"

         semantic-parent.kind = StructDecl
         semantic-parent.spelling = ""
         semantic-parent.location = /home/fitzgen/scratch/macro-templates.h:4:9
         semantic-parent.is-definition? true
         semantic-parent.is-declaration? true
         semantic-parent.is-inlined-function? false
         semantic-parent.usr = "c:@SA@char_buffer_t"

         semantic-parent.semantic-parent.kind = TranslationUnit
         semantic-parent.semantic-parent.spelling = "/home/fitzgen/scratch/macro-templates.h"
         semantic-parent.semantic-parent.location = builtin definitions
         semantic-parent.semantic-parent.is-definition? false
         semantic-parent.semantic-parent.is-declaration? false
         semantic-parent.semantic-parent.is-inlined-function? false

         type.kind = Int
         type.cconv = 100
         type.spelling = "int"
         type.is-variadic? false
        )
    )
)
(
 kind = StructDecl
 spelling = ""
 location = /home/fitzgen/scratch/macro-templates.h:5:9
 is-definition? true
 is-declaration? true
 is-inlined-function? false
 usr = "c:@SA@int_buffer_t"

 semantic-parent.kind = TranslationUnit
 semantic-parent.spelling = "/home/fitzgen/scratch/macro-templates.h"
 semantic-parent.location = builtin definitions
 semantic-parent.is-definition? false
 semantic-parent.is-declaration? false
 semantic-parent.is-inlined-function? false

 type.kind = Record
 type.cconv = 100
 type.spelling = "int_buffer_t"
 type.is-variadic? false

    (
     kind = FieldDecl
     spelling = "data"
     location = /home/fitzgen/scratch/macro-templates.h:5:9
     is-definition? true
     is-declaration? true
     is-inlined-function? false
     usr = "c:@SA@int_buffer_t@FI@data"

     semantic-parent.kind = StructDecl
     semantic-parent.spelling = ""
     semantic-parent.location = /home/fitzgen/scratch/macro-templates.h:5:9
     semantic-parent.is-definition? true
     semantic-parent.is-declaration? true
     semantic-parent.is-inlined-function? false
     semantic-parent.usr = "c:@SA@int_buffer_t"

     semantic-parent.semantic-parent.kind = TranslationUnit
     semantic-parent.semantic-parent.spelling = "/home/fitzgen/scratch/macro-templates.h"
     semantic-parent.semantic-parent.location = builtin definitions
     semantic-parent.semantic-parent.is-definition? false
     semantic-parent.semantic-parent.is-declaration? false
     semantic-parent.semantic-parent.is-inlined-function? false

     type.kind = Pointer
     type.cconv = 100
     type.spelling = "int *"
     type.is-variadic? false

     type.pointee.kind = Int
     type.pointee.cconv = 100
     type.pointee.spelling = "int"
     type.pointee.is-variadic? false
    )
    (
     kind = FieldDecl
     spelling = "capacity"
     location = /home/fitzgen/scratch/macro-templates.h:5:9
     is-definition? true
     is-declaration? true
     is-inlined-function? false
     usr = "c:@SA@int_buffer_t@FI@capacity"

     semantic-parent.kind = StructDecl
     semantic-parent.spelling = ""
     semantic-parent.location = /home/fitzgen/scratch/macro-templates.h:5:9
     semantic-parent.is-definition? true
     semantic-parent.is-declaration? true
     semantic-parent.is-inlined-function? false
     semantic-parent.usr = "c:@SA@int_buffer_t"

     semantic-parent.semantic-parent.kind = TranslationUnit
     semantic-parent.semantic-parent.spelling = "/home/fitzgen/scratch/macro-templates.h"
     semantic-parent.semantic-parent.location = builtin definitions
     semantic-parent.semantic-parent.is-definition? false
     semantic-parent.semantic-parent.is-declaration? false
     semantic-parent.semantic-parent.is-inlined-function? false

     type.kind = Int
     type.cconv = 100
     type.spelling = "int"
     type.is-variadic? false
    )
)
(
 kind = TypedefDecl
 spelling = "int_buffer_t"
 location = /home/fitzgen/scratch/macro-templates.h:5:23
 is-definition? true
 is-declaration? true
 is-inlined-function? false
 usr = "c:macro-templates.h@T@int_buffer_t"
 typedef-type = Elaborated

 semantic-parent.kind = TranslationUnit
 semantic-parent.spelling = "/home/fitzgen/scratch/macro-templates.h"
 semantic-parent.location = builtin definitions
 semantic-parent.is-definition? false
 semantic-parent.is-declaration? false
 semantic-parent.is-inlined-function? false

 type.kind = Typedef
 type.cconv = 100
 type.spelling = "int_buffer_t"
 type.is-variadic? false

 type.canonical.kind = Record
 type.canonical.cconv = 100
 type.canonical.spelling = "int_buffer_t"
 type.canonical.is-variadic? false

    (
     kind = StructDecl
     spelling = ""
     location = /home/fitzgen/scratch/macro-templates.h:5:9
     is-definition? true
     is-declaration? true
     is-inlined-function? false
     usr = "c:@SA@int_buffer_t"

     semantic-parent.kind = TranslationUnit
     semantic-parent.spelling = "/home/fitzgen/scratch/macro-templates.h"
     semantic-parent.location = builtin definitions
     semantic-parent.is-definition? false
     semantic-parent.is-declaration? false
     semantic-parent.is-inlined-function? false

     type.kind = Record
     type.cconv = 100
     type.spelling = "int_buffer_t"
     type.is-variadic? false

        (
         kind = FieldDecl
         spelling = "data"
         location = /home/fitzgen/scratch/macro-templates.h:5:9
         is-definition? true
         is-declaration? true
         is-inlined-function? false
         usr = "c:@SA@int_buffer_t@FI@data"

         semantic-parent.kind = StructDecl
         semantic-parent.spelling = ""
         semantic-parent.location = /home/fitzgen/scratch/macro-templates.h:5:9
         semantic-parent.is-definition? true
         semantic-parent.is-declaration? true
         semantic-parent.is-inlined-function? false
         semantic-parent.usr = "c:@SA@int_buffer_t"

         semantic-parent.semantic-parent.kind = TranslationUnit
         semantic-parent.semantic-parent.spelling = "/home/fitzgen/scratch/macro-templates.h"
         semantic-parent.semantic-parent.location = builtin definitions
         semantic-parent.semantic-parent.is-definition? false
         semantic-parent.semantic-parent.is-declaration? false
         semantic-parent.semantic-parent.is-inlined-function? false

         type.kind = Pointer
         type.cconv = 100
         type.spelling = "int *"
         type.is-variadic? false

         type.pointee.kind = Int
         type.pointee.cconv = 100
         type.pointee.spelling = "int"
         type.pointee.is-variadic? false
        )
        (
         kind = FieldDecl
         spelling = "capacity"
         location = /home/fitzgen/scratch/macro-templates.h:5:9
         is-definition? true
         is-declaration? true
         is-inlined-function? false
         usr = "c:@SA@int_buffer_t@FI@capacity"

         semantic-parent.kind = StructDecl
         semantic-parent.spelling = ""
         semantic-parent.location = /home/fitzgen/scratch/macro-templates.h:5:9
         semantic-parent.is-definition? true
         semantic-parent.is-declaration? true
         semantic-parent.is-inlined-function? false
         semantic-parent.usr = "c:@SA@int_buffer_t"

         semantic-parent.semantic-parent.kind = TranslationUnit
         semantic-parent.semantic-parent.spelling = "/home/fitzgen/scratch/macro-templates.h"
         semantic-parent.semantic-parent.location = builtin definitions
         semantic-parent.semantic-parent.is-definition? false
         semantic-parent.semantic-parent.is-declaration? false
         semantic-parent.semantic-parent.is-inlined-function? false

         type.kind = Int
         type.cconv = 100
         type.spelling = "int"
         type.is-variadic? false
        )
    )
)

It gives us the expanded code, and that there was a macro expansion, but the only way we're given to look inside of macros is a stream of tokens.

I'm not sure this is something we want to support.

@RReverser
Copy link
Author

Well yeah, it gives only stream of tokens, but it can be fed back to clang to detect type definitions?

@RReverser
Copy link
Author

RReverser commented Sep 28, 2017

It also seems that looking "into" C macro contents this way can reveal other interesting possibilities.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants