Fixed the existing but unused attribute parsing code. Added

__attribute__((noexit)) that may be used to mark functions that won't return.
Added this attribute to the exit() function in stdlib.h.


git-svn-id: svn://svn.cc65.org/cc65/trunk@4372 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
uz 2009-10-18 18:31:02 +00:00
parent 0ce362a69b
commit 5a00b38aab
10 changed files with 270 additions and 173 deletions

View file

@ -109,7 +109,7 @@ int __fastcall__ atexit (void (*exitfunc) (void));
void* __fastcall__ bsearch (const void* key, const void* base, size_t n, void* __fastcall__ bsearch (const void* key, const void* base, size_t n,
size_t size, int (*cmp) (const void*, const void*)); size_t size, int (*cmp) (const void*, const void*));
div_t __fastcall__ div (int numer, int denom); div_t __fastcall__ div (int numer, int denom);
void __fastcall__ exit (int ret); void __fastcall__ exit (int ret) __attribute__ ((noreturn));
char* __fastcall__ getenv (const char* name); char* __fastcall__ getenv (const char* name);
void __fastcall__ qsort (void* base, size_t count, size_t size, void __fastcall__ qsort (void* base, size_t count, size_t size,
int (*compare) (const void*, const void*)); int (*compare) (const void*, const void*));

View file

@ -83,7 +83,6 @@ static void Parse (void)
while (CurTok.Tok != TOK_CEOF) { while (CurTok.Tok != TOK_CEOF) {
DeclSpec Spec; DeclSpec Spec;
Declaration Decl;
/* Check for empty statements */ /* Check for empty statements */
if (CurTok.Tok == TOK_SEMI) { if (CurTok.Tok == TOK_SEMI) {
@ -128,6 +127,8 @@ static void Parse (void)
comma = 0; comma = 0;
while (1) { while (1) {
Declaration Decl;
/* Read the next declaration */ /* Read the next declaration */
ParseDecl (&Spec, &Decl, DM_NEED_IDENT); ParseDecl (&Spec, &Decl, DM_NEED_IDENT);
if (Decl.Ident[0] == '\0') { if (Decl.Ident[0] == '\0') {
@ -168,6 +169,9 @@ static void Parse (void)
/* Add an entry to the symbol table */ /* Add an entry to the symbol table */
Entry = AddGlobalSym (Decl.Ident, Decl.Type, Decl.StorageClass); Entry = AddGlobalSym (Decl.Ident, Decl.Type, Decl.StorageClass);
/* Add declaration attributes */
SymUseAttributes (Entry, &Decl);
/* Reserve storage for the variable if we need to */ /* Reserve storage for the variable if we need to */
if (Decl.StorageClass & SC_STORAGE) { if (Decl.StorageClass & SC_STORAGE) {
@ -334,7 +338,7 @@ void Compile (const char* FileName)
strftime (TimeStr, sizeof (TimeStr), "\"%H:%M:%S\"", TM); strftime (TimeStr, sizeof (TimeStr), "\"%H:%M:%S\"", TM);
DefineTextMacro ("__DATE__", DateStr); DefineTextMacro ("__DATE__", DateStr);
DefineTextMacro ("__TIME__", TimeStr); DefineTextMacro ("__TIME__", TimeStr);
/* Other standard macros */ /* Other standard macros */
/* DefineNumericMacro ("__STDC__", 1); <- not now */ /* DefineNumericMacro ("__STDC__", 1); <- not now */
DefineNumericMacro ("__STDC_HOSTED__", 1); DefineNumericMacro ("__STDC_HOSTED__", 1);

View file

@ -249,9 +249,10 @@ static void InitDeclSpec (DeclSpec* D)
static void InitDeclaration (Declaration* D) static void InitDeclaration (Declaration* D)
/* Initialize the Declaration struct for use */ /* Initialize the Declaration struct for use */
{ {
D->Ident[0] = '\0'; D->Ident[0] = '\0';
D->Type[0].C = T_END; D->Type[0].C = T_END;
D->Index = 0; D->Index = 0;
D->Attributes = 0;
} }
@ -1123,7 +1124,6 @@ static void ParseAnsiParamList (FuncDesc* F)
DeclSpec Spec; DeclSpec Spec;
Declaration Decl; Declaration Decl;
DeclAttr Attr;
/* Allow an ellipsis as last parameter */ /* Allow an ellipsis as last parameter */
if (CurTok.Tok == TOK_ELLIPSIS) { if (CurTok.Tok == TOK_ELLIPSIS) {
@ -1161,8 +1161,8 @@ static void ParseAnsiParamList (FuncDesc* F)
Decl.StorageClass &= ~SC_DEF; Decl.StorageClass &= ~SC_DEF;
} }
/* Parse an attribute ### */ /* Parse attributes for this parameter */
ParseAttribute (&Decl, &Attr); ParseAttribute (&Decl);
/* Create a symbol table entry */ /* Create a symbol table entry */
AddLocalSym (Decl.Ident, ParamTypeCvt (Decl.Type), Decl.StorageClass, 0); AddLocalSym (Decl.Ident, ParamTypeCvt (Decl.Type), Decl.StorageClass, 0);
@ -1195,8 +1195,7 @@ static void ParseAnsiParamList (FuncDesc* F)
/* Print an error if we have unnamed parameters and cc65 extensions /* Print an error if we have unnamed parameters and cc65 extensions
* are disabled. * are disabled.
*/ */
if (IS_Get (&Standard) != STD_CC65 && if (IS_Get (&Standard) != STD_CC65 && (F->Flags & FD_UNNAMED_PARAMS)) {
(F->Flags & FD_UNNAMED_PARAMS) != 0) {
Error ("Parameter name omitted"); Error ("Parameter name omitted");
} }
} }
@ -1204,7 +1203,7 @@ static void ParseAnsiParamList (FuncDesc* F)
static FuncDesc* ParseFuncDecl (void) static FuncDesc* ParseFuncDecl (Declaration* D)
/* Parse the argument list of a function. */ /* Parse the argument list of a function. */
{ {
unsigned Offs; unsigned Offs;
@ -1238,8 +1237,24 @@ static FuncDesc* ParseFuncDecl (void)
/* Parse params */ /* Parse params */
if ((F->Flags & FD_OLDSTYLE) == 0) { if ((F->Flags & FD_OLDSTYLE) == 0) {
/* New style function */ /* New style function */
ParseAnsiParamList (F); ParseAnsiParamList (F);
/* Allow attributes */
ParseAttribute (D);
/* Check if this is a function definition */
if (CurTok.Tok == TOK_LCURLY) {
/* Print an error if we have unnamed parameters and cc65 extensions
* are disabled.
*/
if (IS_Get (&Standard) != STD_CC65 &&
(F->Flags & FD_UNNAMED_PARAMS)) {
Error ("Parameter name omitted");
}
}
} else { } else {
/* Old style function */ /* Old style function */
ParseOldStyleParamList (F); ParseOldStyleParamList (F);
@ -1344,7 +1359,7 @@ static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode)
NextToken (); NextToken ();
/* Parse the function declaration */ /* Parse the function declaration */
F = ParseFuncDecl (); F = ParseFuncDecl (D);
/* We cannot specify fastcall for variadic functions */ /* We cannot specify fastcall for variadic functions */
if ((F->Flags & FD_VARIADIC) && (Qualifiers & T_QUAL_FASTCALL)) { if ((F->Flags & FD_VARIADIC) && (Qualifiers & T_QUAL_FASTCALL)) {

View file

@ -6,10 +6,10 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 1998-2008 Ullrich von Bassewitz */ /* (C) 1998-2009, Ullrich von Bassewitz */
/* Roemerstrasse 52 */ /* Roemerstrasse 52 */
/* D-70794 Filderstadt */ /* D-70794 Filderstadt */
/* EMail: uz@cc65.org */ /* EMail: uz@cc65.org */
/* */ /* */
/* */ /* */
/* This software is provided 'as-is', without any expressed or implied */ /* This software is provided 'as-is', without any expressed or implied */
@ -38,6 +38,9 @@
/* common */
#include "coll.h"
/* cc65 */ /* cc65 */
#include "scanner.h" #include "scanner.h"
#include "symtab.h" #include "symtab.h"
@ -58,9 +61,9 @@
/* Result of ParseDeclSpec */ /* Result of ParseDeclSpec */
typedef struct DeclSpec DeclSpec; typedef struct DeclSpec DeclSpec;
struct DeclSpec { struct DeclSpec {
unsigned StorageClass; /* One of the SC_xxx flags */ unsigned StorageClass; /* One of the SC_xxx flags */
Type Type[MAXTYPELEN]; /* Type of the declaration spec */ Type Type[MAXTYPELEN]; /* Type of the declaration spec */
unsigned Flags; /* Bitmapped flags */ unsigned Flags; /* Bitmapped flags */
}; };
/* Result of ParseDecl */ /* Result of ParseDecl */
@ -68,14 +71,15 @@ typedef struct Declaration Declaration;
struct Declaration { struct Declaration {
unsigned StorageClass; /* A set of SC_xxx flags */ unsigned StorageClass; /* A set of SC_xxx flags */
Type Type[MAXTYPELEN]; /* The type */ Type Type[MAXTYPELEN]; /* The type */
ident Ident; /* The identifier if any, else empty */ ident Ident; /* The identifier, if any*/
Collection* Attributes; /* Attributes if any */
/* Working variables */ /* Working variables */
unsigned Index; /* Used to build Type */ unsigned Index; /* Used to build Type */
}; };
/* Modes for ParseDecl */ /* Modes for ParseDecl */
typedef enum { typedef enum {
DM_NEED_IDENT, /* We must have an identifier */ DM_NEED_IDENT, /* We must have an identifier */
DM_NO_IDENT, /* We won't read an identifier */ DM_NO_IDENT, /* We won't read an identifier */
DM_ACCEPT_IDENT, /* We will accept an id if there is one */ DM_ACCEPT_IDENT, /* We will accept an id if there is one */

View file

@ -6,10 +6,10 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 2000-2002 Ullrich von Bassewitz */ /* (C) 1998-2009, Ullrich von Bassewitz */
/* Wacholderweg 14 */ /* Roemerstrasse 52 */
/* D-70597 Stuttgart */ /* D-70794 Filderstadt */
/* EMail: uz@musoftware.de */ /* EMail: uz@cc65.org */
/* */ /* */
/* */ /* */
/* This software is provided 'as-is', without any expressed or implied */ /* This software is provided 'as-is', without any expressed or implied */
@ -35,12 +35,16 @@
#include <string.h> #include <string.h>
/* common */
#include "xmalloc.h"
/* cc65 */ /* cc65 */
#include "declare.h"
#include "declattr.h"
#include "error.h" #include "error.h"
#include "scanner.h" #include "scanner.h"
#include "symtab.h" #include "symtab.h"
#include "typecmp.h" #include "typecmp.h"
#include "declattr.h"
@ -51,28 +55,46 @@
/* Forwards for attribute handlers */ /* Forwards for attribute handlers */
static void AliasAttr (const Declaration* D, DeclAttr* A); static void NoReturnAttr (Declaration* D);
static void UnusedAttr (const Declaration* D, DeclAttr* A);
static void ZeroPageAttr (const Declaration* D, DeclAttr* A);
/* Attribute table */ /* Attribute table */
typedef struct AttrDesc AttrDesc; typedef struct AttrDesc AttrDesc;
struct AttrDesc { struct AttrDesc {
const char Name[12]; const char Name[15];
void (*Handler) (const Declaration*, DeclAttr*); void (*Handler) (Declaration*);
}; };
static const AttrDesc AttrTable [atCount] = { static const AttrDesc AttrTable [] = {
{ "alias", AliasAttr }, { "__noreturn__", NoReturnAttr },
{ "unused", UnusedAttr }, { "noreturn", NoReturnAttr },
{ "zeropage", ZeroPageAttr },
}; };
/*****************************************************************************/ /*****************************************************************************/
/* Code */ /* Struct DeclAttr */
/*****************************************************************************/
static DeclAttr* NewDeclAttr (DeclAttrType AttrType)
/* Create a new DeclAttr struct and return it */
{
/* Allocate memory */
DeclAttr* A = xmalloc (sizeof (DeclAttr));
/* Initialize the fields */
A->AttrType = AttrType;
/* Return the new struct */
return A;
}
/*****************************************************************************/
/* Helper functions */
/*****************************************************************************/ /*****************************************************************************/
@ -85,7 +107,7 @@ static const AttrDesc* FindAttribute (const char* Attr)
unsigned A; unsigned A;
/* For now do a linear search */ /* For now do a linear search */
for (A = 0; A < atCount; ++A) { for (A = 0; A < sizeof (AttrTable) / sizeof (AttrTable[0]); ++A) {
if (strcmp (Attr, AttrTable[A].Name) == 0) { if (strcmp (Attr, AttrTable[A].Name) == 0) {
/* Found */ /* Found */
return AttrTable + A; return AttrTable + A;
@ -98,72 +120,54 @@ static const AttrDesc* FindAttribute (const char* Attr)
static void AliasAttr (const Declaration* D, DeclAttr* A) static void ErrorSkip (void)
/* Handle the "alias" attribute */
{ {
SymEntry* Sym; /* List of tokens to skip */
static const token_t SkipList[] = { TOK_RPAREN, TOK_SEMI };
/* Comma expected */ /* Skip until closing brace or semicolon */
ConsumeComma (); SkipTokens (SkipList, sizeof (SkipList) / sizeof (SkipList[0]));
/* The next identifier is the name of the alias symbol */ /* If we have a closing brace, read it, otherwise bail out */
if (CurTok.Tok != TOK_IDENT) { if (CurTok.Tok == TOK_RPAREN) {
Error ("Identifier expected"); /* Read the two closing braces */
return; ConsumeRParen ();
ConsumeRParen ();
} }
/* Lookup the symbol for this name, it must exist */
Sym = FindSym (CurTok.Ident);
if (Sym == 0) {
Error ("Unknown identifier: `%s'", CurTok.Ident);
NextToken ();
return;
}
/* Since we have the symbol entry now, skip the name */
NextToken ();
/* Check if the types of the symbols are identical */
if (TypeCmp (D->Type, Sym->Type) < TC_EQUAL) {
/* Types are not identical */
Error ("Incompatible types");
return;
}
/* Attribute is verified, set the stuff in the attribute description */
A->AttrType = atAlias;
A->V.Sym = Sym;
} }
static void UnusedAttr (const Declaration* D attribute ((unused)), DeclAttr* A) static void AddAttr (Declaration* D, DeclAttr* A)
/* Handle the "unused" attribute */ /* Add an attribute to a declaration */
{ {
/* No parameters */ /* Allocate the list if necessary, the add the attribute */
A->AttrType = atUnused; if (D->Attributes == 0) {
D->Attributes = NewCollection ();
}
CollAppend (D->Attributes, A);
} }
static void ZeroPageAttr (const Declaration* D attribute ((unused)), DeclAttr* A) /*****************************************************************************/
/* Handle the "zeropage" attribute */ /* Attribute handling code */
/*****************************************************************************/
void NoReturnAttr (Declaration* D)
/* Parse the "noreturn" attribute */
{ {
/* No parameters */ /* Add the noreturn attribute */
A->AttrType = atZeroPage; AddAttr (D, NewDeclAttr (atNoReturn));
} }
void ParseAttribute (const Declaration* D, DeclAttr* A) void ParseAttribute (Declaration* D)
/* Parse an additional __attribute__ modifier */ /* Parse an additional __attribute__ modifier */
{ {
ident AttrName;
const AttrDesc* Attr;
/* Initialize the attribute description with "no attribute" */
A->AttrType = atNone;
/* Do we have an attribute? */ /* Do we have an attribute? */
if (CurTok.Tok != TOK_ATTRIBUTE) { if (CurTok.Tok != TOK_ATTRIBUTE) {
/* No attribute, bail out */ /* No attribute, bail out */
@ -177,45 +181,59 @@ void ParseAttribute (const Declaration* D, DeclAttr* A)
ConsumeLParen (); ConsumeLParen ();
ConsumeLParen (); ConsumeLParen ();
/* Identifier follows */ /* Read a list of attributes */
if (CurTok.Tok != TOK_IDENT) { while (1) {
Error ("Identifier expected");
/* We should *really* try to recover here, but for now: */ ident AttrName;
return; const AttrDesc* Attr = 0;
/* Identifier follows */
if (CurTok.Tok != TOK_IDENT) {
/* No attribute name */
Error ("Attribute name expected");
/* Skip until end of attribute */
ErrorSkip ();
/* Bail out */
return;
}
/* Map the attribute name to its id, then skip the identifier */
strcpy (AttrName, CurTok.Ident);
Attr = FindAttribute (AttrName);
NextToken ();
/* Did we find a valid attribute? */
if (Attr) {
/* Call the handler */
Attr->Handler (D);
} else {
/* Attribute not known, maybe typo */
Error ("Illegal attribute: `%s'", AttrName);
/* Skip until end of attribute */
ErrorSkip ();
/* Bail out */
return;
}
/* If a comma follows, there's a next attribute. Otherwise this is the
* end of the attribute list.
*/
if (CurTok.Tok != TOK_COMMA) {
break;
}
NextToken ();
} }
/* Map the attribute name to its id, then skip the identifier */ /* The declaration is terminated with two closing braces */
strcpy (AttrName, CurTok.Ident); ConsumeRParen ();
Attr = FindAttribute (AttrName); ConsumeRParen ();
NextToken ();
/* Did we find a valid attribute? */
if (Attr) {
/* Call the handler */
Attr->Handler (D, A);
/* Read the two closing braces */
ConsumeRParen ();
ConsumeRParen ();
} else {
/* List of tokens to skip */
static const token_t SkipList[] = { TOK_LPAREN, TOK_SEMI };
/* Attribute not known, maybe typo */
Error ("Illegal attribute: `%s'", AttrName);
/* Skip until closing brace or semicolon */
SkipTokens (SkipList, sizeof (SkipList) / sizeof (SkipList[0]));
/* If we have a closing brace, read it, otherwise bail out */
if (CurTok.Tok == TOK_LPAREN) {
/* Read the two closing braces */
ConsumeRParen ();
ConsumeRParen ();
}
}
} }

View file

@ -6,10 +6,10 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 2000-2002 Ullrich von Bassewitz */ /* (C) 1998-2009, Ullrich von Bassewitz */
/* Wacholderweg 14 */ /* Roemerstrasse 52 */
/* D-70597 Stuttgart */ /* D-70794 Filderstadt */
/* EMail: uz@musoftware.de */ /* EMail: uz@cc65.org */
/* */ /* */
/* */ /* */
/* This software is provided 'as-is', without any expressed or implied */ /* This software is provided 'as-is', without any expressed or implied */
@ -38,45 +38,38 @@
#include "declare.h"
/*****************************************************************************/ /*****************************************************************************/
/* Data */ /* Data */
/*****************************************************************************/ /*****************************************************************************/
/* Forward */
struct Declaration;
/* Supported attribute types */ /* Supported attribute types */
typedef enum { typedef enum {
atNone = -1, /* No attribute */ atNone = -1, /* No attribute */
atAlias, /* Alias declaration */ atNoReturn, /* Function does not return */
atUnused, /* Variable is unused */
atZeroPage, /* Zero page symbol */
atCount /* Number of attributes */ atCount /* Number of attributes */
} attrib_t; } DeclAttrType;
/* An actual attribute description */ /* An actual attribute description */
typedef struct DeclAttr DeclAttr; typedef struct DeclAttr DeclAttr;
struct DeclAttr { struct DeclAttr {
attrib_t AttrType; /* Type of attribute */ DeclAttrType AttrType; /* Type of attribute */
union {
struct SymEntry* Sym; /* Symbol for alias */
} V;
}; };
/*****************************************************************************/ /*****************************************************************************/
/* Code */ /* Code */
/*****************************************************************************/ /*****************************************************************************/
void ParseAttribute (const Declaration* D, DeclAttr* A); void ParseAttribute (struct Declaration* D);
/* Parse an additional __attribute__ modifier */ /* Parse an additional __attribute__ modifier */

View file

@ -486,6 +486,12 @@ static void FunctionCall (ExprDesc* Expr)
} }
} else { } else {
/* Check function attributes */
if (Expr->Sym && SymGetAttribute (Expr->Sym, atNoReturn)) {
/* For now, handle as if a return statement was encountered */
F_ReturnFound (CurrentFunc);
}
/* Check for known standard functions and inline them */ /* Check for known standard functions and inline them */
if (Expr->Name != 0) { if (Expr->Name != 0) {
int StdFunc = FindStdFunc ((const char*) Expr->Name); int StdFunc = FindStdFunc ((const char*) Expr->Name);

View file

@ -40,6 +40,8 @@
/* cc65 */ /* cc65 */
#include "anonname.h" #include "anonname.h"
#include "declare.h"
#include "error.h"
#include "symentry.h" #include "symentry.h"
@ -67,6 +69,7 @@ SymEntry* NewSymEntry (const char* Name, unsigned Flags)
E->Owner = 0; E->Owner = 0;
E->Flags = Flags; E->Flags = Flags;
E->Type = 0; E->Type = 0;
E->Attr = 0;
E->AsmName = 0; E->AsmName = 0;
memcpy (E->Name, Name, Len+1); memcpy (E->Name, Name, Len+1);
@ -150,6 +153,49 @@ void DumpSymEntry (FILE* F, const SymEntry* E)
const DeclAttr* SymGetAttribute (const SymEntry* Sym, DeclAttrType AttrType)
/* Return an attribute for this symbol or NULL if the attribute does not exist */
{
/* Beware: We may not even have a collection */
if (Sym->Attr) {
unsigned I;
for (I = 0; I < CollCount (Sym->Attr); ++I) {
/* Get the next attribute */
const DeclAttr* A = CollConstAt (Sym->Attr, I);
/* If this is the one we're searching for, return it */
if (A->AttrType == AttrType) {
return A;
}
}
}
/* Not found */
return 0;
}
void SymUseAttributes (SymEntry* Sym, struct Declaration* D)
/* Use the attributes from the declaration for this symbol */
{
/* We cannot specify attributes twice */
if ((Sym->Flags & SC_HAVEATTR) != 0) {
if (D->Attributes != 0) {
Error ("Attributes must be specified in the first declaration");
}
return;
}
/* Move the attributes */
Sym->Attr = D->Attributes;
D->Attributes = 0;
Sym->Flags |= SC_HAVEATTR;
}
void CvtRegVarToAuto (SymEntry* Sym) void CvtRegVarToAuto (SymEntry* Sym)
/* Convert a register variable to an auto variable */ /* Convert a register variable to an auto variable */
{ {

View file

@ -6,10 +6,10 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 2000-2009 Ullrich von Bassewitz */ /* (C) 2000-2009, Ullrich von Bassewitz */
/* Roemerstrasse 52 */ /* Roemerstrasse 52 */
/* D-70794 Filderstadt */ /* D-70794 Filderstadt */
/* EMail: uz@cc65.org */ /* EMail: uz@cc65.org */
/* */ /* */
/* */ /* */
/* This software is provided 'as-is', without any expressed or implied */ /* This software is provided 'as-is', without any expressed or implied */
@ -41,10 +41,12 @@
#include <stdio.h> #include <stdio.h>
/* common */ /* common */
#include "coll.h"
#include "inline.h" #include "inline.h"
/* cc65 */ /* cc65 */
#include "datatype.h" #include "datatype.h"
#include "declattr.h"
@ -65,31 +67,33 @@ struct Segments;
/* Storage classes and flags */ /* Storage classes and flags */
#define SC_AUTO 0x0001U #define SC_AUTO 0x0001U /* Auto variable */
#define SC_REGISTER 0x0002U /* Register variable, is in static storage */ #define SC_REGISTER 0x0002U /* Register variable */
#define SC_STATIC 0x0004U #define SC_STATIC 0x0004U /* Static */
#define SC_EXTERN 0x0008U #define SC_EXTERN 0x0008U /* Extern linkage */
#define SC_ENUM 0x0030U /* An enum (numeric constant) */ #define SC_ENUM 0x0030U /* An enum */
#define SC_CONST 0x0020U /* A numeric constant with a type */ #define SC_CONST 0x0020U /* A numeric constant with a type */
#define SC_LABEL 0x0040U /* A goto label */ #define SC_LABEL 0x0040U /* A goto label */
#define SC_PARAM 0x0080U /* This is a function parameter */ #define SC_PARAM 0x0080U /* A function parameter */
#define SC_FUNC 0x0100U /* Function entry */ #define SC_FUNC 0x0100U /* A function */
#define SC_DEFTYPE 0x0200U /* Parameter has default type (=int, old style) */ #define SC_DEFTYPE 0x0200U /* Parameter has default type (=int, old style) */
#define SC_STORAGE 0x0400U /* Symbol with associated storage */ #define SC_STORAGE 0x0400U /* Symbol with associated storage */
#define SC_DEFAULT 0x0800U /* Flag: default storage class was used */ #define SC_DEFAULT 0x0800U /* Flag: default storage class was used */
#define SC_DEF 0x1000U /* Symbol is defined */ #define SC_DEF 0x1000U /* Symbol is defined */
#define SC_REF 0x2000U /* Symbol is referenced */ #define SC_REF 0x2000U /* Symbol is referenced */
#define SC_TYPE 0x4000U /* This is a type, struct, typedef, etc. */ #define SC_TYPE 0x4000U /* This is a type, struct, typedef, etc. */
#define SC_STRUCT 0x4001U /* Struct or union */ #define SC_STRUCT 0x4001U /* Struct or union */
#define SC_STRUCTFIELD 0x4002U /* Struct or union field */ #define SC_STRUCTFIELD 0x4002U /* Struct or union field */
#define SC_BITFIELD 0x4004U /* A bit-field inside a struct or union */ #define SC_BITFIELD 0x4004U /* A bit-field inside a struct or union */
#define SC_TYPEDEF 0x4008U /* A typedef */ #define SC_TYPEDEF 0x4008U /* A typedef */
#define SC_ZEROPAGE 0x8000U /* Symbol marked as zeropage */ #define SC_ZEROPAGE 0x8000U /* Symbol marked as zeropage */
#define SC_HAVEATTR 0x10000U /* Symbol has attributes */
@ -103,6 +107,7 @@ struct SymEntry {
struct SymTable* Owner; /* Symbol table the symbol is in */ struct SymTable* Owner; /* Symbol table the symbol is in */
unsigned Flags; /* Symbol flags */ unsigned Flags; /* Symbol flags */
Type* Type; /* Symbol type */ Type* Type; /* Symbol type */
Collection* Attr; /* Attribute list if any */
char* AsmName; /* Assembler name if any */ char* AsmName; /* Assembler name if any */
/* Data that differs for the different symbol types */ /* Data that differs for the different symbol types */
@ -226,6 +231,12 @@ INLINE const char* SymGetAsmName (const SymEntry* Sym)
# define SymGetAsmName(Sym) ((Sym)->AsmName) # define SymGetAsmName(Sym) ((Sym)->AsmName)
#endif #endif
const DeclAttr* SymGetAttribute (const SymEntry* Sym, DeclAttrType AttrType);
/* Return an attribute for this symbol or NULL if the attribute does not exist */
void SymUseAttributes (SymEntry* Sym, struct Declaration* D);
/* Use the attributes from the declaration for this symbol */
void CvtRegVarToAuto (SymEntry* Sym); void CvtRegVarToAuto (SymEntry* Sym);
/* Convert a register variable to an auto variable */ /* Convert a register variable to an auto variable */

View file

@ -181,7 +181,7 @@ static void CheckSymTable (SymTable* Tab)
/* Undefined label */ /* Undefined label */
Error ("Undefined label: `%s'", Entry->Name); Error ("Undefined label: `%s'", Entry->Name);
} else if (!SymIsRef (Entry)) { } else if (!SymIsRef (Entry)) {
/* Defined but not used */ /* Defined but not used */
if (IS_Get (&WarnUnusedLabel)) { if (IS_Get (&WarnUnusedLabel)) {
Warning ("`%s' is defined but never used", Entry->Name); Warning ("`%s' is defined but never used", Entry->Name);
} }
@ -768,7 +768,7 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags)
TypeCmp (T + 1, EType + 1) < TC_EQUAL) { TypeCmp (T + 1, EType + 1) < TC_EQUAL) {
/* Types not identical: Conflicting types */ /* Types not identical: Conflicting types */
Error ("Conflicting types for `%s'", Name); Error ("Conflicting types for `%s'", Name);
return Entry; return Entry;
} else { } else {
/* Check if we have a size in the existing definition */ /* Check if we have a size in the existing definition */
if (ESize == UNSPECIFIED) { if (ESize == UNSPECIFIED) {
@ -781,7 +781,7 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags)
/* New type must be identical */ /* New type must be identical */
if (TypeCmp (EType, T) < TC_EQUAL) { if (TypeCmp (EType, T) < TC_EQUAL) {
Error ("Conflicting types for `%s'", Name); Error ("Conflicting types for `%s'", Name);
return Entry; return Entry;
} }
/* In case of a function, use the new type descriptor, since it /* In case of a function, use the new type descriptor, since it
@ -791,9 +791,9 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags)
* empty parameter list. * empty parameter list.
*/ */
if (IsFunc) { if (IsFunc) {
/* Get the function descriptor from the new type */ /* Get the function descriptor from the new type */
FuncDesc* F = GetFuncDesc (T); FuncDesc* F = GetFuncDesc (T);
/* Use this new function descriptor if it doesn't contain /* Use this new function descriptor if it doesn't contain
* an empty parameter list. * an empty parameter list.
*/ */
if ((F->Flags & FD_EMPTY) == 0) { if ((F->Flags & FD_EMPTY) == 0) {