Commit Graph

18 Commits

Author SHA1 Message Date
Stephen Heumann 896c60d18c Determine the type to use for computing a >>= or <<= operation based only on the left operand.
Also, fix a case where an uninitialized value could be used, potentially resulting in errors not being reported (although I haven’t seen that in practice).

This fixes problems where >>= operations might not use an arithmetic shift in certain cases where they should, as in the below program:

#include <stdio.h>
int main (void)
{
    int i;
    unsigned u;
    long l;
    unsigned long ul;

    i = -1;
    u = 1;
    i >>= u;
    printf("%i\n", i); /* should be -1 */

    l = -1;
    ul = 3;
    l >>= ul;
    printf("%li\n", l); /* should be -1 */
}
2017-10-21 20:36:21 -05:00
Stephen Heumann 67a29304a7 Fix to consistently update expressionType to reflect the application of usual unary conversions (promotions).
This is necessary so that subsequent processing sees the correct expression type and proceeds accordingly. In particular, without this patch, the casts in the below program were erroneously ignored:

#include <stdio.h>
int main(void)
{
    unsigned int u;
    unsigned char c;

    c = 0;
    u = (unsigned char)~c;
    printf("%u\n", u);

    c = 200;
    printf("%i\n", (unsigned char)(c+c));
}
2017-10-21 20:36:21 -05:00
Stephen Heumann af48935d43 Fix so the type of shift expressions depends only on the (promoted) type of their left operand.
This is as required by the C standards: the type of the right operand should not affect the result type.

The following program demonstrates problems with the old behavior:

#include <stdio.h>

int main(void)
{
    unsigned long ul;
    long l;
    unsigned u;
    int i;

    ul = 0x8000 << 1L; /* should be 0 */
    printf("%lx\n", ul);

    l = -1 >> 1U; /* should be -1 */
    printf("%ld\n", l);

    u = 0xFF10;
    l = 8;
    ul = u << l; /* should be 0x1000 */
    printf("%lx\n", ul);

    l = -4;
    ul = 1;
    l = l >> ul; /* should be -2 */
    printf("%ld\n", l);
}
2017-10-21 20:36:21 -05:00
Stephen Heumann 8b4c83f527 Give an error when trying to use sizeof on incomplete struct or union types.
The following demonstrates cases that would erroneously be allowed (and misleadingly give a size of 0) before:

#include <stdio.h>
struct s *S;
int main(void)
{
        printf("%lu %lu\n", sizeof(struct s), sizeof *S);
}
2017-10-21 20:36:21 -05:00
Stephen Heumann 5950002d03 Fix so the result of sizeof has type unsigned long (i.e. size_t), not signed long.
The following test case demonstrates the problem:

#include <stdio.h>

int main (void)
{
        if (sizeof(int) - 5 < 0) puts("error 1");
        if (sizeof &main - 9 < 0) puts("error 2");
}
2017-10-21 20:36:21 -05:00
Stephen Heumann 26a800e667 Fix bug where certain integer constant expressions would have type signed long when they should have type unsigned long.
This affected binary or unary expressions with constant operands, at least one of which was of type unsigned long.

The following test case demonstrates the problem:

#include <stdio.h>
int main (void)
{
        if (0 + 0x80000000ul < 0) puts("error 1");
        if (~0ul < 0) puts("error 2");
}
2017-10-21 20:36:21 -05:00
Stephen Heumann fa5974199d Don't allow the unary * operator to be applied to structs and unions. 2017-10-21 20:36:20 -05:00
Stephen Heumann f7c3c26794 Report an error when trying to cast a void expression to a non-void type. 2017-10-21 20:36:20 -05:00
Stephen Heumann 89f1dbce9b Report an error when void values are used in binary expressions.
These would previously be allowed, with the void value treated as if it was unsigned long.

Void values are still allowed for the second and third operands of the ?: operator, but only if they are both void. This is as required by the C standard.
2017-10-21 20:36:20 -05:00
Stephen Heumann b83ed7b17b Do not erroneously treat integer constant expressions of type unsigned int as signed in certain contexts.
Unsigned constants in the range 0x8000-0xFFFF were erroneously being treated like negative signed values in some contexts, including in array declarators and in the case labels of switch statements where the expression switched over has type long or unsigned long.

This could lead to bogus compile errors for array declarations and typedefs such as the following:

typedef char foo[0x8000];

It could also lead to cases in switch statements not being properly matched, as in the following program:

#include <stdio.h>
int main(void)
{
    long i = 0xFF00;
    switch (i) {
        case 0xFF00:
            puts("good");
            break;
        default:
            puts("bad");
    }
}
2017-10-21 20:36:20 -05:00
Stephen Heumann ab51fc228d Allow string and double constants to appear within the operands of sizeof in a constant expression.
This fixes one of the problems in the compca08.c test case.
2017-10-21 20:36:20 -05:00
Stephen Heumann 3b9101ea30 Support += and -= operators on function parameters declared using array syntax (which are adjusted to have pointer type).
This fixes the compca25.c test case.
2017-10-21 20:36:20 -05:00
Stephen Heumann 78493936bc When a bit-field is used within an lvalue expression but isn't what's being assigned to, don't erroneously assign to the bit-field instead.
This fixes the compca04.c test case.
2017-10-21 20:36:20 -05:00
Stephen Heumann c788052b99 Allow dereferencing pointers to const struct or const union types.
This fixes the bug in the compca03.c test case.
2017-10-21 20:36:20 -05:00
Stephen Heumann c4360c70a1 Allow arrays to be used (implicitly converted to pointers) as operands of && and ||, and the first operand of the ? : operator.
This fixes the bug in the compca02.c test case.
2017-10-21 20:36:20 -05:00
Stephen Heumann a39c06d268 Usual unary conversions (promotions) should promote unsigned char to int, not unsigned int.
This fixes the compca13.c test case.
2017-10-21 20:36:20 -05:00
Stephen Heumann 46b6aa389f Change all text/source files to LF line endings. 2017-10-21 18:40:19 -05:00
mikew50 e72177985e ORCA/C 2.1.0 source from the Opus ][ CD 2017-10-01 17:47:47 -06:00