drmortalwombat / oscar64

Optimizing Small memory C Compiler Assembler and Runtime for C64
GNU General Public License v3.0
273 stars 24 forks source link

Strange error when casting with parenthesis #83

Closed AGPX closed 2 months ago

AGPX commented 2 months ago

Hi,

in the following code:

#include <stdlib.h>
#include <string.h>

class string
{
private:
    char        *data_;
    unsigned int size_;

    void allocate_and_copy(const char *s, const unsigned int size)
    {
        if ((size == 0) || (s == nullptr)) {
            data_ = nullptr;
        }
        else
        {
            data_ = (char *)(malloc(size + 1));
            memcpy(data_, s, size);
            data_[size] = '\0';
        }
        size_ = size;
    }

public:
    string() : data_(nullptr), size_(0) {}

    string(const char *s) {
        allocate_and_copy(s, strlen(s));
    }

    ~string() {
        free(data_);
    }

    char getDigit(char digit) const
    {
        if (digit >= 'A' && digit <= 'F') {
            digit = digit - 'A' + 'a';
        }
        if (digit >= 'a' && digit <= 'f') {
            return (digit - 'a' + 10);
        }
        else if (digit >= '0' && digit <= '9') {
            return (digit - '0');
        }
        else {
            return 255;
        }
    }

    long to_long(char *const idx = nullptr, const char base = 10) const
    {
        long result = 0;
        bool negative = false;
        unsigned int i = 0;

        if (data_[0] == '-')
        {
            negative = true;
            ++i;
        }

        for (; i < size_; ++i)
        {
            const char digit = getDigit(data_[i]);
            if (digit == 255) {
                break;
            }
            result = result * base + digit;
        }

        if (negative) {
            result = -result;
        }

        if (idx != nullptr) {
            *idx = i;
        }

        return result;
    }

};

int main()
{
    signed char l;
    l = (signed char)(string("-116").to_long(nullptr, 10));    // <-- this gives strange errors, due to parenthesis
  //l = (signed char) string("-116").to_long(nullptr, 10) ;    // <-- this works
    return 0;
}

the second line of the main, gives unexpected errors. The third (commented) is identical but without parenthesis and compiles.

The errors are:

test.cpp(88, 30) : error 3006: ')' expected
test.cpp(88, 30) : error 3006: ')' expected
test.cpp(88, 36) : error 3006: ';' expected
test.cpp(88, 36) : error 3006: Term starts with invalid token '')''
test.cpp(88, 38) : error 3013: Struct expected
test.cpp(88, 38) : error 3006: ';' expected
test.cpp(88, 38) : error 3005: Unknown identifier 'to_long'
test.cpp(88, 45) : error 3013: Function expected for call
test.cpp(88, 58) : error 3006: ';' expected
test.cpp(88, 58) : error 3006: Term starts with invalid token '')''
drmortalwombat commented 2 months ago

You run into a case where C++ constructors cause ambiguity with type declarations, that sometimes can be resolved by parsing the complete expression or not. This case could be resolved, but my simplistic parser is too stupid. I added a special workaround for the parenthized typecast. You can also invoke the constructor qualified string::string. Both fixes checked it, give it a try.

AGPX commented 2 months ago

Ok, it seems to work.