1
0
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:
mrdudz 2022-07-21 02:58:12 +02:00
commit 63dde66519
25 changed files with 244 additions and 96 deletions

View File

@ -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/*.* .

View File

@ -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).

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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");
}

View File

@ -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);

View File

@ -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.

View File

@ -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.

View File

@ -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 */

View File

@ -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;
/*****************************************************************************/

View File

@ -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:

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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 {

View File

@ -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;
}
}

View File

@ -237,5 +237,8 @@ MakeRVal:
/* Set the type of the result */
Expr->Type = ResultType;
/* Propagate from subexpressions */
Expr->Flags |= Expr2.Flags & E_MASK_VIRAL;
}
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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 */

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}