Cc65: [cc65] Yet another mixture piece of demo code for type-related bugs/enhancements

Created on 1 Aug 2020  路  10Comments  路  Source: cc65/cc65

Here's some piece of code that I'm willing to work on to get some expected output from cc65.
The individual Issues exposed should have their own topics, but let's just take a look first:

static static void* y[1];   /* duplicate storage class? */
extern void z[];            /* forward declaration of void (does cc65 have official extension for this?) */
extern struct T (*m)[];     /* forward declaration of incomplete type */
int n[];                    /* tentative "declaration" that should be "defined" by the end with assumed size = 1? */

typedef void F(void);
F f;                        /* you can actually define a "function typed" object? or is it just a function pointer? */
F* pf;                      /* always a 'void (*)(void)? */
F fa[1];                    /* should fail */

#ifdef __CC65__
void ex0    = { 0x1234, (char)12 };     /* our extension? */
void ex1[1] = { {0x1234, (char)12} };   /* OK or not? */
#endif

F* g(F x)                   /* is the parameter a 'void (void)' or a 'void (*)(void)'? */
{
    return &f;              /* is this a 'void (*)(void)' or a 'void (**)(void)'? */
}

struct S foo(void)          /* incomplete struct type */
{
    return 1;               /* always fails */
}

enum E bar(void)            /* incomplete enum type */
{
    return 1;               /* should this fail? */
}

int main(void)
{
    extern typedef int A;       /* too many errors? */
    &f + int a;                 /* just too many errors? */
    f + 0;                      /* should we support this extension? */
    register int a[1] = { 1 };  /* too many errors? */
    pf = g(f);                  /* OK? */
    (const void)&f;             /* should be allowed? */
    (F)&f;                      /* always an error I guess */
    (const F)f;                 /* should be allowed? */

    return 0;
}

The most significant problem you see with the current cc65 is some flood of errors on the same line. Then if you exclude them, you'll see there are mainly these topics:

  • Issue #1143: multiple storage class specifiers in one declaration
  • good old incomplete type declaration issues (see also #1096)

    • Issue #1206: arrays of incomplete typed elements

    • Issue #1205: conversion to incomplete types

  • Issue #1164: "tentative definitions" of arrays, again? (not really, just "related" to #975)

    • assume unknown size = 1 by the end?

  • Issue #1144: cc65 extension for void objects, and more complicated types with them (arrays etc.)?
  • function type vs function pointer type

    • PR #1218 (55896917c7287e5803374dc68e82245e38010011): when does a function type decay into a pointer/address?

  • Issue #1205: cast-ability

    • casting to qualified void types

    • casting to "non-arithmetic/pointer" types differred by just qualifiers

Yeah this is a big "question" topic for now despite of the error message flood. Maybe it will be converted to a "bug" or "enhancement" topic later.

enhancement

All 10 comments

Yeah this is a big "question" topic for now despite of the error message flood.

I know that good error messages a premier topic for main stream compilers, especially when it comes to C++ where people prefer Clang over GCC "just" for the way better error messages.

However, for cc65 I personally think it should rather focus on generating correct (and efficient) code for correct programs. I'm personally fine with every reaction on incorrect source code which isn't an internal compiler error or a straight crash.

Even if someone would say: Okay, Oliver, even if you personally aren't into better error messages, you surely aren't against PRs improving them, I'd answer: Let's see how much complexity better error message add to cc65 - which later on makes maintenance harder for others less skilled than you.

Just my two cents.

Now that I see how you want to proceed it seems this "issue" will never get "fixed" so I rather remove the 'bug' label again.

In my attempt to fix Issue #1089 (in the "strange message" part), I thought of the same. You won't see "pretty formatted" or "colorized" diagnostics like that in Clang or mordern GCC from me. ;)

Refactoring the code generator could help easing many of the complexity issues (and correctness issues like #250) we have encountered, but that's... not any time soon as far as I see.

Refactoring the code generator could help easing many of the complexity issues (and correctness issues like #250) we have encountered, but that's... not so soon as far as I see.

;-)

Compiled with current HEAD revision:

1142.c(1): Warning: Duplicate storage class specifier
1142.c(3): Error: Array of incomplete element type 'struct T'
1142.c(9): Error: Array of 0-size element type 'void (void)'
1142.c(19): Warning: Parameter 'x' is never used
1142.c(22): Error: Function has incomplete return type 'struct S'
1142.c(27): Error: Function has incomplete return type 'enum E'
1142.c(33): Error: Conflicting storage class specifier
1142.c(34): Error: Mixed declarations and code are not supported in cc65
1142.c(34): Error: Size of type 'void (void)' is unknown
1142.c(35): Error: Invalid operands for binary operator '+'
1142.c(36): Error: Mixed declarations and code are not supported in cc65
1142.c(39): Error: Arithmetic or pointer type expected but function is used
1142.c(40): Error: Arithmetic or pointer type expected but function is used
1142.c(43): Warning: Incomplete array 'n[]' assumed to have one element
11 errors and 3 warnings generated.

Have we done?

EDIT: The only fishy part is (Line 35) f + 0, where a function-to-function-pointer conversion is done with GCC and Clang, but rejected by cc65 with no conversion. Still, it's questionable what pointer arithmetics would be meaningful with function pointers:

void f() {}
void g() {}
&f + 0;  /* sensible but pointless? */
&f - &f; /* sensible but pointless? */
&f + 1;  /* what does this do? */
&f - &g; /* could just convert them to intptr_t (extension) and do this as integers */

I'm inclined to not bother to "fix" this conversion for some UB extensions that don't seem to serve a purpose.

I don't know what the term "UB extensions" refers to. Regarding the usefulness: Would arithmetic on an array of function pointers be a useful scenario? But that would be rather arithmetic on a pointer to a function pointer, right?

I don't know what the term "UB extensions" refers to.

Pointer arithmetics with function pointers is undefined behaviour (UB). Apparently GCC and Clang accept it however, so they implement a "UB extension".

I find this a rather esoteric and weird thing to do and wont miss it if it doesnt exist :)

I don't know what the term "UB extensions" refers to.

What mrdudz says. Undefined Behaviors "defined" by the compiler as extensions. In the example above, to do function pointer arithmetics as if they were char/byte pointers for GCC and Clang.

Regarding the usefulness: Would arithmetic on an array of function pointers be a useful scenario?

To implement "virtual-table" polymorphism in C, perhaps?

But that would be rather arithmetic on a pointer to a function pointer, right?

Yeah. That is already working and not affected by this.

@acqn: Thanks for the explanation. I second @mrdudz that it's not worth any effort to support.

I find this a rather esoteric and weird thing to do and wont miss it if it doesnt exist :)

I'm pretty sure most people are thinking the whole cc65 project is esoteric ;-)

Was this page helpful?
0 / 5 - 0 ratings