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

[PARSE BUG]: various type aliases (C array, struct, function) #83

Open
scherno2000 opened this issue Nov 15, 2023 · 3 comments
Open

[PARSE BUG]: various type aliases (C array, struct, function) #83

scherno2000 opened this issue Nov 15, 2023 · 3 comments

Comments

@scherno2000
Copy link

Problem description

It seems that the new style of alias declarations are not completely implemented.
The equivalent typedefs are working as expected.

I provide below a short program which works under compiler explorer, but is not parsed correctly (I took the declaration part into the demo)

#include <iostream>

using namespace std;

// --------------- begin to be placed into the parser demo
using aType = int[4];
using fType = void(int);
using lType = struct {int x;int y;int z;int t;};
using sType = struct l{int x;int y;int z;int t;};
using vType = union {int x;int y;int z;int t;};
using uType = union v{int x;int y;int z;int t;};
using arefType = int(&)[4];
using frefType = int(&)(int);
using lrefType = struct {int x;int y;int z;int t;}&;
using srefType = struct l/*{int x;int y;int z;int t;}*/&;
using vrefType = union {int x;int y;int z;int t;}&;
using urefType = union v/*{int x;int y;int z;int t;}*/&;
using aptrType = int(*)[4];
using fptrType = int(*)(int);
using lptrType = struct {int x;int y;int z;int t;}*;
using sptrType = struct l/*{int x;int y;int z;int t;}*/*;
using vptrType = union {int x;int y;int z;int t;}*;
using uptrType = union v/*{int x;int y;int z;int t;}*/*;

typedef int(aType1)[4];
typedef void(fType1)(int);
typedef struct {int x;int y;int z;int t;} lType1;
typedef struct l/*{int x;int y;int z;int t;}*/ sType1;
typedef union {int x;int y;int z;int t;} vType1;
typedef union v/*{int x;int y;int z;int t;}*/ uType1;
typedef int(&arefType1)[4];
typedef int(&frefType1)(int);
typedef struct {int x;int y;int z;int t;}& lrefType1;
typedef struct l/*{int x;int y;int z;int t;}*/& srefType1;
typedef union {int x;int y;int z;int t;}& vrefType1;
typedef union v/*{int x;int y;int z;int t;}*/& urefType1;
typedef int(*aptrType1)[4];
typedef int(*fptrType1)(int);
typedef struct {int x;int y;int z;int t;}* lptrType1;
typedef struct l/*{int x;int y;int z;int t;}*/* sptrType1;
typedef union {int x;int y;int z;int t;}* vptrType1;
typedef union v/*{int x;int y;int z;int t;}*/* uptrType1;
// --------------- end to be placed into the parser demo

int f(int x)
{
    return x;
}

int main(int argc, char* argv[]) 
{ 
    aType x{0,1,2,3};
    cout << x[1] << endl;
    static_assert(is_same<aType, aType1>::value, "wrong");
    static_assert(is_same<decltype(x[1]), int&>::value, "wrong");

    arefType x2 = x;
    cout << x2[2] << endl;
    static_assert(is_same<arefType, arefType1>::value, "wrong");
    static_assert(is_same<decltype(x2[2]), int&>::value, "wrong");

    aptrType x3 = &x;
    cout << (*x3)[3] << endl;
    static_assert(is_same<aptrType, aptrType1>::value, "wrong");
    static_assert(is_same<decltype((*x3)[3]), int&>::value, "wrong");

    static_assert(is_same<arefType, aType&>::value, "wrong");
    static_assert(is_same<aptrType, aType*>::value, "wrong");

//---------------------------------

    cout << f(1) << endl;
    static_assert(is_same<fType, fType1>::value, "wrong");
    static_assert(is_same<decltype(f(1)), int>::value, "wrong");

    frefType ff2 = f;
    cout << ff2(2) << endl;
    static_assert(is_same<frefType, frefType1>::value, "wrong");
    static_assert(is_same<decltype(ff2(2)), int>::value, "wrong");

    fptrType ff3 = f;
    cout << ff3(3) << endl;
    static_assert(is_same<fptrType, fptrType1>::value, "wrong");
    static_assert(is_same<decltype(ff3(3)), int>::value, "wrong");

    static_assert(is_same<frefType, decltype(f)&>::value, "wrong");
    static_assert(is_same<fptrType, decltype(f)*>::value, "wrong");

//---------------------------------

    sType s{0,1,2,3};
    cout << s.y << endl;
    static_assert(is_same<sType, sType1>::value, "wrong");
    static_assert(is_same<decltype(s.y), int>::value, "wrong");

    srefType s2 = s;
    cout << s2.z << endl;
    static_assert(is_same<srefType, srefType1>::value, "wrong");
    static_assert(is_same<decltype(s2.z), int>::value, "wrong");

    sptrType s3 = &s;
    cout << s3->t << endl;
    static_assert(is_same<sptrType, sptrType1>::value, "wrong");
    static_assert(is_same<decltype(s3->t), int>::value, "wrong");

    static_assert(is_same<srefType, sType&>::value, "wrong");
    static_assert(is_same<sptrType, sType*>::value, "wrong");

    //anon structs are different types
    static_assert(!is_same<lrefType, lType&>::value, "wrong");
    static_assert(!is_same<lptrType, lType*>::value, "wrong");
//---------------------------------

    uType u; u.y=1;
    cout << u.y << endl;
    static_assert(is_same<sType, sType1>::value, "wrong");
    static_assert(is_same<decltype(s.y), int>::value, "wrong");

    urefType u2 = u; u.z=2;
    cout << u2.z << endl;
    static_assert(is_same<urefType, urefType1>::value, "wrong");
    static_assert(is_same<decltype(u2.z), int>::value, "wrong");

    uptrType u3 = &u; u.t=3;
    cout << u3->t << endl;
    static_assert(is_same<uptrType, uptrType1>::value, "wrong");
    static_assert(is_same<decltype(u3->t), int>::value, "wrong");

    static_assert(is_same<urefType, uType&>::value, "wrong");
    static_assert(is_same<uptrType, uType*>::value, "wrong");

    //anon unions are different types
    static_assert(!is_same<vrefType, vType&>::value, "wrong");
    static_assert(!is_same<vptrType, vType*>::value, "wrong");

    return 0;
}

C++ code that can't be parsed correctly (please double-check that https://robotpy.github.io/cxxheaderparser/ has the same error)

//these all fail to be parsed, the typedef equivalents are correctly parsed.
using aType = int[4];
using fType = void(int);
using lType = struct {int x;int y;int z;int t;};
using sType = struct l{int x;int y;int z;int t;};
using vType = union {int x;int y;int z;int t;};
using uType = union v{int x;int y;int z;int t;};
using lrefType = struct {int x;int y;int z;int t;}&;
using vrefType = union {int x;int y;int z;int t;}&;
using lptrType = struct {int x;int y;int z;int t;}*;
using vptrType = union {int x;int y;int z;int t;}*;
@virtuald
Copy link
Member

How are you intending to use the parsed data? If you just need it to parse then this should be straightforward to do, but I note that the way I implemented typedefs is a bit annoying to actually use the data.

@scherno2000
Copy link
Author

I would use them to generate some kind of documentation. (I would generate a json file, and then I would use the json in my program as the source).

It would be OK for me analogous to the way the typedefs are implemented as it contains all of the necessary data.
Basically what I need is equivalent to be possible to reconstruct the original alias declaration considering also the enclosing context (namespace scope, class scope), based on the the parsed data (I would use the generated json for this purpose).

@virtuald
Copy link
Member

I looked at this briefly the other night and it's slightly more involved than I thought it would be, and my time is a bit limited at the moment.

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