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

Anonymous structure error in function's parameters #3

Open
X-Ryl669 opened this issue Jul 7, 2022 · 3 comments
Open

Anonymous structure error in function's parameters #3

X-Ryl669 opened this issue Jul 7, 2022 · 3 comments

Comments

@X-Ryl669
Copy link

X-Ryl669 commented Jul 7, 2022

Take this code for example:

typedef struct {
   int a;
} M;

int foo(const M bar);

Right now, crefl can't reproduce the signature for the foo function because the bar parameter is of type "qualifier(struct)" instead of "qualifier(typedef(struct))". Since the structure is anonymous, the only way to call this function is to use the typedef but this is not what crefl has stored in its database.

So, is there a way to find out the typedef's decl_ref for an anonymous structure's decl_ref ?
Or better, would it be possible for crefl to store the parameter as a typedef instead of a struct at first ?

@michaeljclark
Copy link
Owner

I see the typedef in the metadata. the query interfaces needs usability testing and refinement. this is a point where one was up to.

if you see the code example in the response to #1, you'll see the use of crefl_type(decl_db*, <type reference>) e.g. crefl_type(db, function f) which returns a decl_ref based on a stringified type reference. That macro doesn't actually exist yet in the source tree. It probably needs a run-time and compile-time parser for references to types in the crefl decl database. unfortunately, we don't have decltype(T) in C, but also we want to be able to get a reference to type metadata without statically seeing the type i.e. by an unambiguous name-spec.

$ ./scripts/run_tests.py test/input/example-1.h

===== INPUT  test-case: test/input/example-1.h =====

typedef struct {
   int a;
} M;

int foo(const M bar);

===== OUTPUT test-case: test/input/example-1.h =====

sizeof(decl_node)=32
id   attr next link type      name           props          detail              
--------------------------------------------------------------------------------
23   0    0    24   source    example-1.h                   struct("anonymous") 
24   0    26   25   struct    (anonymous)                   field("a")          
25   0    0    10   field     a                             intrinsic("int")    
26   0    27   24   typedef   M                             struct("anonymous") 
27   0    0    28   function  foo            extern_c,globa…param("anonymous")  
28   0    29   10   param     (anonymous)    out            intrinsic("int")    
29   0    0    30   param     bar                           qualifier("const_") 
30   0    0    24   qualifier const_         const          struct("anonymous") 
--------------------------------------------------------------------------------

It might be possible to formulate the references to the types in less ambiguous ways than C. i.e. Rust-style or Go-style where types are left-to-right instead of a complex mix of left-to-right and right-to-left due to C pointer specification mess.

try ./scripts/run_tests.py test/input/pointer-to-array-3.h to see what I mean.

$ ./scripts/run_tests.py --dump-ext test/input/pointer-to-array-3.h 

===== INPUT  test-case: test/input/pointer-to-array-3.h =====

int f(int n, const int(*p)[n][10]);

===== OUTPUT test-case: test/input/pointer-to-array-3.h =====

sizeof(decl_node)=32
id   attr next link type      name                        props                    detail                        
-----------------------------------------------------------------------------------------------------------------
23   0    0    24   source    pointer-to-array-3.h                                 function("f")                 
24   0    0    25   function  f                           extern_c,global,addr=0x0 param("anonymous")            
25   0    26   10   param     (anonymous)                 out                      intrinsic("int")              
26   0    27   10   param     n                                                    intrinsic("int")              
27   0    0    31   param     p                                                    pointer("*[*][10]const_int")  
28   0    0    10   qualifier const_int                   const                    intrinsic("int")              
29   0    0    28   array     [10]const_int               size=10                  qualifier("const_int")        
30   0    0    29   array     [*][10]const_int            vla,size=0               array("[10]const_int")        
31   0    0    30   pointer   *[*][10]const_int           width=64                 array("[*][10]const_int")     
-----------------------------------------------------------------------------------------------------------------

@X-Ryl669
Copy link
Author

Maybe have a look to #5, I've tried to solve this when it isn't ambiguous. It gives something like this:

===== OUTPUT test-case: test/input/example-1.h =====

sizeof(decl_node)=32
id   attr next link type      name           props          detail              
--------------------------------------------------------------------------------
23   0    0    24   source    example-1.h                   struct("anonymous") 
24   0    26   25   struct    (anonymous)                   field("a")          
25   0    0    10   field     a                             intrinsic("int")    
26   0    27   24   typedef   M                             struct("anonymous") 
27   0    0    28   function  foo            extern_c,globa…param("anonymous")  
28   0    29   10   param     (anonymous)    out            intrinsic("int")    
29   0    0    30   param     bar                           qualifier("const_") 
30   0    0    24   qualifier const_         const          typedef(M)
--------------------------------------------------------------------------------

@michaeljclark
Copy link
Owner

I think I see what you mean from reading the output.

typedefs are desugared so the function links to the anonymous structure decl but do you want a link to the typedef instead?

I had wanted that also but I don't know the implications of a particular approach yet as not all clang AST methods are robust.

the test cases have not been "buttoned down" yet so to speak i.e. we presently use visual inspection of the resulting graphs and intend to create exemplars after inspection to tie the behaviour to the expected output. so the test cases we have at present are inputs that we need to handle but there is no reporting of errors unless. locally I save the output of run_tests.py and diff it.

I will take a look at the pull request...

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

No branches or pull requests

2 participants