mirror of
https://github.com/cc65/cc65.git
synced 2025-01-10 03:30:05 +00:00
Some changes in the way, types and type strings are handled.
Check for and honour const in several places: Assignment to const is flagged with an error. Const data is placed in the rodata segment. git-svn-id: svn://svn.cc65.org/cc65/trunk@252 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
5ee8618510
commit
85417b6d1b
@ -37,7 +37,7 @@
|
||||
|
||||
/* common */
|
||||
#include "version.h"
|
||||
|
||||
|
||||
/* cc65 */
|
||||
#include "asmlabel.h"
|
||||
#include "codegen.h"
|
||||
@ -136,7 +136,7 @@ static void Parse (void)
|
||||
|
||||
/* Get the symbol flags */
|
||||
SymFlags = Spec.StorageClass;
|
||||
if (IsFunc (Decl.Type)) {
|
||||
if (IsTypeFunc (Decl.Type)) {
|
||||
SymFlags |= SC_FUNC;
|
||||
} else {
|
||||
if (NeedStorage) {
|
||||
@ -161,19 +161,23 @@ static void Parse (void)
|
||||
* void types in non ANSI mode.
|
||||
*/
|
||||
if (Size == 0) {
|
||||
if (!IsTypeVoid (Decl.Type)) {
|
||||
if (!IsArray (Decl.Type)) {
|
||||
/* Size is unknown and not an array */
|
||||
Error (ERR_UNKNOWN_SIZE);
|
||||
}
|
||||
} else if (ANSI) {
|
||||
/* We cannot declare variables of type void */
|
||||
Error (ERR_ILLEGAL_TYPE);
|
||||
}
|
||||
if (!IsTypeVoid (Decl.Type)) {
|
||||
if (!IsTypeArray (Decl.Type)) {
|
||||
/* Size is unknown and not an array */
|
||||
Error (ERR_UNKNOWN_SIZE);
|
||||
}
|
||||
} else if (ANSI) {
|
||||
/* We cannot declare variables of type void */
|
||||
Error (ERR_ILLEGAL_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Switch to the data segment */
|
||||
g_usedata ();
|
||||
/* Switch to the data or rodata segment */
|
||||
if (IsConst (Decl.Type)) {
|
||||
g_userodata ();
|
||||
} else {
|
||||
g_usedata ();
|
||||
}
|
||||
|
||||
/* Define a label */
|
||||
g_defgloblabel (Entry->Name);
|
||||
@ -215,7 +219,7 @@ static void Parse (void)
|
||||
}
|
||||
|
||||
/* Function declaration? */
|
||||
if (IsFunc (Decl.Type)) {
|
||||
if (IsTypeFunc (Decl.Type)) {
|
||||
|
||||
/* Function */
|
||||
if (!comma) {
|
||||
|
@ -222,45 +222,49 @@ static type PrintTypeComp (FILE* F, type T, type Mask, const char* Name)
|
||||
void PrintType (FILE* F, const type* Type)
|
||||
/* Output translation of type array. */
|
||||
{
|
||||
/* If the first field has const and/or volatile qualifiers, print and
|
||||
* remove them.
|
||||
*/
|
||||
type T = *Type++;
|
||||
T = PrintTypeComp (F, T, T_QUAL_CONST, "const");
|
||||
T = PrintTypeComp (F, T, T_QUAL_VOLATILE, "volatile");
|
||||
type T;
|
||||
|
||||
|
||||
/* Walk over the complete string */
|
||||
do {
|
||||
while ((T = *Type++) != T_END) {
|
||||
|
||||
/* Check for the sizes */
|
||||
T = PrintTypeComp (F, T, T_SIZE_SHORT, "short");
|
||||
T = PrintTypeComp (F, T, T_SIZE_LONG, "long");
|
||||
T = PrintTypeComp (F, T, T_SIZE_LONGLONG, "long long");
|
||||
/* Print any qualifiers */
|
||||
T = PrintTypeComp (F, T, T_QUAL_CONST, "const");
|
||||
T = PrintTypeComp (F, T, T_QUAL_VOLATILE, "volatile");
|
||||
|
||||
/* Signedness */
|
||||
T = PrintTypeComp (F, T, T_SIGN_SIGNED, "signed");
|
||||
T = PrintTypeComp (F, T, T_SIGN_UNSIGNED, "unsigned");
|
||||
/* Signedness */
|
||||
T = PrintTypeComp (F, T, T_SIGN_SIGNED, "signed");
|
||||
T = PrintTypeComp (F, T, T_SIGN_UNSIGNED, "unsigned");
|
||||
|
||||
/* Now check the real type */
|
||||
/* Now check the real type */
|
||||
switch (T & T_MASK_TYPE) {
|
||||
case T_TYPE_CHAR:
|
||||
fprintf (F, "char\n");
|
||||
break;
|
||||
case T_TYPE_INT:
|
||||
fprintf (F, "int\n");
|
||||
break;
|
||||
case T_TYPE_FLOAT:
|
||||
fprintf (F, "float\n");
|
||||
break;
|
||||
case T_TYPE_DOUBLE:
|
||||
fprintf (F, "double\n");
|
||||
break;
|
||||
case T_TYPE_CHAR:
|
||||
fprintf (F, "char\n");
|
||||
break;
|
||||
case T_TYPE_SHORT:
|
||||
fprintf (F, "short\n");
|
||||
break;
|
||||
case T_TYPE_INT:
|
||||
fprintf (F, "int\n");
|
||||
break;
|
||||
case T_TYPE_LONG:
|
||||
fprintf (F, "long\n");
|
||||
break;
|
||||
case T_TYPE_LONGLONG:
|
||||
fprintf (F, "long long\n");
|
||||
break;
|
||||
case T_TYPE_FLOAT:
|
||||
fprintf (F, "float\n");
|
||||
break;
|
||||
case T_TYPE_DOUBLE:
|
||||
fprintf (F, "double\n");
|
||||
break;
|
||||
case T_TYPE_VOID:
|
||||
fprintf (F, "void\n");
|
||||
break;
|
||||
case T_TYPE_STRUCT:
|
||||
fprintf (F, "struct %s\n", ((SymEntry*) DecodePtr (Type))->Name);
|
||||
Type += DECODE_SIZE;
|
||||
break;
|
||||
case T_TYPE_STRUCT:
|
||||
fprintf (F, "struct %s\n", ((SymEntry*) DecodePtr (Type))->Name);
|
||||
Type += DECODE_SIZE;
|
||||
break;
|
||||
case T_TYPE_UNION:
|
||||
fprintf (F, "union %s\n", ((SymEntry*) DecodePtr (Type))->Name);
|
||||
@ -281,10 +285,7 @@ void PrintType (FILE* F, const type* Type)
|
||||
fprintf (F, "unknown type: %04X\n", T);
|
||||
}
|
||||
|
||||
/* Get the next type element */
|
||||
T = *Type++;
|
||||
|
||||
} while (T != T_END);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -345,7 +346,7 @@ void* DecodePtr (const type* Type)
|
||||
int HasEncode (const type* Type)
|
||||
/* Return true if the given type has encoded data */
|
||||
{
|
||||
return IsStruct (Type) || IsArray (Type) || IsFunc (Type);
|
||||
return IsClassStruct (Type) || IsTypeArray (Type) || IsTypeFunc (Type);
|
||||
}
|
||||
|
||||
|
||||
@ -358,15 +359,23 @@ void CopyEncode (const type* Source, type* Target)
|
||||
|
||||
|
||||
|
||||
type UnqualifiedType (type T)
|
||||
/* Return the unqalified type */
|
||||
{
|
||||
return (T & ~T_MASK_QUAL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned SizeOf (const type* T)
|
||||
/* Compute size of object represented by type array. */
|
||||
{
|
||||
SymEntry* Entry;
|
||||
|
||||
switch (*T) {
|
||||
switch (UnqualifiedType (T[0])) {
|
||||
|
||||
case T_VOID:
|
||||
Error (ERR_ILLEGAL_SIZE);
|
||||
case T_VOID:
|
||||
Error (ERR_ILLEGAL_SIZE);
|
||||
return 0;
|
||||
|
||||
case T_SCHAR:
|
||||
@ -419,7 +428,7 @@ unsigned PSizeOf (const type* T)
|
||||
CHECK ((*T & T_CLASS_PTR) != 0);
|
||||
|
||||
/* Skip the pointer or array token itself */
|
||||
if (*T == T_ARRAY) {
|
||||
if (IsTypeArray (T)) {
|
||||
return SizeOf (T + DECODE_SIZE + 1);
|
||||
} else {
|
||||
return SizeOf (T + 1);
|
||||
@ -428,12 +437,12 @@ unsigned PSizeOf (const type* T)
|
||||
|
||||
|
||||
|
||||
unsigned TypeOf (const type* Type)
|
||||
unsigned TypeOf (const type* T)
|
||||
/* Get the code generator base type of the object */
|
||||
{
|
||||
FuncDesc* F;
|
||||
|
||||
switch (*Type) {
|
||||
switch (UnqualifiedType (T[0])) {
|
||||
|
||||
case T_SCHAR:
|
||||
return CF_CHAR;
|
||||
@ -459,7 +468,7 @@ unsigned TypeOf (const type* Type)
|
||||
return CF_LONG | CF_UNSIGNED;
|
||||
|
||||
case T_FUNC:
|
||||
F = DecodePtr (Type+1);
|
||||
F = DecodePtr (T+1);
|
||||
return (F->Flags & FD_ELLIPSIS)? 0 : CF_FIXARGC;
|
||||
|
||||
case T_STRUCT:
|
||||
@ -484,7 +493,7 @@ type* Indirect (type* T)
|
||||
CHECK ((*T & T_MASK_CLASS) == T_CLASS_PTR);
|
||||
|
||||
/* Skip the pointer or array token itself */
|
||||
if (*T == T_ARRAY) {
|
||||
if (IsTypeArray (T)) {
|
||||
return T + DECODE_SIZE + 1;
|
||||
} else {
|
||||
return T + 1;
|
||||
@ -493,15 +502,29 @@ type* Indirect (type* T)
|
||||
|
||||
|
||||
|
||||
int IsTypeVoid (const type* T)
|
||||
/* Return true if this is a void type */
|
||||
int IsConst (const type* T)
|
||||
/* Return true if the given type has a const memory image */
|
||||
{
|
||||
return (T[0] == T_VOID && T[1] == T_END);
|
||||
/* If this is an array, look at the element type, otherwise look at the
|
||||
* type itself.
|
||||
*/
|
||||
if (IsTypeArray (T)) {
|
||||
T += DECODE_SIZE + 1;
|
||||
}
|
||||
return ((T[0] & T_QUAL_CONST) == T_QUAL_CONST);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int IsPtr (const type* T)
|
||||
int IsTypeVoid (const type* T)
|
||||
/* Return true if this is a void type */
|
||||
{
|
||||
return ((T[0] & T_MASK_TYPE) == T_TYPE_VOID && T[1] == T_END);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int IsClassPtr (const type* T)
|
||||
/* Return true if this is a pointer type */
|
||||
{
|
||||
return (T[0] & T_MASK_CLASS) == T_CLASS_PTR;
|
||||
@ -509,7 +532,7 @@ int IsPtr (const type* T)
|
||||
|
||||
|
||||
|
||||
int IsChar (const type* T)
|
||||
int IsTypeChar (const type* T)
|
||||
/* Return true if this is a character type */
|
||||
{
|
||||
return (T[0] & T_MASK_TYPE) == T_TYPE_CHAR && T[1] == T_END;
|
||||
@ -517,7 +540,7 @@ int IsChar (const type* T)
|
||||
|
||||
|
||||
|
||||
int IsInt (const type* T)
|
||||
int IsClassInt (const type* T)
|
||||
/* Return true if this is an integer type */
|
||||
{
|
||||
return (T[0] & T_MASK_CLASS) == T_CLASS_INT;
|
||||
@ -525,10 +548,10 @@ int IsInt (const type* T)
|
||||
|
||||
|
||||
|
||||
int IsLong (const type* T)
|
||||
int IsTypeLong (const type* T)
|
||||
/* Return true if this is a long type (signed or unsigned) */
|
||||
{
|
||||
return (T[0] & T_MASK_SIZE) == T_SIZE_LONG;
|
||||
return (T[0] & T_MASK_TYPE) == T_TYPE_LONG;
|
||||
}
|
||||
|
||||
|
||||
@ -541,7 +564,7 @@ int IsUnsigned (const type* T)
|
||||
|
||||
|
||||
|
||||
int IsStruct (const type* T)
|
||||
int IsClassStruct (const type* T)
|
||||
/* Return true if this is a struct type */
|
||||
{
|
||||
return (T[0] & T_MASK_CLASS) == T_CLASS_STRUCT;
|
||||
@ -549,10 +572,10 @@ int IsStruct (const type* T)
|
||||
|
||||
|
||||
|
||||
int IsFunc (const type* T)
|
||||
/* Return true if this is a function type */
|
||||
int IsTypeFunc (const type* T)
|
||||
/* Return true if this is a function class */
|
||||
{
|
||||
return (T[0] == T_FUNC);
|
||||
return ((T[0] & T_MASK_TYPE) == T_TYPE_FUNC);
|
||||
}
|
||||
|
||||
|
||||
@ -561,25 +584,25 @@ int IsFastCallFunc (const type* T)
|
||||
/* Return true if this is a function type with __fastcall__ calling conventions */
|
||||
{
|
||||
FuncDesc* F;
|
||||
CHECK (T[0] == T_FUNC);
|
||||
CHECK (IsTypeFunc (T));
|
||||
F = DecodePtr (T+1);
|
||||
return (F->Flags & FD_FASTCALL) != 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int IsFuncPtr (const type* T)
|
||||
int IsTypeFuncPtr (const type* T)
|
||||
/* Return true if this is a function pointer */
|
||||
{
|
||||
return (T[0] == T_PTR && T[1] == T_FUNC);
|
||||
return ((T[0] & T_MASK_TYPE) == T_TYPE_PTR && (T[1] & T_MASK_TYPE) == T_TYPE_FUNC);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int IsArray (const type* T)
|
||||
int IsTypeArray (const type* T)
|
||||
/* Return true if this is an array type */
|
||||
{
|
||||
return (T[0] == T_ARRAY);
|
||||
return ((T[0] & T_MASK_TYPE) == T_TYPE_ARRAY);
|
||||
}
|
||||
|
||||
|
||||
|
@ -56,16 +56,19 @@ enum {
|
||||
// Basic types
|
||||
T_TYPE_NONE = 0x0000,
|
||||
T_TYPE_CHAR = 0x0001,
|
||||
T_TYPE_INT = 0x0002,
|
||||
T_TYPE_ENUM = 0x0003,
|
||||
T_TYPE_FLOAT = 0x0004,
|
||||
T_TYPE_DOUBLE = 0x0005,
|
||||
T_TYPE_VOID = 0x0006,
|
||||
T_TYPE_STRUCT = 0x0007,
|
||||
T_TYPE_UNION = 0x0008,
|
||||
T_TYPE_ARRAY = 0x0009,
|
||||
T_TYPE_PTR = 0x000A,
|
||||
T_TYPE_FUNC = 0x000B,
|
||||
T_TYPE_SHORT = 0x0002,
|
||||
T_TYPE_INT = 0x0003,
|
||||
T_TYPE_LONG = 0x0004,
|
||||
T_TYPE_LONGLONG = 0x0005,
|
||||
T_TYPE_ENUM = 0x0006,
|
||||
T_TYPE_FLOAT = 0x0007,
|
||||
T_TYPE_DOUBLE = 0x0008,
|
||||
T_TYPE_VOID = 0x0009,
|
||||
T_TYPE_STRUCT = 0x000A,
|
||||
T_TYPE_UNION = 0x000B,
|
||||
T_TYPE_ARRAY = 0x000C,
|
||||
T_TYPE_PTR = 0x000D,
|
||||
T_TYPE_FUNC = 0x000E,
|
||||
T_MASK_TYPE = 0x001F,
|
||||
|
||||
// Type classes
|
||||
@ -97,26 +100,26 @@ enum {
|
||||
T_MASK_QUAL = 0x3000,
|
||||
|
||||
// Types
|
||||
T_CHAR = T_TYPE_CHAR | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_NONE,
|
||||
T_SCHAR = T_TYPE_CHAR | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_NONE,
|
||||
T_UCHAR = T_TYPE_CHAR | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_NONE,
|
||||
T_SHORT = T_TYPE_INT | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_SHORT,
|
||||
T_USHORT = T_TYPE_INT | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_SHORT,
|
||||
T_INT = T_TYPE_INT | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_NONE,
|
||||
T_UINT = T_TYPE_INT | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_NONE,
|
||||
T_LONG = T_TYPE_INT | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_LONG,
|
||||
T_ULONG = T_TYPE_INT | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_LONG,
|
||||
T_LONGLONG = T_TYPE_INT | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_LONGLONG,
|
||||
T_ULONGLONG = T_TYPE_INT | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_LONGLONG,
|
||||
T_ENUM = T_TYPE_ENUM | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_NONE,
|
||||
T_FLOAT = T_TYPE_FLOAT | T_CLASS_FLOAT | T_SIGN_NONE | T_SIZE_NONE,
|
||||
T_DOUBLE = T_TYPE_DOUBLE | T_CLASS_FLOAT | T_SIGN_NONE | T_SIZE_NONE,
|
||||
T_VOID = T_TYPE_VOID | T_CLASS_NONE | T_SIGN_NONE | T_SIZE_NONE,
|
||||
T_STRUCT = T_TYPE_STRUCT | T_CLASS_STRUCT | T_SIGN_NONE | T_SIZE_NONE,
|
||||
T_UNION = T_TYPE_UNION | T_CLASS_STRUCT | T_SIGN_NONE | T_SIZE_NONE,
|
||||
T_ARRAY = T_TYPE_ARRAY | T_CLASS_PTR | T_SIGN_NONE | T_SIZE_NONE,
|
||||
T_PTR = T_TYPE_PTR | T_CLASS_PTR | T_SIGN_NONE | T_SIZE_NONE,
|
||||
T_FUNC = T_TYPE_FUNC | T_CLASS_FUNC | T_SIGN_NONE | T_SIZE_NONE,
|
||||
T_CHAR = T_TYPE_CHAR | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_NONE,
|
||||
T_SCHAR = T_TYPE_CHAR | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_NONE,
|
||||
T_UCHAR = T_TYPE_CHAR | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_NONE,
|
||||
T_SHORT = T_TYPE_SHORT | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_SHORT,
|
||||
T_USHORT = T_TYPE_SHORT | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_SHORT,
|
||||
T_INT = T_TYPE_INT | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_NONE,
|
||||
T_UINT = T_TYPE_INT | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_NONE,
|
||||
T_LONG = T_TYPE_LONG | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_LONG,
|
||||
T_ULONG = T_TYPE_LONG | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_LONG,
|
||||
T_LONGLONG = T_TYPE_LONGLONG | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_LONGLONG,
|
||||
T_ULONGLONG = T_TYPE_LONGLONG | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_LONGLONG,
|
||||
T_ENUM = T_TYPE_ENUM | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_NONE,
|
||||
T_FLOAT = T_TYPE_FLOAT | T_CLASS_FLOAT | T_SIGN_NONE | T_SIZE_NONE,
|
||||
T_DOUBLE = T_TYPE_DOUBLE | T_CLASS_FLOAT | T_SIGN_NONE | T_SIZE_NONE,
|
||||
T_VOID = T_TYPE_VOID | T_CLASS_NONE | T_SIGN_NONE | T_SIZE_NONE,
|
||||
T_STRUCT = T_TYPE_STRUCT | T_CLASS_STRUCT | T_SIGN_NONE | T_SIZE_NONE,
|
||||
T_UNION = T_TYPE_UNION | T_CLASS_STRUCT | T_SIGN_NONE | T_SIZE_NONE,
|
||||
T_ARRAY = T_TYPE_ARRAY | T_CLASS_PTR | T_SIGN_NONE | T_SIZE_NONE,
|
||||
T_PTR = T_TYPE_PTR | T_CLASS_PTR | T_SIGN_NONE | T_SIZE_NONE,
|
||||
T_FUNC = T_TYPE_FUNC | T_CLASS_FUNC | T_SIGN_NONE | T_SIZE_NONE,
|
||||
|
||||
};
|
||||
|
||||
@ -207,6 +210,9 @@ int HasEncode (const type* Type);
|
||||
void CopyEncode (const type* Source, type* Target);
|
||||
/* Copy encoded data from Source to Target */
|
||||
|
||||
type UnqualifiedType (type T);
|
||||
/* Return the unqalified type */
|
||||
|
||||
unsigned SizeOf (const type* Type);
|
||||
/* Compute size of object represented by type array. */
|
||||
|
||||
@ -221,37 +227,40 @@ type* Indirect (type* Type);
|
||||
* given type points to.
|
||||
*/
|
||||
|
||||
int IsConst (const type* T);
|
||||
/* Return true if the given type has a const memory image */
|
||||
|
||||
int IsTypeVoid (const type* Type);
|
||||
/* Return true if this is a void type */
|
||||
|
||||
int IsPtr (const type* Type);
|
||||
int IsClassPtr (const type* Type);
|
||||
/* Return true if this is a pointer type */
|
||||
|
||||
int IsChar (const type* Type);
|
||||
int IsTypeChar (const type* Type);
|
||||
/* Return true if this is a character type */
|
||||
|
||||
int IsInt (const type* Type);
|
||||
int IsClassInt (const type* Type);
|
||||
/* Return true if this is an integer type */
|
||||
|
||||
int IsLong (const type* Type);
|
||||
int IsTypeLong (const type* Type);
|
||||
/* Return true if this is a long type (signed or unsigned) */
|
||||
|
||||
int IsUnsigned (const type* Type);
|
||||
/* Return true if this is an unsigned type */
|
||||
|
||||
int IsStruct (const type* Type);
|
||||
int IsClassStruct (const type* Type);
|
||||
/* Return true if this is a struct type */
|
||||
|
||||
int IsFunc (const type* Type);
|
||||
/* Return true if this is a function type */
|
||||
int IsTypeFunc (const type* Type);
|
||||
/* Return true if this is a function class */
|
||||
|
||||
int IsFastCallFunc (const type* Type);
|
||||
/* Return true if this is a function type with __fastcall__ calling conventions */
|
||||
|
||||
int IsFuncPtr (const type* Type);
|
||||
int IsTypeFuncPtr (const type* Type);
|
||||
/* Return true if this is a function pointer */
|
||||
|
||||
int IsArray (const type* Type);
|
||||
int IsTypeArray (const type* Type);
|
||||
/* Return true if this is an array type */
|
||||
|
||||
struct FuncDesc* GetFuncDesc (const type* Type);
|
||||
|
@ -11,8 +11,10 @@
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "../common/xmalloc.h"
|
||||
/* common */
|
||||
#include "xmalloc.h"
|
||||
|
||||
/* cc65 */
|
||||
#include "anonname.h"
|
||||
#include "codegen.h"
|
||||
#include "datatype.h"
|
||||
@ -46,13 +48,39 @@ static void ParseTypeSpec (DeclSpec* D, int Default);
|
||||
|
||||
|
||||
|
||||
static void optional_modifiers (void)
|
||||
/* Eat optional "const" or "volatile" tokens */
|
||||
static type OptionalQualifiers (type Q)
|
||||
/* Read type qualifiers if we have any */
|
||||
{
|
||||
while (curtok == TOK_CONST || curtok == TOK_VOLATILE) {
|
||||
/* Skip it */
|
||||
NextToken ();
|
||||
|
||||
switch (curtok) {
|
||||
|
||||
case TOK_CONST:
|
||||
if (Q & T_QUAL_CONST) {
|
||||
Error (ERR_DUPLICATE_QUALIFIER, "const");
|
||||
}
|
||||
Q |= T_QUAL_CONST;
|
||||
break;
|
||||
|
||||
case TOK_VOLATILE:
|
||||
if (Q & T_QUAL_VOLATILE) {
|
||||
Error (ERR_DUPLICATE_QUALIFIER, "volatile");
|
||||
}
|
||||
Q |= T_QUAL_VOLATILE;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Keep gcc silent */
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
/* Skip the token */
|
||||
NextToken ();
|
||||
}
|
||||
|
||||
/* Return the qualifiers read */
|
||||
return Q;
|
||||
}
|
||||
|
||||
|
||||
@ -93,7 +121,7 @@ static void InitDeclaration (Declaration* D)
|
||||
/* Initialize the Declaration struct for use */
|
||||
{
|
||||
D->Ident[0] = '\0';
|
||||
D->Type[0] = T_END;
|
||||
D->Type[0] = T_END;
|
||||
D->T = D->Type;
|
||||
}
|
||||
|
||||
@ -278,15 +306,16 @@ static SymEntry* ParseStructDecl (const char* Name, type StructType)
|
||||
static void ParseTypeSpec (DeclSpec* D, int Default)
|
||||
/* Parse a type specificier */
|
||||
{
|
||||
ident Ident;
|
||||
ident Ident;
|
||||
SymEntry* Entry;
|
||||
type StructType;
|
||||
type Qualifiers; /* Type qualifiers */
|
||||
|
||||
/* Assume we have an explicit type */
|
||||
D->Flags &= ~DS_DEF_TYPE;
|
||||
|
||||
/* Skip const or volatile modifiers if needed */
|
||||
optional_modifiers ();
|
||||
/* Read type qualifiers if we have any */
|
||||
Qualifiers = OptionalQualifiers (T_QUAL_NONE);
|
||||
|
||||
/* Look at the data type */
|
||||
switch (curtok) {
|
||||
@ -306,29 +335,29 @@ static void ParseTypeSpec (DeclSpec* D, int Default)
|
||||
case TOK_LONG:
|
||||
NextToken ();
|
||||
if (curtok == TOK_UNSIGNED) {
|
||||
NextToken ();
|
||||
optionalint ();
|
||||
D->Type[0] = T_ULONG;
|
||||
D->Type[1] = T_END;
|
||||
NextToken ();
|
||||
optionalint ();
|
||||
D->Type[0] = T_ULONG;
|
||||
D->Type[1] = T_END;
|
||||
} else {
|
||||
optionalsigned ();
|
||||
optionalint ();
|
||||
D->Type[0] = T_LONG;
|
||||
D->Type[1] = T_END;
|
||||
optionalsigned ();
|
||||
optionalint ();
|
||||
D->Type[0] = T_LONG;
|
||||
D->Type[1] = T_END;
|
||||
}
|
||||
break;
|
||||
|
||||
case TOK_SHORT:
|
||||
NextToken ();
|
||||
if (curtok == TOK_UNSIGNED) {
|
||||
NextToken ();
|
||||
optionalint ();
|
||||
D->Type[0] = T_USHORT;
|
||||
D->Type[1] = T_END;
|
||||
NextToken ();
|
||||
optionalint ();
|
||||
D->Type[0] = T_USHORT;
|
||||
D->Type[1] = T_END;
|
||||
} else {
|
||||
optionalsigned ();
|
||||
optionalint ();
|
||||
D->Type[0] = T_SHORT;
|
||||
optionalsigned ();
|
||||
optionalint ();
|
||||
D->Type[0] = T_SHORT;
|
||||
D->Type[1] = T_END;
|
||||
}
|
||||
break;
|
||||
@ -480,6 +509,9 @@ static void ParseTypeSpec (DeclSpec* D, int Default)
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* There may also be qualifiers *after* the initial type */
|
||||
D->Type[0] |= OptionalQualifiers (Qualifiers);
|
||||
}
|
||||
|
||||
|
||||
@ -489,7 +521,7 @@ static type* ParamTypeCvt (type* T)
|
||||
* resulting type.
|
||||
*/
|
||||
{
|
||||
if (IsArray (T)) {
|
||||
if (IsTypeArray (T)) {
|
||||
T += DECODE_SIZE;
|
||||
T[0] = T_PTR;
|
||||
}
|
||||
@ -717,12 +749,14 @@ static FuncDesc* ParseFuncDecl (void)
|
||||
static void Decl (Declaration* D, unsigned Mode)
|
||||
/* Recursively process declarators. Build a type array in reverse order. */
|
||||
{
|
||||
|
||||
if (curtok == TOK_STAR) {
|
||||
type T = T_PTR;
|
||||
NextToken ();
|
||||
/* Allow optional const or volatile modifiers */
|
||||
optional_modifiers ();
|
||||
/* Allow optional const or volatile qualifiers */
|
||||
T |= OptionalQualifiers (T_QUAL_NONE);
|
||||
Decl (D, Mode);
|
||||
*D->T++ = T_PTR;
|
||||
*D->T++ = T;
|
||||
return;
|
||||
} else if (curtok == TOK_LPAREN) {
|
||||
NextToken ();
|
||||
@ -736,7 +770,7 @@ static void Decl (Declaration* D, unsigned Mode)
|
||||
/* Parse the function */
|
||||
Decl (D, Mode);
|
||||
/* Set the fastcall flag */
|
||||
if (!IsFunc (T)) {
|
||||
if (!IsTypeFunc (T)) {
|
||||
Error (ERR_ILLEGAL_MODIFIER);
|
||||
} else {
|
||||
FuncDesc* F = DecodePtr (T+1);
|
||||
@ -840,7 +874,7 @@ void ParseDecl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
|
||||
TypeCpy (D->T, Spec->Type);
|
||||
|
||||
/* Check the size of the generated type */
|
||||
if (!IsFunc (D->Type) && !IsTypeVoid (D->Type) && SizeOf (D->Type) >= 0x10000) {
|
||||
if (!IsTypeFunc (D->Type) && !IsTypeVoid (D->Type) && SizeOf (D->Type) >= 0x10000) {
|
||||
Error (ERR_ILLEGAL_SIZE);
|
||||
}
|
||||
}
|
||||
@ -979,10 +1013,8 @@ static void ParseStructInit (type* Type)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void ParseInit (type *tptr)
|
||||
/* Parse initialization of variables */
|
||||
void ParseInit (type* T)
|
||||
/* Parse initialization of variables. */
|
||||
{
|
||||
int count;
|
||||
struct expent lval;
|
||||
@ -990,7 +1022,7 @@ void ParseInit (type *tptr)
|
||||
const char* str;
|
||||
int sz;
|
||||
|
||||
switch (*tptr) {
|
||||
switch (UnqualifiedType (*T)) {
|
||||
|
||||
case T_SCHAR:
|
||||
case T_UCHAR:
|
||||
@ -999,7 +1031,7 @@ void ParseInit (type *tptr)
|
||||
/* Make it byte sized */
|
||||
lval.e_const &= 0xFF;
|
||||
}
|
||||
assignadjust (tptr, &lval);
|
||||
assignadjust (T, &lval);
|
||||
DefineData (&lval);
|
||||
break;
|
||||
|
||||
@ -1013,7 +1045,7 @@ void ParseInit (type *tptr)
|
||||
/* Make it word sized */
|
||||
lval.e_const &= 0xFFFF;
|
||||
}
|
||||
assignadjust (tptr, &lval);
|
||||
assignadjust (T, &lval);
|
||||
DefineData (&lval);
|
||||
break;
|
||||
|
||||
@ -1024,14 +1056,14 @@ void ParseInit (type *tptr)
|
||||
/* Make it long sized */
|
||||
lval.e_const &= 0xFFFFFFFF;
|
||||
}
|
||||
assignadjust (tptr, &lval);
|
||||
assignadjust (T, &lval);
|
||||
DefineData (&lval);
|
||||
break;
|
||||
|
||||
case T_ARRAY:
|
||||
sz = Decode (tptr + 1);
|
||||
t = tptr + DECODE_SIZE + 1;
|
||||
if ((t [0] == T_CHAR || t [0] == T_UCHAR) && curtok == TOK_SCONST) {
|
||||
sz = Decode (T + 1);
|
||||
t = T + DECODE_SIZE + 1;
|
||||
if (IsTypeChar(t) && curtok == TOK_SCONST) {
|
||||
str = GetLiteral (curval);
|
||||
count = strlen (str) + 1;
|
||||
TranslateLiteralPool (curval); /* Translate into target charset */
|
||||
@ -1042,7 +1074,7 @@ void ParseInit (type *tptr)
|
||||
ConsumeLCurly ();
|
||||
count = 0;
|
||||
while (curtok != TOK_RCURLY) {
|
||||
ParseInit (tptr + DECODE_SIZE + 1);
|
||||
ParseInit (T + DECODE_SIZE + 1);
|
||||
++count;
|
||||
if (curtok != TOK_COMMA)
|
||||
break;
|
||||
@ -1051,9 +1083,9 @@ void ParseInit (type *tptr)
|
||||
ConsumeRCurly ();
|
||||
}
|
||||
if (sz == 0) {
|
||||
Encode (tptr + 1, count);
|
||||
Encode (T + 1, count);
|
||||
} else if (count < sz) {
|
||||
g_zerobytes ((sz - count) * SizeOf (tptr + DECODE_SIZE + 1));
|
||||
g_zerobytes ((sz - count) * SizeOf (T + DECODE_SIZE + 1));
|
||||
} else if (count > sz) {
|
||||
Error (ERR_TOO_MANY_INITIALIZERS);
|
||||
}
|
||||
@ -1061,7 +1093,7 @@ void ParseInit (type *tptr)
|
||||
|
||||
case T_STRUCT:
|
||||
case T_UNION:
|
||||
ParseStructInit (tptr);
|
||||
ParseStructInit (T);
|
||||
break;
|
||||
|
||||
case T_VOID:
|
||||
|
@ -74,7 +74,7 @@ void CheckEmptyDecl (const DeclSpec* D);
|
||||
*/
|
||||
|
||||
void ParseInit (type* tptr);
|
||||
/* Parse initialization of variables */
|
||||
/* Parse initialization of variables. */
|
||||
|
||||
|
||||
|
||||
|
@ -135,6 +135,7 @@ static char* ErrMsg [ERR_COUNT-1] = {
|
||||
"Illegal hex digit",
|
||||
"Illegal character constant",
|
||||
"Illegal modifier",
|
||||
"Illegal type qualifier",
|
||||
"Illegal storage class",
|
||||
"Illegal segment name: `%s'",
|
||||
"Division by zero",
|
||||
@ -150,6 +151,8 @@ static char* ErrMsg [ERR_COUNT-1] = {
|
||||
"__fastcall__ is not allowed for C functions",
|
||||
"Variable has unknown size",
|
||||
"Unknown identifier: `%s'",
|
||||
"Duplicate qualifier: `%s'",
|
||||
"Assignment to const",
|
||||
};
|
||||
|
||||
|
||||
|
@ -130,6 +130,7 @@ enum Errors {
|
||||
ERR_ILLEGAL_HEX_DIGIT,
|
||||
ERR_ILLEGAL_CHARCONST,
|
||||
ERR_ILLEGAL_MODIFIER,
|
||||
ERR_ILLEGAL_QUALIFIER,
|
||||
ERR_ILLEGAL_STORAGE_CLASS,
|
||||
ERR_ILLEGAL_SEG_NAME,
|
||||
ERR_DIV_BY_ZERO,
|
||||
@ -145,6 +146,8 @@ enum Errors {
|
||||
ERR_FASTCALL,
|
||||
ERR_UNKNOWN_SIZE,
|
||||
ERR_UNKNOWN_IDENT,
|
||||
ERR_DUPLICATE_QUALIFIER,
|
||||
ERR_CONST_ASSIGN,
|
||||
ERR_COUNT /* Error count */
|
||||
};
|
||||
|
||||
|
123
src/cc65/expr.c
123
src/cc65/expr.c
@ -116,7 +116,7 @@ static unsigned GlobalModeFlags (unsigned flags)
|
||||
static int IsNullPtr (struct expent* lval)
|
||||
/* Return true if this is the NULL pointer constant */
|
||||
{
|
||||
return (IsInt (lval->e_tptr) && /* Is it an int? */
|
||||
return (IsClassInt (lval->e_tptr) && /* Is it an int? */
|
||||
lval->e_flags == E_MCONST && /* Is it constant? */
|
||||
lval->e_const == 0); /* And is it's value zero? */
|
||||
}
|
||||
@ -131,7 +131,7 @@ static type* promoteint (type* lhst, type* rhst)
|
||||
* - If one of the values is unsigned, the result is also unsigned.
|
||||
* - Otherwise the result is an int.
|
||||
*/
|
||||
if (IsLong (lhst) || IsLong (rhst)) {
|
||||
if (IsTypeLong (lhst) || IsTypeLong (rhst)) {
|
||||
if (IsUnsigned (lhst) || IsUnsigned (rhst)) {
|
||||
return type_ulong;
|
||||
} else {
|
||||
@ -209,11 +209,11 @@ unsigned assignadjust (type* lhst, struct expent* rhs)
|
||||
* error message.
|
||||
*/
|
||||
Error (ERR_ILLEGAL_TYPE);
|
||||
} else if (IsInt (lhst)) {
|
||||
if (IsPtr (rhst)) {
|
||||
} else if (IsClassInt (lhst)) {
|
||||
if (IsClassPtr (rhst)) {
|
||||
/* Pointer -> int conversion */
|
||||
Warning (WARN_PTR_TO_INT_CONV);
|
||||
} else if (!IsInt (rhst)) {
|
||||
} else if (!IsClassInt (rhst)) {
|
||||
Error (ERR_INCOMPATIBLE_TYPES);
|
||||
} else {
|
||||
/* Adjust the int types. To avoid manipulation of TOS mark lhs
|
||||
@ -225,8 +225,8 @@ unsigned assignadjust (type* lhst, struct expent* rhs)
|
||||
}
|
||||
return g_typeadjust (TypeOf (lhst) | CF_CONST, flags);
|
||||
}
|
||||
} else if (IsPtr (lhst)) {
|
||||
if (IsPtr (rhst)) {
|
||||
} else if (IsClassPtr (lhst)) {
|
||||
if (IsClassPtr (rhst)) {
|
||||
/* Pointer to pointer assignment is valid, if:
|
||||
* - both point to the same types, or
|
||||
* - the rhs pointer is a void pointer, or
|
||||
@ -237,12 +237,12 @@ unsigned assignadjust (type* lhst, struct expent* rhs)
|
||||
if (!EqualTypes (left, right) && *left != T_VOID && *right != T_VOID) {
|
||||
Error (ERR_INCOMPATIBLE_POINTERS);
|
||||
}
|
||||
} else if (IsInt (rhst)) {
|
||||
} else if (IsClassInt (rhst)) {
|
||||
/* Int to pointer assignment is valid only for constant zero */
|
||||
if ((rhs->e_flags & E_MCONST) == 0 || rhs->e_const != 0) {
|
||||
Warning (WARN_INT_TO_PTR_CONV);
|
||||
}
|
||||
} else if (IsFuncPtr (lhst) && IsFunc(rhst)) {
|
||||
} else if (IsTypeFuncPtr (lhst) && IsTypeFunc(rhst)) {
|
||||
/* Assignment of function to function pointer is allowed, provided
|
||||
* that both functions have the same parameter list.
|
||||
*/
|
||||
@ -785,7 +785,7 @@ static int primary (struct expent* lval)
|
||||
|
||||
/* The symbol is referenced now */
|
||||
Sym->Flags |= SC_REF;
|
||||
if (IsFunc (lval->e_tptr) || IsArray (lval->e_tptr)) {
|
||||
if (IsTypeFunc (lval->e_tptr) || IsTypeArray (lval->e_tptr)) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@ -917,7 +917,7 @@ static int arrayref (int k, struct expent* lval)
|
||||
exprhs (CF_NONE, k, lval);
|
||||
}
|
||||
|
||||
if (IsPtr (tptr1)) {
|
||||
if (IsClassPtr (tptr1)) {
|
||||
|
||||
/* Scale the subscript value according to element size */
|
||||
lval2.e_const *= PSizeOf (tptr1);
|
||||
@ -928,7 +928,7 @@ static int arrayref (int k, struct expent* lval)
|
||||
/* Handle constant base array on stack. Be sure NOT to
|
||||
* handle pointers the same way, this won't work.
|
||||
*/
|
||||
if (IsArray (tptr1) &&
|
||||
if (IsTypeArray (tptr1) &&
|
||||
((lval->e_flags & ~E_MCTYPE) == E_MCONST ||
|
||||
(lval->e_flags & ~E_MCTYPE) == E_MLOCAL ||
|
||||
(lval->e_flags & E_MGLOBAL) != 0 ||
|
||||
@ -950,7 +950,7 @@ static int arrayref (int k, struct expent* lval)
|
||||
/* Done */
|
||||
goto end_array;
|
||||
|
||||
} else if (IsPtr (tptr2 = lval2.e_tptr)) {
|
||||
} else if (IsClassPtr (tptr2 = lval2.e_tptr)) {
|
||||
/* Subscript is pointer, get element type */
|
||||
lval2.e_tptr = Indirect (tptr2);
|
||||
|
||||
@ -975,7 +975,7 @@ static int arrayref (int k, struct expent* lval)
|
||||
exprhs (CF_NONE, l, &lval2);
|
||||
|
||||
tptr2 = lval2.e_tptr;
|
||||
if (IsPtr (tptr1)) {
|
||||
if (IsClassPtr (tptr1)) {
|
||||
|
||||
/* Get the element type */
|
||||
lval->e_tptr = Indirect (tptr1);
|
||||
@ -986,7 +986,7 @@ static int arrayref (int k, struct expent* lval)
|
||||
*/
|
||||
g_scale (CF_INT, SizeOf (lval->e_tptr));
|
||||
|
||||
} else if (IsPtr (tptr2)) {
|
||||
} else if (IsClassPtr (tptr2)) {
|
||||
|
||||
/* Get the element type */
|
||||
lval2.e_tptr = Indirect (tptr2);
|
||||
@ -1065,7 +1065,7 @@ static int arrayref (int k, struct expent* lval)
|
||||
g_inc (CF_INT | CF_UNSIGNED, lval->e_const);
|
||||
} else if (lflags == E_MLOCAL) {
|
||||
/* Base address is a local variable address */
|
||||
if (IsArray (tptr1)) {
|
||||
if (IsTypeArray (tptr1)) {
|
||||
g_addaddr_local (CF_INT, lval->e_const);
|
||||
} else {
|
||||
g_addlocal (CF_PTR, lval->e_const);
|
||||
@ -1074,7 +1074,7 @@ static int arrayref (int k, struct expent* lval)
|
||||
/* Base address is a static variable address */
|
||||
unsigned flags = CF_INT;
|
||||
flags |= GlobalModeFlags (lval->e_flags);
|
||||
if (IsArray (tptr1)) {
|
||||
if (IsTypeArray (tptr1)) {
|
||||
g_addaddr_static (flags, lval->e_name, lval->e_const);
|
||||
} else {
|
||||
g_addstatic (flags, lval->e_name, lval->e_const);
|
||||
@ -1086,7 +1086,7 @@ static int arrayref (int k, struct expent* lval)
|
||||
lval->e_flags = E_MEXPR;
|
||||
end_array:
|
||||
ConsumeRBrack ();
|
||||
return !IsArray (lval->e_tptr);
|
||||
return !IsTypeArray (lval->e_tptr);
|
||||
|
||||
}
|
||||
|
||||
@ -1132,7 +1132,7 @@ static int structref (int k, struct expent* lval)
|
||||
lval->e_flags = E_MEOFFS;
|
||||
}
|
||||
lval->e_tptr = Field->Type;
|
||||
return !IsArray (Field->Type);
|
||||
return !IsTypeArray (Field->Type);
|
||||
}
|
||||
|
||||
|
||||
@ -1162,8 +1162,8 @@ static int hie11 (struct expent *lval)
|
||||
/* Function call. Skip the opening parenthesis */
|
||||
NextToken ();
|
||||
tptr = lval->e_tptr;
|
||||
if (IsFunc (tptr) || IsFuncPtr (tptr)) {
|
||||
if (IsFuncPtr (tptr)) {
|
||||
if (IsTypeFunc (tptr) || IsTypeFuncPtr (tptr)) {
|
||||
if (IsTypeFuncPtr (tptr)) {
|
||||
/* Pointer to function. Handle transparently */
|
||||
exprhs (CF_NONE, k, lval); /* Function pointer to A/X */
|
||||
++lval->e_tptr; /* Skip T_PTR */
|
||||
@ -1179,7 +1179,7 @@ static int hie11 (struct expent *lval)
|
||||
|
||||
} else if (curtok == TOK_DOT) {
|
||||
|
||||
if (!IsStruct (lval->e_tptr)) {
|
||||
if (!IsClassStruct (lval->e_tptr)) {
|
||||
Error (ERR_STRUCT_EXPECTED);
|
||||
}
|
||||
k = structref (0, lval);
|
||||
@ -1474,7 +1474,7 @@ static int hie10 (struct expent* lval)
|
||||
lval->e_const = 0; /* Offset is zero now */
|
||||
}
|
||||
t = lval->e_tptr;
|
||||
if (IsPtr (t)) {
|
||||
if (IsClassPtr (t)) {
|
||||
lval->e_tptr = Indirect (t);
|
||||
} else {
|
||||
Error (ERR_ILLEGAL_INDIRECT);
|
||||
@ -1486,7 +1486,7 @@ static int hie10 (struct expent* lval)
|
||||
k = hie10 (lval);
|
||||
if (k == 0) {
|
||||
/* Allow the & operator with an array */
|
||||
if (!IsArray (lval->e_tptr)) {
|
||||
if (!IsTypeArray (lval->e_tptr)) {
|
||||
Error (ERR_ILLEGAL_ADDRESS);
|
||||
}
|
||||
} else {
|
||||
@ -1566,7 +1566,7 @@ static int hie_internal (GenDesc** ops, /* List of generators */
|
||||
*UsedGen = 1;
|
||||
|
||||
/* All operators that call this function expect an int on the lhs */
|
||||
if (!IsInt (lval->e_tptr)) {
|
||||
if (!IsClassInt (lval->e_tptr)) {
|
||||
Error (ERR_INT_EXPR_EXPECTED);
|
||||
}
|
||||
|
||||
@ -1592,7 +1592,7 @@ static int hie_internal (GenDesc** ops, /* List of generators */
|
||||
rconst = (evalexpr (CF_NONE, hienext, &lval2) == 0);
|
||||
|
||||
/* Check the type of the rhs */
|
||||
if (!IsInt (lval2.e_tptr)) {
|
||||
if (!IsClassInt (lval2.e_tptr)) {
|
||||
Error (ERR_INT_EXPR_EXPECTED);
|
||||
}
|
||||
|
||||
@ -1692,12 +1692,12 @@ static int hie_compare (GenDesc** ops, /* List of generators */
|
||||
rconst = (evalexpr (CF_NONE, hienext, &lval2) == 0);
|
||||
|
||||
/* Make sure, the types are compatible */
|
||||
if (IsInt (lval->e_tptr)) {
|
||||
if (!IsInt (lval2.e_tptr) && !(IsPtr(lval2.e_tptr) && IsNullPtr(lval))) {
|
||||
if (IsClassInt (lval->e_tptr)) {
|
||||
if (!IsClassInt (lval2.e_tptr) && !(IsClassPtr(lval2.e_tptr) && IsNullPtr(lval))) {
|
||||
Error (ERR_INCOMPATIBLE_TYPES);
|
||||
}
|
||||
} else if (IsPtr (lval->e_tptr)) {
|
||||
if (IsPtr (lval2.e_tptr)) {
|
||||
} else if (IsClassPtr (lval->e_tptr)) {
|
||||
if (IsClassPtr (lval2.e_tptr)) {
|
||||
/* Both pointers are allowed in comparison if they point to
|
||||
* the same type, or if one of them is a void pointer.
|
||||
*/
|
||||
@ -1744,7 +1744,7 @@ static int hie_compare (GenDesc** ops, /* List of generators */
|
||||
* operation as char operation. Otherwise the default
|
||||
* promotions are used.
|
||||
*/
|
||||
if (IsChar (lval->e_tptr) && (IsChar (lval2.e_tptr) || rconst)) {
|
||||
if (IsTypeChar (lval->e_tptr) && (IsTypeChar (lval2.e_tptr) || rconst)) {
|
||||
flags |= CF_CHAR;
|
||||
if (IsUnsigned (lval->e_tptr) || IsUnsigned (lval2.e_tptr)) {
|
||||
flags |= CF_UNSIGNED;
|
||||
@ -1818,16 +1818,16 @@ static void parseadd (int k, struct expent* lval)
|
||||
rhst = lval2.e_tptr;
|
||||
|
||||
/* Both expressions are constants. Check for pointer arithmetic */
|
||||
if (IsPtr (lhst) && IsInt (rhst)) {
|
||||
if (IsClassPtr (lhst) && IsClassInt (rhst)) {
|
||||
/* Left is pointer, right is int, must scale rhs */
|
||||
lval->e_const = lval->e_const + lval2.e_const * PSizeOf (lhst);
|
||||
/* Result type is a pointer */
|
||||
} else if (IsInt (lhst) && IsPtr (rhst)) {
|
||||
} else if (IsClassInt (lhst) && IsClassPtr (rhst)) {
|
||||
/* Left is int, right is pointer, must scale lhs */
|
||||
lval->e_const = lval->e_const * PSizeOf (rhst) + lval2.e_const;
|
||||
/* Result type is a pointer */
|
||||
lval->e_tptr = lval2.e_tptr;
|
||||
} else if (IsInt (lhst) && IsInt (rhst)) {
|
||||
} else if (IsClassInt (lhst) && IsClassInt (rhst)) {
|
||||
/* Integer addition */
|
||||
lval->e_const += lval2.e_const;
|
||||
typeadjust (lval, &lval2, 1);
|
||||
@ -1845,18 +1845,18 @@ static void parseadd (int k, struct expent* lval)
|
||||
rhst = lval2.e_tptr;
|
||||
|
||||
/* Check for pointer arithmetic */
|
||||
if (IsPtr (lhst) && IsInt (rhst)) {
|
||||
if (IsClassPtr (lhst) && IsClassInt (rhst)) {
|
||||
/* Left is pointer, right is int, must scale rhs */
|
||||
g_scale (CF_INT, PSizeOf (lhst));
|
||||
/* Operate on pointers, result type is a pointer */
|
||||
flags = CF_PTR;
|
||||
} else if (IsInt (lhst) && IsPtr (rhst)) {
|
||||
} else if (IsClassInt (lhst) && IsClassPtr (rhst)) {
|
||||
/* Left is int, right is pointer, must scale lhs */
|
||||
lval->e_const *= PSizeOf (rhst);
|
||||
/* Operate on pointers, result type is a pointer */
|
||||
flags = CF_PTR;
|
||||
lval->e_tptr = lval2.e_tptr;
|
||||
} else if (IsInt (lhst) && IsInt (rhst)) {
|
||||
} else if (IsClassInt (lhst) && IsClassInt (rhst)) {
|
||||
/* Integer addition */
|
||||
flags = typeadjust (lval, &lval2, 1);
|
||||
} else {
|
||||
@ -1891,18 +1891,18 @@ static void parseadd (int k, struct expent* lval)
|
||||
pop (TypeOf (lval->e_tptr));
|
||||
|
||||
/* Check for pointer arithmetic */
|
||||
if (IsPtr (lhst) && IsInt (rhst)) {
|
||||
if (IsClassPtr (lhst) && IsClassInt (rhst)) {
|
||||
/* Left is pointer, right is int, must scale rhs */
|
||||
lval2.e_const *= PSizeOf (lhst);
|
||||
/* Operate on pointers, result type is a pointer */
|
||||
flags = CF_PTR;
|
||||
} else if (IsInt (lhst) && IsPtr (rhst)) {
|
||||
} else if (IsClassInt (lhst) && IsClassPtr (rhst)) {
|
||||
/* Left is int, right is pointer, must scale lhs (ptr only) */
|
||||
g_scale (CF_INT | CF_CONST, PSizeOf (rhst));
|
||||
/* Operate on pointers, result type is a pointer */
|
||||
flags = CF_PTR;
|
||||
lval->e_tptr = lval2.e_tptr;
|
||||
} else if (IsInt (lhst) && IsInt (rhst)) {
|
||||
} else if (IsClassInt (lhst) && IsClassInt (rhst)) {
|
||||
/* Integer addition */
|
||||
flags = typeadjust (lval, &lval2, 1);
|
||||
} else {
|
||||
@ -1923,12 +1923,12 @@ static void parseadd (int k, struct expent* lval)
|
||||
rhst = lval2.e_tptr;
|
||||
|
||||
/* Check for pointer arithmetic */
|
||||
if (IsPtr (lhst) && IsInt (rhst)) {
|
||||
if (IsClassPtr (lhst) && IsClassInt (rhst)) {
|
||||
/* Left is pointer, right is int, must scale rhs */
|
||||
g_scale (CF_INT, PSizeOf (lhst));
|
||||
/* Operate on pointers, result type is a pointer */
|
||||
flags = CF_PTR;
|
||||
} else if (IsInt (lhst) && IsPtr (rhst)) {
|
||||
} else if (IsClassInt (lhst) && IsClassPtr (rhst)) {
|
||||
/* Left is int, right is pointer, must scale lhs */
|
||||
g_tosint (TypeOf (rhst)); /* Make sure, TOS is int */
|
||||
g_swap (CF_INT); /* Swap TOS and primary */
|
||||
@ -1936,7 +1936,7 @@ static void parseadd (int k, struct expent* lval)
|
||||
/* Operate on pointers, result type is a pointer */
|
||||
flags = CF_PTR;
|
||||
lval->e_tptr = lval2.e_tptr;
|
||||
} else if (IsInt (lhst) && IsInt (rhst)) {
|
||||
} else if (IsClassInt (lhst) && IsClassInt (rhst)) {
|
||||
/* Integer addition */
|
||||
flags = typeadjust (lval, &lval2, 0);
|
||||
} else {
|
||||
@ -2001,11 +2001,11 @@ static void parsesub (int k, struct expent* lval)
|
||||
pop (TypeOf (lhst)); /* Clean up the stack */
|
||||
|
||||
/* Check for pointer arithmetic */
|
||||
if (IsPtr (lhst) && IsInt (rhst)) {
|
||||
if (IsClassPtr (lhst) && IsClassInt (rhst)) {
|
||||
/* Left is pointer, right is int, must scale rhs */
|
||||
lval->e_const -= lval2.e_const * PSizeOf (lhst);
|
||||
/* Operate on pointers, result type is a pointer */
|
||||
} else if (IsPtr (lhst) && IsPtr (rhst)) {
|
||||
} else if (IsClassPtr (lhst) && IsClassPtr (rhst)) {
|
||||
/* Left is pointer, right is pointer, must scale result */
|
||||
if (TypeCmp (Indirect (lhst), Indirect (rhst)) != 0) {
|
||||
Error (ERR_INCOMPATIBLE_POINTERS);
|
||||
@ -2014,7 +2014,7 @@ static void parsesub (int k, struct expent* lval)
|
||||
}
|
||||
/* Operate on pointers, result type is an integer */
|
||||
lval->e_tptr = type_int;
|
||||
} else if (IsInt (lhst) && IsInt (rhst)) {
|
||||
} else if (IsClassInt (lhst) && IsClassInt (rhst)) {
|
||||
/* Integer subtraction */
|
||||
typeadjust (lval, &lval2, 1);
|
||||
lval->e_const -= lval2.e_const;
|
||||
@ -2035,12 +2035,12 @@ static void parsesub (int k, struct expent* lval)
|
||||
RemoveCode (Mark2);
|
||||
pop (TypeOf (lhst));
|
||||
|
||||
if (IsPtr (lhst) && IsInt (rhst)) {
|
||||
if (IsClassPtr (lhst) && IsClassInt (rhst)) {
|
||||
/* Left is pointer, right is int, must scale rhs */
|
||||
lval2.e_const *= PSizeOf (lhst);
|
||||
/* Operate on pointers, result type is a pointer */
|
||||
flags = CF_PTR;
|
||||
} else if (IsPtr (lhst) && IsPtr (rhst)) {
|
||||
} else if (IsClassPtr (lhst) && IsClassPtr (rhst)) {
|
||||
/* Left is pointer, right is pointer, must scale result */
|
||||
if (TypeCmp (Indirect (lhst), Indirect (rhst)) != 0) {
|
||||
Error (ERR_INCOMPATIBLE_POINTERS);
|
||||
@ -2050,7 +2050,7 @@ static void parsesub (int k, struct expent* lval)
|
||||
/* Operate on pointers, result type is an integer */
|
||||
flags = CF_PTR;
|
||||
lval->e_tptr = type_int;
|
||||
} else if (IsInt (lhst) && IsInt (rhst)) {
|
||||
} else if (IsClassInt (lhst) && IsClassInt (rhst)) {
|
||||
/* Integer subtraction */
|
||||
flags = typeadjust (lval, &lval2, 1);
|
||||
} else {
|
||||
@ -2078,12 +2078,12 @@ static void parsesub (int k, struct expent* lval)
|
||||
rhst = lval2.e_tptr;
|
||||
|
||||
/* Check for pointer arithmetic */
|
||||
if (IsPtr (lhst) && IsInt (rhst)) {
|
||||
if (IsClassPtr (lhst) && IsClassInt (rhst)) {
|
||||
/* Left is pointer, right is int, must scale rhs */
|
||||
g_scale (CF_INT, PSizeOf (lhst));
|
||||
/* Operate on pointers, result type is a pointer */
|
||||
flags = CF_PTR;
|
||||
} else if (IsPtr (lhst) && IsPtr (rhst)) {
|
||||
} else if (IsClassPtr (lhst) && IsClassPtr (rhst)) {
|
||||
/* Left is pointer, right is pointer, must scale result */
|
||||
if (TypeCmp (Indirect (lhst), Indirect (rhst)) != 0) {
|
||||
Error (ERR_INCOMPATIBLE_POINTERS);
|
||||
@ -2093,7 +2093,7 @@ static void parsesub (int k, struct expent* lval)
|
||||
/* Operate on pointers, result type is an integer */
|
||||
flags = CF_PTR;
|
||||
lval->e_tptr = type_int;
|
||||
} else if (IsInt (lhst) && IsInt (rhst)) {
|
||||
} else if (IsClassInt (lhst) && IsClassInt (rhst)) {
|
||||
/* Integer subtraction. If the left hand side descriptor says that
|
||||
* the lhs is const, we have to remove this mark, since this is no
|
||||
* longer true, lhs is on stack instead.
|
||||
@ -2409,7 +2409,7 @@ static int hieQuest (struct expent *lval)
|
||||
*/
|
||||
type2 = lval2.e_tptr;
|
||||
type3 = lval3.e_tptr;
|
||||
if (IsInt (type2) && IsInt (type3)) {
|
||||
if (IsClassInt (type2) && IsClassInt (type3)) {
|
||||
|
||||
/* Get common type */
|
||||
rtype = promoteint (type2, type3);
|
||||
@ -2442,17 +2442,17 @@ static int hieQuest (struct expent *lval)
|
||||
labt = 0; /* Mark other label as invalid */
|
||||
}
|
||||
|
||||
} else if (IsPtr (type2) && IsPtr (type3)) {
|
||||
} else if (IsClassPtr (type2) && IsClassPtr (type3)) {
|
||||
/* Must point to same type */
|
||||
if (TypeCmp (Indirect (type2), Indirect (type3)) != 0) {
|
||||
Error (ERR_INCOMPATIBLE_TYPES);
|
||||
}
|
||||
/* Result has the common type */
|
||||
rtype = lval2.e_tptr;
|
||||
} else if (IsPtr (type2) && IsNullPtr (&lval3)) {
|
||||
} else if (IsClassPtr (type2) && IsNullPtr (&lval3)) {
|
||||
/* Result type is pointer, no cast needed */
|
||||
rtype = lval2.e_tptr;
|
||||
} else if (IsNullPtr (&lval2) && IsPtr (type3)) {
|
||||
} else if (IsNullPtr (&lval2) && IsClassPtr (type3)) {
|
||||
/* Result type is pointer, no cast needed */
|
||||
rtype = lval3.e_tptr;
|
||||
} else {
|
||||
@ -2656,11 +2656,16 @@ static void Assignment (struct expent* lval)
|
||||
unsigned flags;
|
||||
type* ltype = lval->e_tptr;
|
||||
|
||||
/* Check for assignment to const */
|
||||
if (IsConst (ltype)) {
|
||||
Error (ERR_CONST_ASSIGN);
|
||||
}
|
||||
|
||||
/* cc65 does not have full support for handling structs by value. Since
|
||||
* assigning structs is one of the more useful operations from this
|
||||
* familiy, allow it here.
|
||||
*/
|
||||
if (IsStruct (ltype)) {
|
||||
if (IsClassStruct (ltype)) {
|
||||
|
||||
/* Bring the address of the lhs into the primary and push it */
|
||||
exprhs (0, 0, lval);
|
||||
@ -2889,7 +2894,7 @@ void intexpr (struct expent* lval)
|
||||
/* Get an integer expression */
|
||||
{
|
||||
expression (lval);
|
||||
if (!IsInt (lval->e_tptr)) {
|
||||
if (!IsClassInt (lval->e_tptr)) {
|
||||
Error (ERR_INT_EXPR_EXPECTED);
|
||||
/* To avoid any compiler errors, make the expression a valid int */
|
||||
lval->e_flags = E_MCONST;
|
||||
@ -2910,7 +2915,7 @@ void boolexpr (struct expent* lval)
|
||||
* the pointer used in a boolean context is also ok (Ootherwise check if it's a pointer
|
||||
* expression.
|
||||
*/
|
||||
if (!IsInt (lval->e_tptr) && !IsPtr (lval->e_tptr)) {
|
||||
if (!IsClassInt (lval->e_tptr) && !IsClassPtr (lval->e_tptr)) {
|
||||
Error (ERR_INT_EXPR_EXPECTED);
|
||||
/* To avoid any compiler errors, make the expression a valid int */
|
||||
lval->e_flags = E_MCONST;
|
||||
|
@ -146,7 +146,7 @@ static void ParseOneDecl (const DeclSpec* Spec)
|
||||
ParseDecl (Spec, &Decl, DM_NEED_IDENT);
|
||||
|
||||
/* Set the correct storage class for functions */
|
||||
if (IsFunc (Decl.Type)) {
|
||||
if (IsTypeFunc (Decl.Type)) {
|
||||
/* Function prototypes are always external */
|
||||
if ((SC & SC_EXTERN) == 0) {
|
||||
Warning (WARN_FUNC_MUST_BE_EXTERN);
|
||||
|
@ -11,8 +11,10 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../common/xmalloc.h"
|
||||
|
||||
/* common */
|
||||
#include "xmalloc.h"
|
||||
|
||||
/* cc65 */
|
||||
#include "asmcode.h"
|
||||
#include "asmlabel.h"
|
||||
#include "codegen.h"
|
||||
@ -298,7 +300,7 @@ static void cascadeswitch (struct expent* eval)
|
||||
|
||||
/* Read the selector expression */
|
||||
constexpr (&lval);
|
||||
if (!IsInt (lval.e_tptr)) {
|
||||
if (!IsClassInt (lval.e_tptr)) {
|
||||
Error (ERR_ILLEGAL_TYPE);
|
||||
}
|
||||
|
||||
@ -456,7 +458,7 @@ static void tableswitch (struct expent* eval)
|
||||
if (curtok == TOK_CASE) {
|
||||
NextToken ();
|
||||
constexpr (&lval);
|
||||
if (!IsInt (lval.e_tptr)) {
|
||||
if (!IsClassInt (lval.e_tptr)) {
|
||||
Error (ERR_ILLEGAL_TYPE);
|
||||
}
|
||||
p->sw_const = lval.e_const;
|
||||
@ -538,7 +540,7 @@ static void doswitch (void)
|
||||
ConsumeLCurly ();
|
||||
|
||||
/* Now decide which sort of switch we will create: */
|
||||
if (IsChar (eval.e_tptr) || (FavourSize == 0 && IsInt (eval.e_tptr))) {
|
||||
if (IsTypeChar (eval.e_tptr) || (FavourSize == 0 && IsClassInt (eval.e_tptr))) {
|
||||
cascadeswitch (&eval);
|
||||
} else {
|
||||
tableswitch (&eval);
|
||||
|
@ -467,7 +467,7 @@ SymEntry* FindStructField (const type* Type, const char* Name)
|
||||
}
|
||||
|
||||
/* Non-structs do not have any struct fields... */
|
||||
if (IsStruct (Type)) {
|
||||
if (IsClassStruct (Type)) {
|
||||
|
||||
const SymTable* Tab;
|
||||
|
||||
@ -664,7 +664,7 @@ SymEntry* AddGlobalSym (const char* Name, type* Type, unsigned Flags)
|
||||
/* Add an external or global symbol to the symbol table and return the entry */
|
||||
{
|
||||
/* Functions must be inserted in the global symbol table */
|
||||
SymTable* Tab = IsFunc (Type)? SymTab0 : SymTab;
|
||||
SymTable* Tab = IsTypeFunc (Type)? SymTab0 : SymTab;
|
||||
|
||||
/* Do we have an entry with this name already? */
|
||||
SymEntry* Entry = FindSymInTable (Tab, Name, HashStr (Name));
|
||||
@ -685,7 +685,7 @@ SymEntry* AddGlobalSym (const char* Name, type* Type, unsigned Flags)
|
||||
* incomplete declaration. Accept this, and if the exsting entry is
|
||||
* incomplete, complete it.
|
||||
*/
|
||||
if (IsArray (Type) && IsArray (EType)) {
|
||||
if (IsTypeArray (Type) && IsTypeArray (EType)) {
|
||||
|
||||
/* Get the array sizes */
|
||||
unsigned Size = Decode (Type + 1);
|
||||
@ -713,7 +713,7 @@ SymEntry* AddGlobalSym (const char* Name, type* Type, unsigned Flags)
|
||||
* contains pointers to the new symbol tables that are needed if
|
||||
* an actual function definition follows.
|
||||
*/
|
||||
if (IsFunc (Type)) {
|
||||
if (IsTypeFunc (Type)) {
|
||||
CopyEncode (Type+1, EType+1);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user