mirror of
https://github.com/cc65/cc65.git
synced 2024-06-18 07:29:36 +00:00
Merge branch 'master' into fptest
# Conflicts: # src/cc65/expr.c
This commit is contained in:
commit
ececcad756
|
@ -7,9 +7,13 @@ For details look at the [Website](https://cc65.github.io).
|
|||
|
||||
## People
|
||||
|
||||
Project founder:
|
||||
Project founders:
|
||||
|
||||
* Ullrich von Bassewitz
|
||||
* John R. Dunning: original implementation of the C compiler and runtime library, Atari hosted
|
||||
* Ullrich von Bassewitz:
|
||||
* move the code to modern systems
|
||||
* rewrite most parts of the compiler
|
||||
* complete rewrite of the runtime library
|
||||
|
||||
Core team members:
|
||||
|
||||
|
|
|
@ -1422,7 +1422,7 @@ static void Primary (ExprDesc* E)
|
|||
} else {
|
||||
/* Let's see if this is a C99-style declaration */
|
||||
DeclSpec Spec;
|
||||
ParseDeclSpec (&Spec, TS_DEFAULT_TYPE_INT, SC_AUTO);
|
||||
ParseDeclSpec (&Spec, TS_DEFAULT_TYPE_NONE, SC_AUTO);
|
||||
|
||||
if ((Spec.Flags & DS_TYPE_MASK) != DS_NONE) {
|
||||
Error ("Mixed declarations and code are not supported in cc65");
|
||||
|
@ -2049,7 +2049,7 @@ void hie10 (ExprDesc* Expr)
|
|||
if (ED_IsConstAbs (Expr)) {
|
||||
/* Constant numeric expression */
|
||||
Expr->IVal = !Expr->IVal;
|
||||
} else if (ED_IsAddrExpr (Expr)) {
|
||||
} else if (ED_IsEntityAddr (Expr)) {
|
||||
/* Address != NULL, so !Address == 0 */
|
||||
ED_MakeConstBool (Expr, 0);
|
||||
} else {
|
||||
|
@ -2737,8 +2737,8 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */
|
|||
}
|
||||
|
||||
/* Check for numeric constant operands */
|
||||
if ((ED_IsAddrExpr (Expr) && ED_IsNullPtr (&Expr2)) ||
|
||||
(ED_IsNullPtr (Expr) && ED_IsAddrExpr (&Expr2))) {
|
||||
if ((ED_IsEntityAddr (Expr) && ED_IsNullPtr (&Expr2)) ||
|
||||
(ED_IsNullPtr (Expr) && ED_IsEntityAddr (&Expr2))) {
|
||||
LOG(("hie_compare numeric constant operands\n"));
|
||||
/* Object addresses are inequal to null pointer */
|
||||
Expr->IVal = (Tok != TOK_EQ);
|
||||
|
@ -2770,8 +2770,8 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */
|
|||
pop (ltype);
|
||||
}
|
||||
|
||||
} else if (ED_IsAddrExpr (Expr) &&
|
||||
ED_IsAddrExpr (&Expr2) &&
|
||||
} else if (ED_IsEntityAddr (Expr) &&
|
||||
ED_IsEntityAddr (&Expr2) &&
|
||||
Expr->Sym == Expr2.Sym) {
|
||||
/* Evaluate the result for static addresses */
|
||||
unsigned long Val1 = Expr->IVal;
|
||||
|
@ -4658,10 +4658,10 @@ static void hieQuest (ExprDesc* Expr)
|
|||
NextToken ();
|
||||
|
||||
/* Parse second expression. Remember for later if it is a NULL pointer
|
||||
** expression, then load it into the primary.
|
||||
** constant expression, then load it into the primary.
|
||||
*/
|
||||
ExprWithCheck (hie0, &Expr2);
|
||||
Expr2IsNULL = ED_IsNullPtr (&Expr2);
|
||||
Expr2IsNULL = ED_IsNullPtrConstant (&Expr2);
|
||||
if (!IsTypeVoid (Expr2.Type) &&
|
||||
ED_YetToLoad (&Expr2) &&
|
||||
(!ConstantCond || !ED_IsConst (&Expr2))) {
|
||||
|
@ -4705,10 +4705,10 @@ static void hieQuest (ExprDesc* Expr)
|
|||
ConsumeColon ();
|
||||
|
||||
/* Parse third expression. Remember for later if it is a NULL pointer
|
||||
** expression, then load it into the primary.
|
||||
** constant expression, then load it into the primary.
|
||||
*/
|
||||
ExprWithCheck (hieQuest, &Expr3);
|
||||
Expr3IsNULL = ED_IsNullPtr (&Expr3);
|
||||
Expr3IsNULL = ED_IsNullPtrConstant (&Expr3);
|
||||
if (!IsTypeVoid (Expr3.Type) &&
|
||||
ED_YetToLoad (&Expr3) &&
|
||||
(!ConstantCond || !ED_IsConst (&Expr3))) {
|
||||
|
@ -5022,8 +5022,13 @@ ExprDesc NoCodeConstExpr (void (*Func) (ExprDesc*))
|
|||
if (!ED_IsConst (&Expr) || !ED_CodeRangeIsEmpty (&Expr)) {
|
||||
Error ("Constant expression expected");
|
||||
/* To avoid any compiler errors, make the expression a valid const */
|
||||
Expr.Flags &= E_MASK_RTYPE | E_MASK_KEEP_RESULT;
|
||||
Expr.Flags &= E_MASK_RTYPE | E_MASK_KEEP_MAKE;
|
||||
Expr.Flags |= E_LOC_NONE;
|
||||
|
||||
/* Remove any non-constant code generated */
|
||||
if (!ED_CodeRangeIsEmpty (&Expr)) {
|
||||
RemoveCodeRange (&Expr.Start, &Expr.End);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return by value */
|
||||
|
@ -5048,6 +5053,11 @@ ExprDesc NoCodeConstAbsIntExpr (void (*Func) (ExprDesc*))
|
|||
Error ("Constant integer expression expected");
|
||||
/* To avoid any compiler errors, make the expression a valid const */
|
||||
ED_MakeConstAbsInt (&Expr, 1);
|
||||
|
||||
/* Remove any non-constant code generated */
|
||||
if (!ED_CodeRangeIsEmpty (&Expr)) {
|
||||
RemoveCodeRange (&Expr.Start, &Expr.End);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return by value */
|
||||
|
|
|
@ -255,7 +255,7 @@ int ED_IsConstTrue (const ExprDesc* Expr)
|
|||
{
|
||||
/* Non-zero arithmetics and objects addresses are boolean true */
|
||||
return (ED_IsConstAbsInt (Expr) && Expr->IVal != 0) ||
|
||||
(ED_IsAddrExpr (Expr));
|
||||
ED_IsEntityAddr (Expr);
|
||||
}
|
||||
|
||||
|
||||
|
@ -331,12 +331,41 @@ int ED_IsZPInd (const ExprDesc* Expr)
|
|||
|
||||
|
||||
int ED_IsNullPtr (const ExprDesc* Expr)
|
||||
/* Return true if the given expression is a NULL pointer constant */
|
||||
/* Return true if the given expression is a null pointer.
|
||||
** Note: A null pointer constant converted to a pointer type is a null pointer.
|
||||
*/
|
||||
{
|
||||
return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE)) ==
|
||||
(E_LOC_NONE|E_RTYPE_RVAL) &&
|
||||
Expr->IVal == 0 &&
|
||||
IsClassInt (Expr->Type);
|
||||
return ED_IsConstAbs (Expr) &&
|
||||
Expr->IVal == 0 &&
|
||||
(IsClassInt (Expr->Type) || IsTypePtr (Expr->Type));
|
||||
}
|
||||
|
||||
|
||||
|
||||
int ED_IsNullPtrConstant (const ExprDesc* Expr)
|
||||
/* Return true if the given expression is a null pointer constant.
|
||||
** Note: An integer constant expression with value 0, or such an
|
||||
** expression cast to void* is a null pointer constant. However, a
|
||||
** null pointer constant converted to a pointer type is just a null
|
||||
** pointer, not necessarily a constant in ISO C.
|
||||
*/
|
||||
{
|
||||
return ED_IsConstAbs (Expr) &&
|
||||
Expr->IVal == 0 &&
|
||||
(IsClassInt (Expr->Type) ||
|
||||
(IsTypePtr (Expr->Type) && IsTypeVoid (Expr->Type + 1) &&
|
||||
GetQualifier (Expr->Type + 1) == T_QUAL_NONE));
|
||||
}
|
||||
|
||||
|
||||
|
||||
int ED_IsEntityAddr (const ExprDesc* Expr)
|
||||
/* Return true if the expression denotes the address of an object or function.
|
||||
*/
|
||||
{
|
||||
return ED_IsAddrExpr (Expr) &&
|
||||
Expr->Sym != 0 &&
|
||||
(IsClassPtr (Expr->Type) || IsTypeFunc (Expr->Type));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -582,7 +582,21 @@ int ED_IsZPInd (const ExprDesc* Expr);
|
|||
/* Return true if the expression is located on the zeropage */
|
||||
|
||||
int ED_IsNullPtr (const ExprDesc* Expr);
|
||||
/* Return true if the given expression is a NULL pointer constant */
|
||||
/* Return true if the given expression is a null pointer.
|
||||
** Note: A null pointer constant converted to a pointer type is a null pointer.
|
||||
*/
|
||||
|
||||
int ED_IsNullPtrConstant (const ExprDesc* Expr);
|
||||
/* Return true if the given expression is a null pointer constant.
|
||||
** Note: An integer constant expression with value 0, or such an
|
||||
** expression cast to void* is a null pointer constant. However, a
|
||||
** null pointer constant converted to a pointer type is just a null
|
||||
** pointer, not necessarily a constant in ISO C.
|
||||
*/
|
||||
|
||||
int ED_IsEntityAddr (const ExprDesc* Expr);
|
||||
/* Return true if the expression denotes the address of an object or function.
|
||||
*/
|
||||
|
||||
int ED_IsBool (const ExprDesc* Expr);
|
||||
/* Return true if the expression can be treated as a boolean, that is, it can
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
int enum { a } x;
|
||||
inline enum { b };
|
||||
|
||||
_Static_assert();
|
||||
|
||||
int main(void)
|
||||
{
|
||||
return 0;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
bug1889-missing-identifier.c:3: Error: Identifier or ';' expected after declaration specifiers
|
||||
bug1889-missing-identifier.c:3: Warning: Implicit 'int' is an obsolete feature
|
||||
bug1889-missing-identifier.c:4: Error: Declaration specifier or identifier expected
|
||||
bug1889-missing-identifier.c:6: Error: Expression expected
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
*/
|
||||
|
||||
typedef short return_t;
|
||||
#error /* produce an error */
|
||||
#error This is an/* produce an error */error
|
||||
|
||||
return_t main(int argc, char* argv[])
|
||||
{
|
||||
|
@ -22,3 +22,6 @@ return_t main(int argc, char* argv[])
|
|||
n = 0; /* produce an error */
|
||||
/* produce a warning */
|
||||
}
|
||||
|
||||
int arr[main(0, 0)]; /* produce an error */
|
||||
int b = 0;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
custom-reference-error.c:17: Error: #error
|
||||
custom-reference-error.c:17: Error: #error: This is an error
|
||||
custom-reference-error.c:21: Error: Call to undeclared function 'printf'
|
||||
custom-reference-error.c:22: Error: Undeclared identifier 'n'
|
||||
custom-reference-error.c:24: Warning: Control reaches end of non-void function [-Wreturn-type]
|
||||
custom-reference-error.c:24: Warning: Parameter 'argc' is never used
|
||||
custom-reference-error.c:24: Warning: Parameter 'argv' is never used
|
||||
custom-reference-error.c:26: Error: Constant integer expression expected
|
||||
|
|
71
test/val/nullptr.c
Normal file
71
test/val/nullptr.c
Normal file
|
@ -0,0 +1,71 @@
|
|||
/* Bug # - Pointer compared to null pointer constant */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
unsigned failures;
|
||||
|
||||
struct S {
|
||||
char a[4];
|
||||
} *p;
|
||||
|
||||
#define TEST_NULL(E) \
|
||||
do { \
|
||||
a = (E) == 0 && !(E); \
|
||||
if (!a) \
|
||||
{ \
|
||||
++failures; \
|
||||
printf("failed: " #E " should be null\n"); \
|
||||
} \
|
||||
} while(0);
|
||||
|
||||
#define TEST_NON_NULL(E) \
|
||||
do { \
|
||||
a = (E) != 0 && !!(E) && (E); \
|
||||
if (!a) \
|
||||
{ \
|
||||
++failures; \
|
||||
printf("failed: " #E " should be non-null\n"); \
|
||||
} \
|
||||
} while(0);
|
||||
|
||||
int main()
|
||||
{
|
||||
int a;
|
||||
|
||||
/* Null pointer constant (per ISO C) compared equal to null pointer constant */
|
||||
TEST_NULL((void*)0)
|
||||
|
||||
/* Null pointer compared equal to null pointer constant */
|
||||
TEST_NULL((char*)0)
|
||||
|
||||
/* Null pointer obtained with -> */
|
||||
TEST_NULL(((struct S*)0)->a)
|
||||
|
||||
/* Null pointer obtained with -> */
|
||||
TEST_NULL(p->a)
|
||||
|
||||
/* Null pointer obtained with cast and -> */
|
||||
TEST_NULL(((struct S*)(a = 0))->a)
|
||||
|
||||
/* Null pointer obtained with cast and -> */
|
||||
TEST_NULL((a = 0, ((struct S*)a)->a))
|
||||
|
||||
/* Non-null pointer obtained with cast and -> */
|
||||
TEST_NON_NULL(((struct S*)(long)(a = 0x1234))->a)
|
||||
|
||||
/* Non-null pointer obtained with cast and -> */
|
||||
TEST_NON_NULL((a = 0x1234, ((struct S*)a)->a))
|
||||
|
||||
/* Non-null pointer obtained with cast and -> */
|
||||
TEST_NON_NULL(((struct S*)&a)->a)
|
||||
|
||||
/* Non-null pointer obtained with cast and -> */
|
||||
TEST_NON_NULL(((struct S*)&main)->a)
|
||||
|
||||
if (failures != 0)
|
||||
{
|
||||
printf("failures: %u\n", failures);
|
||||
}
|
||||
|
||||
return failures;
|
||||
}
|
Loading…
Reference in New Issue
Block a user