Skip to content

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

Open

Description

@scherno2000

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;}*;

Activity

  1. virtuald commented on Nov 15, 2023

    @virtuald
    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.

  2. scherno2000 commented on Nov 16, 2023

    @scherno2000
    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).

  3. virtuald commented on Nov 20, 2023

    @virtuald
    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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions