mirror of
https://github.com/cc65/cc65.git
synced 2024-06-18 07:29:36 +00:00
Merge remote-tracking branch 'upstream/master' into fptest
This commit is contained in:
commit
63dde66519
|
@ -102,10 +102,7 @@ jobs:
|
|||
repository: cc65/doc
|
||||
path: doc.git
|
||||
- name: Update the online documents.
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
env
|
||||
cd doc.git
|
||||
rm *.*
|
||||
cp ../html/*.* .
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# About cc65
|
||||
|
||||
cc65 is a complete cross development package for 65(C)02 systems, including
|
||||
a powerful macro assembler, a C compiler, linker, librarian and several
|
||||
a powerful macro assembler, a C compiler, linker, archiver and several
|
||||
other tools. cc65 has C and runtime library support for many of the old 6502 machines.
|
||||
For details look at the [Website](https://cc65.github.io).
|
||||
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
FEATURES {
|
||||
STARTADDRESS: default = $1000;
|
||||
}
|
||||
|
||||
SYMBOLS {
|
||||
__ORIXHDR__: type = import;
|
||||
__STACKSIZE__: type = weak, value = $0800; # 2K stack
|
||||
|
@ -7,7 +11,7 @@ SYMBOLS {
|
|||
MEMORY {
|
||||
ZP: file = "", define = yes, start = $00B0, size = $003A;
|
||||
ORIXHDR: file = %O, type = ro, start = $0000, size = $001F;
|
||||
MAIN: file = %O, define = yes, start = $0800, size = __RAMEND__ - __MAIN_START__;
|
||||
MAIN: file = %O, define = yes, start = %S, size = __RAMEND__ - __MAIN_START__;
|
||||
BSS: file = "", start = __ONCE_RUN__, size = __RAMEND__ - __STACKSIZE__ - __ONCE_RUN__;
|
||||
}
|
||||
SEGMENTS {
|
||||
|
|
|
@ -83,7 +83,6 @@
|
|||
#define TGI_COLOR_YELLOW COLOR_YELLOW
|
||||
#define TGI_COLOR_LIGHTGREEN COLOR_LIGHTGREEN
|
||||
#define TGI_COLOR_GREEN COLOR_GREEN
|
||||
#define TGI_COLOR_DARKBROWN COLOR_DARKBROWN
|
||||
#define TGI_COLOR_PURPLE COLOR_PURPLE
|
||||
#define TGI_COLOR_BLUE COLOR_BLUE
|
||||
#define TGI_COLOR_LIGHTBLUE COLOR_LIGHTBLUE
|
||||
|
|
|
@ -148,7 +148,7 @@ unsigned char __fastcall__ ser_open (const struct ser_params* params);
|
|||
/* "Open" the port by setting the port parameters and enable interrupts. */
|
||||
|
||||
unsigned char ser_close (void);
|
||||
/* "Close" the port. Clear buffers and and disable interrupts. */
|
||||
/* "Close" the port. Clear buffers and disable interrupts. */
|
||||
|
||||
unsigned char __fastcall__ ser_get (char* b);
|
||||
/* Get a character from the serial port. If no characters are available, the
|
||||
|
@ -171,6 +171,3 @@ unsigned char __fastcall__ ser_ioctl (unsigned char code, void* data);
|
|||
|
||||
/* End of serial.h */
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -42,15 +42,18 @@
|
|||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
/*
|
||||
CAUTION: we need to reserve enough space to be able to hold the maximum
|
||||
length string:
|
||||
|
||||
1234567890123456789012345678901234567
|
||||
"Wednesday September ..1 00:00:00 1970"
|
||||
*/
|
||||
|
||||
char* __fastcall__ asctime (const struct tm* timep)
|
||||
{
|
||||
static char buf[26];
|
||||
static char buf[38];
|
||||
|
||||
/* Format into given buffer and return the result */
|
||||
return strftime (buf, sizeof (buf), "%c\n", timep)? buf : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -55,21 +55,6 @@
|
|||
#define FIXME(x)
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* Map a generator function and its attributes to a token */
|
||||
typedef struct GenDesc {
|
||||
token_t Tok; /* Token to map to */
|
||||
unsigned Flags; /* Flags for generator function */
|
||||
void (*Func) (unsigned, unsigned long); /* Generator func */
|
||||
} GenDesc;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
@ -622,6 +607,12 @@ void OpAssign (const GenDesc* Gen, ExprDesc* Expr, const char* Op)
|
|||
/* Normal straight 'op=' */
|
||||
OpAssignArithmetic (Gen, Expr, Op);
|
||||
}
|
||||
|
||||
/* Expression has had side effects */
|
||||
Expr->Flags |= E_SIDE_EFFECTS;
|
||||
|
||||
/* Propagate viral flags */
|
||||
ED_PropagateFrom (Expr, &Expr2);
|
||||
}
|
||||
|
||||
|
||||
|
@ -742,4 +733,10 @@ void OpAddSubAssign (const GenDesc* Gen, ExprDesc *Expr, const char* Op)
|
|||
|
||||
/* Expression is an rvalue in the primary now */
|
||||
ED_FinalizeRValLoad (Expr);
|
||||
|
||||
/* Expression has had side effects */
|
||||
Expr->Flags |= E_SIDE_EFFECTS;
|
||||
|
||||
/* Propagate viral flags */
|
||||
ED_PropagateFrom (Expr, &Expr2);
|
||||
}
|
||||
|
|
|
@ -470,7 +470,8 @@ void g_importstartup (void)
|
|||
|
||||
|
||||
void g_importmainargs (void)
|
||||
/* Forced import of a special symbol that handles arguments to main */
|
||||
/* Forced import of a special symbol that handles arguments to main. This will
|
||||
happen only when the compiler sees a main function that takes arguments. */
|
||||
{
|
||||
AddTextLine ("\t.forceimport\tinitmainargs");
|
||||
}
|
||||
|
|
|
@ -218,14 +218,16 @@ static void Parse (void)
|
|||
** void types in ISO modes.
|
||||
*/
|
||||
if (Size == 0) {
|
||||
if (!IsTypeVoid (Decl.Type)) {
|
||||
if (!IsEmptiableObjectType (Decl.Type)) {
|
||||
if (!IsTypeArray (Decl.Type)) {
|
||||
/* Size is unknown and not an array */
|
||||
Error ("Variable '%s' has unknown size", Decl.Ident);
|
||||
Error ("Cannot initialize variable '%s' of unknown size", Decl.Ident);
|
||||
}
|
||||
} else if (IS_Get (&Standard) != STD_CC65) {
|
||||
/* We cannot declare variables of type void */
|
||||
Error ("Illegal type for variable '%s'", Decl.Ident);
|
||||
Error ("Illegal type '%s' for variable '%s'",
|
||||
GetFullTypeName (Decl.Type),
|
||||
Decl.Ident);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -253,7 +255,7 @@ static void Parse (void)
|
|||
/* We cannot declare variables of type void */
|
||||
Error ("Illegal type for variable '%s'", Decl.Ident);
|
||||
Entry->Flags &= ~(SC_STORAGE | SC_DEF);
|
||||
} else if (Size == 0 && SymIsDef (Entry)) {
|
||||
} else if (Size == 0 && SymIsDef (Entry) && !IsEmptiableObjectType (Decl.Type)) {
|
||||
/* Size is unknown. Is it an array? */
|
||||
if (!IsTypeArray (Decl.Type)) {
|
||||
Error ("Variable '%s' has unknown size", Decl.Ident);
|
||||
|
|
|
@ -805,7 +805,11 @@ unsigned CheckedSizeOf (const Type* T)
|
|||
{
|
||||
unsigned Size = SizeOf (T);
|
||||
if (Size == 0) {
|
||||
Error ("Size of type '%s' is unknown", GetFullTypeName (T));
|
||||
if (HasUnknownSize (T + 1)) {
|
||||
Error ("Size of type '%s' is unknown", GetFullTypeName (T));
|
||||
} else {
|
||||
Error ("Size of type '%s' is 0", GetFullTypeName (T));
|
||||
}
|
||||
Size = SIZEOF_CHAR; /* Don't return zero */
|
||||
}
|
||||
return Size;
|
||||
|
@ -821,7 +825,11 @@ unsigned CheckedPSizeOf (const Type* T)
|
|||
{
|
||||
unsigned Size = PSizeOf (T);
|
||||
if (Size == 0) {
|
||||
Error ("Size of type '%s' is unknown", GetFullTypeName (T + 1));
|
||||
if (HasUnknownSize (T + 1)) {
|
||||
Error ("Pointer to type '%s' of unknown size", GetFullTypeName (T + 1));
|
||||
} else {
|
||||
Error ("Pointer to type '%s' of 0 size", GetFullTypeName (T + 1));
|
||||
}
|
||||
Size = SIZEOF_CHAR; /* Don't return zero */
|
||||
}
|
||||
return Size;
|
||||
|
@ -999,6 +1007,25 @@ const Type* PtrConversion (const Type* T)
|
|||
|
||||
|
||||
|
||||
const Type* StdConversion (const Type* T)
|
||||
/* If the type is a function, convert it to pointer to function. If the
|
||||
** expression is an array, convert it to pointer to first element. If the
|
||||
** type is an integer, do integeral promotion. Otherwise return T.
|
||||
*/
|
||||
{
|
||||
if (IsTypeFunc (T)) {
|
||||
return AddressOf (T);
|
||||
} else if (IsTypeArray (T)) {
|
||||
return AddressOf (GetElementType (T));
|
||||
} else if (IsClassInt (T)) {
|
||||
return IntPromotion (T);
|
||||
} else {
|
||||
return T;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const Type* IntPromotion (const Type* T)
|
||||
/* Apply the integer promotions to T and return the result. The returned type
|
||||
** string may be T if there is no need to change it.
|
||||
|
|
|
@ -368,6 +368,12 @@ const Type* PtrConversion (const Type* T);
|
|||
** return T.
|
||||
*/
|
||||
|
||||
const Type* StdConversion (const Type* T);
|
||||
/* If the type is a function, convert it to pointer to function. If the
|
||||
** expression is an array, convert it to pointer to first element. If the
|
||||
** type is an integer, do integeral promotion. Otherwise return T.
|
||||
*/
|
||||
|
||||
const Type* IntPromotion (const Type* T);
|
||||
/* Apply the integer promotions to T and return the result. The returned type
|
||||
** string may be T if there is no need to change it.
|
||||
|
|
122
src/cc65/expr.c
122
src/cc65/expr.c
|
@ -54,13 +54,6 @@
|
|||
|
||||
|
||||
|
||||
/* Map a generator function and its attributes to a token */
|
||||
typedef struct GenDesc {
|
||||
token_t Tok; /* Token to map to */
|
||||
unsigned Flags; /* Flags for generator function */
|
||||
void (*Func) (unsigned, unsigned long); /* Generator func */
|
||||
} GenDesc;
|
||||
|
||||
/* Descriptors for the operations */
|
||||
static GenDesc GenPASGN = { TOK_PLUS_ASSIGN, GEN_NOPUSH, g_add };
|
||||
static GenDesc GenSASGN = { TOK_MINUS_ASSIGN, GEN_NOPUSH, g_sub };
|
||||
|
@ -255,7 +248,7 @@ static const GenDesc* FindGen (token_t Tok, const GenDesc* Table)
|
|||
/* Find a token in a generator table */
|
||||
{
|
||||
while (Table->Tok != TOK_INVALID) {
|
||||
if (Table->Tok == Tok) {
|
||||
if ((token_t)Table->Tok == Tok) {
|
||||
return Table;
|
||||
}
|
||||
++Table;
|
||||
|
@ -661,6 +654,9 @@ void DoDeferred (unsigned Flags, ExprDesc* Expr)
|
|||
/* Sufficient to pop the processor flags */
|
||||
AddCodeLine ("plp");
|
||||
}
|
||||
|
||||
/* Expression has had side effects */
|
||||
Expr->Flags |= E_SIDE_EFFECTS;
|
||||
}
|
||||
|
||||
|
||||
|
@ -784,9 +780,10 @@ static unsigned FunctionArgList (FuncDesc* Func, int IsFastcall, ExprDesc* ED)
|
|||
} else {
|
||||
|
||||
/* No prototype available. Convert array to "pointer to first
|
||||
** element", and function to "pointer to function".
|
||||
** element", function to "pointer to function" and do integral
|
||||
** promotion if necessary.
|
||||
*/
|
||||
Expr.Type = PtrConversion (Expr.Type);
|
||||
TypeConversion (&Expr, StdConversion (Expr.Type));
|
||||
|
||||
}
|
||||
|
||||
|
@ -834,6 +831,9 @@ static unsigned FunctionArgList (FuncDesc* Func, int IsFastcall, ExprDesc* ED)
|
|||
}
|
||||
}
|
||||
|
||||
/* Propagate viral flags */
|
||||
ED_PropagateFrom (ED, &Expr);
|
||||
|
||||
/* Check for end of argument list */
|
||||
if (CurTok.Tok != TOK_COMMA) {
|
||||
break;
|
||||
|
@ -1076,6 +1076,9 @@ static void FunctionCall (ExprDesc* Expr)
|
|||
}
|
||||
|
||||
Expr->Type = ReturnType;
|
||||
|
||||
/* We assume all function calls had side effects */
|
||||
Expr->Flags |= E_SIDE_EFFECTS;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1145,7 +1148,7 @@ static void Primary (ExprDesc* E)
|
|||
/* output its label */
|
||||
E->Flags = E_RTYPE_RVAL | E_LOC_CODE | E_ADDRESS_OF;
|
||||
E->Name = Entry->V.L.Label;
|
||||
E->Type = NewPointerTo (type_void);
|
||||
E->Type = type_void_p;
|
||||
NextToken ();
|
||||
} else {
|
||||
Error ("Computed gotos are a C extension, not supported with this --standard");
|
||||
|
@ -1285,7 +1288,7 @@ static void Primary (ExprDesc* E)
|
|||
case TOK_ASM:
|
||||
/* ASM statement */
|
||||
AsmStatement ();
|
||||
E->Flags = E_RTYPE_RVAL | E_EVAL_MAYBE_UNUSED;
|
||||
E->Flags = E_RTYPE_RVAL | E_EVAL_MAYBE_UNUSED | E_SIDE_EFFECTS;
|
||||
E->Type = type_void;
|
||||
break;
|
||||
|
||||
|
@ -1670,6 +1673,9 @@ static void PreInc (ExprDesc* Expr)
|
|||
|
||||
/* Result is an expression, no reference */
|
||||
ED_FinalizeRValLoad (Expr);
|
||||
|
||||
/* Expression has had side effects */
|
||||
Expr->Flags |= E_SIDE_EFFECTS;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1697,6 +1703,9 @@ static void PreDec (ExprDesc* Expr)
|
|||
|
||||
/* Result is an expression, no reference */
|
||||
ED_FinalizeRValLoad (Expr);
|
||||
|
||||
/* Expression has had side effects */
|
||||
Expr->Flags |= E_SIDE_EFFECTS;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1733,6 +1742,9 @@ static void PostInc (ExprDesc* Expr)
|
|||
LoadExpr (CF_NONE, Expr);
|
||||
AddCodeLine ("inc %s", ED_GetLabelName (Expr, 0));
|
||||
|
||||
/* Expression has had side effects */
|
||||
Expr->Flags |= E_SIDE_EFFECTS;
|
||||
|
||||
} else {
|
||||
|
||||
if (ED_IsLocPrimaryOrExpr (Expr)) {
|
||||
|
@ -1740,6 +1752,9 @@ static void PostInc (ExprDesc* Expr)
|
|||
/* Do the increment */
|
||||
DoInc (Expr, OA_NEED_OLD);
|
||||
|
||||
/* Expression has had side effects */
|
||||
Expr->Flags |= E_SIDE_EFFECTS;
|
||||
|
||||
} else {
|
||||
|
||||
/* Defer the increment until after the value of this expression is used */
|
||||
|
@ -1783,6 +1798,9 @@ static void PostDec (ExprDesc* Expr)
|
|||
LoadExpr (CF_NONE, Expr);
|
||||
AddCodeLine ("dec %s", ED_GetLabelName (Expr, 0));
|
||||
|
||||
/* Expression has had side effects */
|
||||
Expr->Flags |= E_SIDE_EFFECTS;
|
||||
|
||||
} else {
|
||||
|
||||
if (ED_IsLocPrimaryOrExpr (Expr)) {
|
||||
|
@ -1790,6 +1808,9 @@ static void PostDec (ExprDesc* Expr)
|
|||
/* Do the decrement */
|
||||
DoDec (Expr, OA_NEED_OLD);
|
||||
|
||||
/* Expression has had side effects */
|
||||
Expr->Flags |= E_SIDE_EFFECTS;
|
||||
|
||||
} else {
|
||||
|
||||
/* Defer the decrement until after the value of this expression is used */
|
||||
|
@ -1983,7 +2004,7 @@ void hie10 (ExprDesc* Expr)
|
|||
/* The & operator yields an rvalue address */
|
||||
ED_AddrExpr (Expr);
|
||||
}
|
||||
Expr->Type = NewPointerTo (Expr->Type);
|
||||
Expr->Type = AddressOf (Expr->Type);
|
||||
break;
|
||||
|
||||
case TOK_SIZEOF:
|
||||
|
@ -2336,6 +2357,9 @@ LOG(("hie_internal Expr->Type:%s Expr2->Type:%s\n",
|
|||
/* We have an rvalue in the primary now */
|
||||
ED_FinalizeRValLoad (Expr);
|
||||
}
|
||||
|
||||
/* Propagate viral flags */
|
||||
ED_PropagateFrom (Expr, &Expr2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2368,9 +2392,9 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */
|
|||
Tok = CurTok.Tok;
|
||||
NextToken ();
|
||||
|
||||
/* If lhs is a function, convert it to pointer to function */
|
||||
/* If lhs is a function, convert it to the address of the function */
|
||||
if (IsTypeFunc (Expr->Type)) {
|
||||
Expr->Type = NewPointerTo (Expr->Type);
|
||||
Expr->Type = AddressOf (Expr->Type);
|
||||
}
|
||||
|
||||
/* Get the lhs on stack */
|
||||
|
@ -2391,9 +2415,9 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */
|
|||
/* Get the right hand side */
|
||||
MarkedExprWithCheck (hienext, &Expr2);
|
||||
|
||||
/* If rhs is a function, convert it to pointer to function */
|
||||
/* If rhs is a function, convert it to the address of the function */
|
||||
if (IsTypeFunc (Expr2.Type)) {
|
||||
Expr2.Type = NewPointerTo (Expr2.Type);
|
||||
Expr2.Type = AddressOf (Expr2.Type);
|
||||
}
|
||||
|
||||
/* Check for a numeric constant expression */
|
||||
|
@ -2757,6 +2781,9 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */
|
|||
|
||||
/* Result type is always boolean */
|
||||
Done: Expr->Type = type_bool;
|
||||
|
||||
/* Propagate viral flags */
|
||||
ED_PropagateFrom (Expr, &Expr2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3211,12 +3238,15 @@ static void parseadd (ExprDesc* Expr, int DoArrayRef)
|
|||
Error ("Invalid operands for binary operator '+'");
|
||||
} else {
|
||||
/* Array and function types must be converted to pointer types */
|
||||
Expr->Type = PtrConversion (Expr->Type);
|
||||
Expr->Type = StdConversion (Expr->Type);
|
||||
}
|
||||
}
|
||||
|
||||
/* Condition code not set */
|
||||
ED_MarkAsUntested (Expr);
|
||||
|
||||
/* Propagate viral flags */
|
||||
ED_PropagateFrom (Expr, &Expr2);
|
||||
}
|
||||
|
||||
|
||||
|
@ -3502,10 +3532,13 @@ static void parsesub (ExprDesc* Expr)
|
|||
}
|
||||
|
||||
/* Result type is either a pointer or an integer */
|
||||
Expr->Type = PtrConversion (Expr->Type);
|
||||
Expr->Type = StdConversion (Expr->Type);
|
||||
|
||||
/* Condition code not set */
|
||||
ED_MarkAsUntested (Expr);
|
||||
|
||||
/* Propagate viral flags */
|
||||
ED_PropagateFrom (Expr, &Expr2);
|
||||
}
|
||||
|
||||
|
||||
|
@ -3757,6 +3790,12 @@ static int hieAnd (ExprDesc* Expr, unsigned* TrueLab, int* TrueLabAllocated)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Propagate viral flags */
|
||||
if ((Expr->Flags & E_EVAL_UNEVAL) != E_EVAL_UNEVAL) {
|
||||
ED_PropagateFrom (Expr, &Expr2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Last expression */
|
||||
|
@ -3922,6 +3961,11 @@ static void hieOr (ExprDesc *Expr)
|
|||
}
|
||||
}
|
||||
|
||||
/* Propagate viral flags */
|
||||
if ((Expr->Flags & E_EVAL_UNEVAL) != E_EVAL_UNEVAL) {
|
||||
ED_PropagateFrom (Expr, &Expr2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Convert to bool */
|
||||
|
@ -4213,6 +4257,14 @@ static void hieQuest (ExprDesc* Expr)
|
|||
|
||||
/* Setup the target expression */
|
||||
Expr->Type = ResultType;
|
||||
|
||||
/* Propagate viral flags */
|
||||
if ((Expr2.Flags & E_EVAL_UNEVAL) != E_EVAL_UNEVAL) {
|
||||
ED_PropagateFrom (Expr, &Expr2);
|
||||
}
|
||||
if ((Expr3.Flags & E_EVAL_UNEVAL) != E_EVAL_UNEVAL) {
|
||||
ED_PropagateFrom (Expr, &Expr3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4290,26 +4342,39 @@ void hie0 (ExprDesc *Expr)
|
|||
/* Append deferred inc/dec at sequence point */
|
||||
DoDeferred (SQP_KEEP_NONE, Expr);
|
||||
|
||||
/* If the expression didn't generate code or isn't cast to type void,
|
||||
** emit a warning.
|
||||
/* If the expression has no observable effect and isn't cast to type
|
||||
** void, emit a warning and remove useless code if any.
|
||||
*/
|
||||
GetCodePos (&End);
|
||||
if (!ED_MayHaveNoEffect (Expr) &&
|
||||
CodeRangeIsEmpty (&Start, &End) &&
|
||||
IS_Get (&WarnNoEffect) &&
|
||||
PrevErrorCount == ErrorCount) {
|
||||
Warning ("Expression result unused");
|
||||
if (CodeRangeIsEmpty (&Start, &End) ||
|
||||
(Expr->Flags & E_SIDE_EFFECTS) == 0) {
|
||||
|
||||
if (!ED_MayHaveNoEffect (Expr) &&
|
||||
IS_Get (&WarnNoEffect) &&
|
||||
PrevErrorCount == ErrorCount) {
|
||||
Warning ("Left-hand operand of comma expression has no effect");
|
||||
}
|
||||
|
||||
/* Remove code with no effect */
|
||||
RemoveCode (&Start);
|
||||
}
|
||||
|
||||
PrevErrorCount = ErrorCount;
|
||||
|
||||
/* Remember the current code position */
|
||||
GetCodePos (&Start);
|
||||
|
||||
/* Keep viral flags propagated from subexpressions */
|
||||
Flags |= Expr->Flags & E_MASK_VIRAL;
|
||||
|
||||
/* Reset the expression */
|
||||
ED_Init (Expr);
|
||||
Expr->Flags = Flags;
|
||||
Expr->Flags = Flags & ~E_MASK_VIRAL;
|
||||
NextToken ();
|
||||
hie1 (Expr);
|
||||
|
||||
/* Propagate viral flags */
|
||||
Expr->Flags |= Flags & E_MASK_VIRAL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4371,7 +4436,8 @@ 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 */
|
||||
ED_MakeConstAbsInt (&Expr, 1);
|
||||
Expr.Flags &= E_MASK_RTYPE | E_MASK_KEEP_RESULT;
|
||||
Expr.Flags |= E_LOC_NONE;
|
||||
}
|
||||
|
||||
/* Return by value */
|
||||
|
|
|
@ -26,13 +26,20 @@
|
|||
#define SQP_KEEP_NONE 0x00
|
||||
#define SQP_KEEP_TEST 0x01U
|
||||
#define SQP_KEEP_EAX 0x02U
|
||||
#define SQP_KEEP_EXPR 0x03U /* SQP_KEEP_TEST | SQP_KEEP_EAX */
|
||||
#define SQP_KEEP_EXPR 0x03U /* SQP_KEEP_TEST | SQP_KEEP_EAX */
|
||||
|
||||
/* Generator attributes */
|
||||
#define GEN_NOPUSH 0x01 /* Don't push lhs */
|
||||
#define GEN_COMM 0x02 /* Operator is commutative */
|
||||
#define GEN_NOFUNC 0x04 /* Not allowed for function pointers */
|
||||
|
||||
/* Map a generator function and its attributes to a token */
|
||||
typedef struct GenDesc {
|
||||
long Tok; /* Token to map to */
|
||||
unsigned Flags; /* Flags for generator function */
|
||||
void (*Func) (unsigned, unsigned long); /* Generator func */
|
||||
} GenDesc;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
@ -93,8 +93,7 @@ int ED_IsLocPrimaryOrExpr (const ExprDesc* Expr)
|
|||
int ED_IsIndExpr (const ExprDesc* Expr)
|
||||
/* Check if the expression is a reference to its value */
|
||||
{
|
||||
return (Expr->Flags & E_ADDRESS_OF) == 0 &&
|
||||
!ED_IsLocNone (Expr) && !ED_IsLocPrimary (Expr);
|
||||
return (Expr->Flags & E_ADDRESS_OF) == 0 && !ED_IsLocNone (Expr);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -282,7 +281,7 @@ ExprDesc* ED_AddrExpr (ExprDesc* Expr)
|
|||
|
||||
case E_LOC_EXPR:
|
||||
Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE);
|
||||
Expr->Flags |= E_LOC_PRIMARY | E_RTYPE_RVAL;
|
||||
Expr->Flags |= E_ADDRESS_OF | E_LOC_PRIMARY | E_RTYPE_RVAL;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -125,6 +125,7 @@ enum {
|
|||
E_LOADED = 0x1000, /* Expression is loaded in primary */
|
||||
E_CC_SET = 0x2000, /* Condition codes are set */
|
||||
E_HAVE_MARKS = 0x4000, /* Code marks are valid */
|
||||
E_SIDE_EFFECTS = 0x8000, /* Expression has had side effects */
|
||||
|
||||
/* Optimization hints */
|
||||
E_MASK_NEED = 0x030000,
|
||||
|
@ -181,6 +182,9 @@ enum {
|
|||
/* Expression result must be known to the compiler and generate no code to load */
|
||||
E_EVAL_C_CONST = E_EVAL_COMPILER_KNOWN | E_EVAL_NO_CODE,
|
||||
|
||||
/* Flags to combine from subexpressions */
|
||||
E_MASK_VIRAL = E_SIDE_EFFECTS,
|
||||
|
||||
/* Flags to keep in subexpressions of most operations other than ternary */
|
||||
E_MASK_KEEP_SUBEXPR = E_MASK_EVAL,
|
||||
|
||||
|
@ -467,6 +471,16 @@ INLINE int ED_MayHaveNoEffect (const ExprDesc* Expr)
|
|||
# define ED_MayHaveNoEffect(Expr) (((Expr)->Flags & E_EVAL_MAYBE_UNUSED) == E_EVAL_MAYBE_UNUSED)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE void ED_PropagateFrom (ExprDesc* Expr, const ExprDesc* SubExpr)
|
||||
/* Propagate viral flags from subexpression */
|
||||
{
|
||||
Expr->Flags |= SubExpr->Flags & E_MASK_VIRAL;
|
||||
}
|
||||
#else
|
||||
# define ED_PropagateFrom(Expr, SubExpr) (void)((Expr)->Flags |= (SubExpr)->Flags & E_MASK_VIRAL)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE int ED_IsLocPrimaryOrExpr (const ExprDesc* Expr)
|
||||
/* Return true if the expression is E_LOC_PRIMARY or E_LOC_EXPR */
|
||||
|
@ -493,8 +507,7 @@ INLINE int ED_IsAddrExpr (const ExprDesc* Expr)
|
|||
INLINE int ED_IsIndExpr (const ExprDesc* Expr)
|
||||
/* Check if the expression is a reference to its value */
|
||||
{
|
||||
return (Expr->Flags & E_ADDRESS_OF) == 0 &&
|
||||
!ED_IsLocNone (Expr) && !ED_IsLocPrimary (Expr);
|
||||
return (Expr->Flags & E_ADDRESS_OF) == 0 && !ED_IsLocNone (Expr);
|
||||
}
|
||||
#else
|
||||
int ED_IsIndExpr (const ExprDesc* Expr);
|
||||
|
|
|
@ -101,6 +101,7 @@ static void LoadAddress (unsigned Flags, ExprDesc* Expr)
|
|||
g_leasp (Expr->IVal);
|
||||
break;
|
||||
|
||||
case E_LOC_PRIMARY:
|
||||
case E_LOC_EXPR:
|
||||
if (Expr->IVal != 0) {
|
||||
/* We have an expression in the primary plus a constant
|
||||
|
@ -320,4 +321,8 @@ void LoadExpr (unsigned Flags, struct ExprDesc* Expr)
|
|||
}
|
||||
}
|
||||
|
||||
if (ED_IsLVal (Expr) && IsQualVolatile (Expr->Type)) {
|
||||
/* Expression has had side effects */
|
||||
Expr->Flags |= E_SIDE_EFFECTS;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -180,8 +180,8 @@ static void ParseRegisterDecl (Declaration* Decl, int Reg)
|
|||
Sym->Flags |= SC_REF;
|
||||
}
|
||||
|
||||
/* Cannot allocate a variable of zero size */
|
||||
if (Size == 0) {
|
||||
/* Cannot allocate a variable of unknown size */
|
||||
if (HasUnknownSize (Sym->Type)) {
|
||||
if (IsTypeArray (Decl->Type)) {
|
||||
Error ("Array '%s' has unknown size", Decl->Ident);
|
||||
} else {
|
||||
|
@ -391,8 +391,8 @@ static void ParseAutoDecl (Declaration* Decl)
|
|||
}
|
||||
}
|
||||
|
||||
/* Cannot allocate a variable of zero size */
|
||||
if (Size == 0) {
|
||||
/* Cannot allocate an incomplete variable */
|
||||
if (HasUnknownSize (Sym->Type)) {
|
||||
if (IsTypeArray (Decl->Type)) {
|
||||
Error ("Array '%s' has unknown size", Decl->Ident);
|
||||
} else {
|
||||
|
@ -449,8 +449,8 @@ static void ParseStaticDecl (Declaration* Decl)
|
|||
|
||||
}
|
||||
|
||||
/* Cannot allocate a variable of zero size */
|
||||
if (Size == 0) {
|
||||
/* Cannot allocate an incomplete variable */
|
||||
if (HasUnknownSize (Sym->Type)) {
|
||||
if (IsTypeArray (Decl->Type)) {
|
||||
Error ("Array '%s' has unknown size", Decl->Ident);
|
||||
} else {
|
||||
|
|
|
@ -245,7 +245,7 @@ void AddMacroArg (Macro* M, const char* Arg)
|
|||
for (I = 0; I < CollCount (&M->FormalArgs); ++I) {
|
||||
if (strcmp (CollAtUnchecked (&M->FormalArgs, I), Arg) == 0) {
|
||||
/* Found */
|
||||
Error ("Duplicate macro parameter: '%s'", Arg);
|
||||
PPError ("Duplicate macro parameter: '%s'", Arg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -237,5 +237,8 @@ MakeRVal:
|
|||
|
||||
/* Set the type of the result */
|
||||
Expr->Type = ResultType;
|
||||
|
||||
/* Propagate from subexpressions */
|
||||
Expr->Flags |= Expr2.Flags & E_MASK_VIRAL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -185,6 +185,9 @@ static void ParseArg (ArgDesc* Arg, const Type* Type, ExprDesc* Expr)
|
|||
|
||||
/* Use the type of the argument for the push */
|
||||
Arg->Flags |= TypeOf (Arg->Expr.Type);
|
||||
|
||||
/* Propagate from subexpressions */
|
||||
Expr->Flags |= Arg->Expr.Flags & E_MASK_VIRAL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1365,6 +1368,9 @@ static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
|
|||
ExitPoint:
|
||||
/* We expect the closing brace */
|
||||
ConsumeRParen ();
|
||||
|
||||
/* Propagate from subexpressions */
|
||||
Expr->Flags |= Arg.Flags & E_MASK_VIRAL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1405,4 +1411,7 @@ void HandleStdFunc (int Index, FuncDesc* F, ExprDesc* lval)
|
|||
|
||||
/* Call the handler function */
|
||||
D->Handler (F, lval);
|
||||
|
||||
/* We assume all function calls had side effects */
|
||||
lval->Flags |= E_SIDE_EFFECTS;
|
||||
}
|
||||
|
|
|
@ -609,17 +609,23 @@ static void Statement (int* PendingToken)
|
|||
Expr.Flags |= E_NEED_NONE;
|
||||
Expression0 (&Expr);
|
||||
|
||||
/* If the statement didn't generate code, and is not of type
|
||||
** void, emit a warning.
|
||||
/* If the statement has no observable effect and isn't cast to type
|
||||
** void, emit a warning and remove useless code if any.
|
||||
*/
|
||||
GetCodePos (&End);
|
||||
if (!ED_YetToLoad (&Expr) &&
|
||||
!ED_MayHaveNoEffect (&Expr) &&
|
||||
CodeRangeIsEmpty (&Start, &End) &&
|
||||
IS_Get (&WarnNoEffect) &&
|
||||
PrevErrorCount == ErrorCount) {
|
||||
Warning ("Expression result unused");
|
||||
if (CodeRangeIsEmpty (&Start, &End) ||
|
||||
(Expr.Flags & E_SIDE_EFFECTS) == 0) {
|
||||
|
||||
if (!ED_MayHaveNoEffect (&Expr) &&
|
||||
IS_Get (&WarnNoEffect) &&
|
||||
PrevErrorCount == ErrorCount) {
|
||||
Warning ("Statement has no effect");
|
||||
}
|
||||
|
||||
/* Remove code with no effect */
|
||||
RemoveCode (&Start);
|
||||
}
|
||||
|
||||
CheckSemi (PendingToken);
|
||||
}
|
||||
|
||||
|
|
|
@ -206,7 +206,7 @@ void SwitchStatement (void)
|
|||
|
||||
|
||||
void CaseLabel (void)
|
||||
/* Handle a case sabel */
|
||||
/* Handle a case label */
|
||||
{
|
||||
ExprDesc CaseExpr; /* Case label expression */
|
||||
long Val; /* Case label value */
|
||||
|
|
|
@ -728,6 +728,7 @@ static int HandleSymRedefinition (SymEntry* Entry, const Type* T, unsigned Flags
|
|||
/* New type must be compatible with the composite prototype */
|
||||
if (IsDistinctRedef (E_Type, T, TC_EQUAL, TCF_MASK_QUAL)) {
|
||||
Error ("Conflicting function types for '%s'", Entry->Name);
|
||||
TypeCompatibilityDiagnostic (T, E_Type, 0, "'%s' vs '%s'");
|
||||
Entry = 0;
|
||||
} else {
|
||||
/* Refine the existing composite prototype with this new
|
||||
|
|
|
@ -178,10 +178,10 @@ static void DoConversion (ExprDesc* Expr, const Type* NewType)
|
|||
|
||||
/* Do the integer constant <-> absolute address conversion if necessary */
|
||||
if (IsClassPtr (NewType)) {
|
||||
Expr->Flags &= ~E_LOC_NONE;
|
||||
Expr->Flags &= ~E_MASK_LOC;
|
||||
Expr->Flags |= E_LOC_ABS | E_ADDRESS_OF;
|
||||
} else if (IsClassInt (NewType)) {
|
||||
Expr->Flags &= ~(E_LOC_ABS | E_ADDRESS_OF);
|
||||
Expr->Flags &= ~(E_MASK_LOC | E_ADDRESS_OF);
|
||||
Expr->Flags |= E_LOC_NONE;
|
||||
}
|
||||
|
||||
|
|
|
@ -776,14 +776,20 @@ static void PrintUnresolved (ExpCheckFunc F, void* Data)
|
|||
Import* Imp = E->ImpList;
|
||||
const char* name = GetString (E->Name);
|
||||
while (Imp) {
|
||||
unsigned J;
|
||||
for (J = 0; J < CollCount (&Imp->RefLines); ++J) {
|
||||
const LineInfo* LI = CollConstAt (&Imp->RefLines, J);
|
||||
fprintf (stderr,
|
||||
"%s:%u: Error: Unresolved external '%s'\n",
|
||||
GetSourceName (LI),
|
||||
GetSourceLine (LI),
|
||||
name);
|
||||
unsigned J, count = CollCount (&Imp->RefLines);
|
||||
/* The count is 0 when the import was not added by an input file,
|
||||
but by the compiler itself. */
|
||||
if (count == 0) {
|
||||
fprintf (stderr, "Error: Unresolved external '%s'\n", name);
|
||||
} else {
|
||||
for (J = 0; J < count; ++J) {
|
||||
const LineInfo* LI = CollConstAt (&Imp->RefLines, J);
|
||||
fprintf (stderr,
|
||||
"%s:%u: Error: Unresolved external '%s'\n",
|
||||
GetSourceName (LI),
|
||||
GetSourceLine (LI),
|
||||
name);
|
||||
}
|
||||
}
|
||||
Imp = Imp->Next;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user