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:
parent
0ce362a69b
commit
5a00b38aab
10 changed files with 270 additions and 173 deletions
|
@ -109,7 +109,7 @@ int __fastcall__ atexit (void (*exitfunc) (void));
|
|||
void* __fastcall__ bsearch (const void* key, const void* base, size_t n,
|
||||
size_t size, int (*cmp) (const void*, const void*));
|
||||
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);
|
||||
void __fastcall__ qsort (void* base, size_t count, size_t size,
|
||||
int (*compare) (const void*, const void*));
|
||||
|
|
|
@ -83,7 +83,6 @@ static void Parse (void)
|
|||
while (CurTok.Tok != TOK_CEOF) {
|
||||
|
||||
DeclSpec Spec;
|
||||
Declaration Decl;
|
||||
|
||||
/* Check for empty statements */
|
||||
if (CurTok.Tok == TOK_SEMI) {
|
||||
|
@ -128,6 +127,8 @@ static void Parse (void)
|
|||
comma = 0;
|
||||
while (1) {
|
||||
|
||||
Declaration Decl;
|
||||
|
||||
/* Read the next declaration */
|
||||
ParseDecl (&Spec, &Decl, DM_NEED_IDENT);
|
||||
if (Decl.Ident[0] == '\0') {
|
||||
|
@ -168,6 +169,9 @@ static void Parse (void)
|
|||
/* Add an entry to the symbol table */
|
||||
Entry = AddGlobalSym (Decl.Ident, Decl.Type, Decl.StorageClass);
|
||||
|
||||
/* Add declaration attributes */
|
||||
SymUseAttributes (Entry, &Decl);
|
||||
|
||||
/* Reserve storage for the variable if we need to */
|
||||
if (Decl.StorageClass & SC_STORAGE) {
|
||||
|
||||
|
@ -334,7 +338,7 @@ void Compile (const char* FileName)
|
|||
strftime (TimeStr, sizeof (TimeStr), "\"%H:%M:%S\"", TM);
|
||||
DefineTextMacro ("__DATE__", DateStr);
|
||||
DefineTextMacro ("__TIME__", TimeStr);
|
||||
|
||||
|
||||
/* Other standard macros */
|
||||
/* DefineNumericMacro ("__STDC__", 1); <- not now */
|
||||
DefineNumericMacro ("__STDC_HOSTED__", 1);
|
||||
|
|
|
@ -249,9 +249,10 @@ static void InitDeclSpec (DeclSpec* D)
|
|||
static void InitDeclaration (Declaration* D)
|
||||
/* Initialize the Declaration struct for use */
|
||||
{
|
||||
D->Ident[0] = '\0';
|
||||
D->Type[0].C = T_END;
|
||||
D->Index = 0;
|
||||
D->Ident[0] = '\0';
|
||||
D->Type[0].C = T_END;
|
||||
D->Index = 0;
|
||||
D->Attributes = 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1123,7 +1124,6 @@ static void ParseAnsiParamList (FuncDesc* F)
|
|||
|
||||
DeclSpec Spec;
|
||||
Declaration Decl;
|
||||
DeclAttr Attr;
|
||||
|
||||
/* Allow an ellipsis as last parameter */
|
||||
if (CurTok.Tok == TOK_ELLIPSIS) {
|
||||
|
@ -1161,8 +1161,8 @@ static void ParseAnsiParamList (FuncDesc* F)
|
|||
Decl.StorageClass &= ~SC_DEF;
|
||||
}
|
||||
|
||||
/* Parse an attribute ### */
|
||||
ParseAttribute (&Decl, &Attr);
|
||||
/* Parse attributes for this parameter */
|
||||
ParseAttribute (&Decl);
|
||||
|
||||
/* Create a symbol table entry */
|
||||
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
|
||||
* are disabled.
|
||||
*/
|
||||
if (IS_Get (&Standard) != STD_CC65 &&
|
||||
(F->Flags & FD_UNNAMED_PARAMS) != 0) {
|
||||
if (IS_Get (&Standard) != STD_CC65 && (F->Flags & FD_UNNAMED_PARAMS)) {
|
||||
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. */
|
||||
{
|
||||
unsigned Offs;
|
||||
|
@ -1238,8 +1237,24 @@ static FuncDesc* ParseFuncDecl (void)
|
|||
|
||||
/* Parse params */
|
||||
if ((F->Flags & FD_OLDSTYLE) == 0) {
|
||||
|
||||
/* New style function */
|
||||
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 {
|
||||
/* Old style function */
|
||||
ParseOldStyleParamList (F);
|
||||
|
@ -1344,7 +1359,7 @@ static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode)
|
|||
NextToken ();
|
||||
|
||||
/* Parse the function declaration */
|
||||
F = ParseFuncDecl ();
|
||||
F = ParseFuncDecl (D);
|
||||
|
||||
/* We cannot specify fastcall for variadic functions */
|
||||
if ((F->Flags & FD_VARIADIC) && (Qualifiers & T_QUAL_FASTCALL)) {
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2008 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* (C) 1998-2009, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
|
@ -38,6 +38,9 @@
|
|||
|
||||
|
||||
|
||||
/* common */
|
||||
#include "coll.h"
|
||||
|
||||
/* cc65 */
|
||||
#include "scanner.h"
|
||||
#include "symtab.h"
|
||||
|
@ -58,9 +61,9 @@
|
|||
/* Result of ParseDeclSpec */
|
||||
typedef struct DeclSpec 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 */
|
||||
unsigned Flags; /* Bitmapped flags */
|
||||
unsigned Flags; /* Bitmapped flags */
|
||||
};
|
||||
|
||||
/* Result of ParseDecl */
|
||||
|
@ -68,14 +71,15 @@ typedef struct Declaration Declaration;
|
|||
struct Declaration {
|
||||
unsigned StorageClass; /* A set of SC_xxx flags */
|
||||
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 */
|
||||
unsigned Index; /* Used to build Type */
|
||||
unsigned Index; /* Used to build Type */
|
||||
};
|
||||
|
||||
/* Modes for ParseDecl */
|
||||
typedef enum {
|
||||
typedef enum {
|
||||
DM_NEED_IDENT, /* We must have an identifier */
|
||||
DM_NO_IDENT, /* We won't read an identifier */
|
||||
DM_ACCEPT_IDENT, /* We will accept an id if there is one */
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2002 Ullrich von Bassewitz */
|
||||
/* Wacholderweg 14 */
|
||||
/* D-70597 Stuttgart */
|
||||
/* EMail: uz@musoftware.de */
|
||||
/* (C) 1998-2009, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
|
@ -35,12 +35,16 @@
|
|||
|
||||
#include <string.h>
|
||||
|
||||
/* common */
|
||||
#include "xmalloc.h"
|
||||
|
||||
/* cc65 */
|
||||
#include "declare.h"
|
||||
#include "declattr.h"
|
||||
#include "error.h"
|
||||
#include "scanner.h"
|
||||
#include "symtab.h"
|
||||
#include "typecmp.h"
|
||||
#include "declattr.h"
|
||||
|
||||
|
||||
|
||||
|
@ -51,28 +55,46 @@
|
|||
|
||||
|
||||
/* Forwards for attribute handlers */
|
||||
static void AliasAttr (const Declaration* D, DeclAttr* A);
|
||||
static void UnusedAttr (const Declaration* D, DeclAttr* A);
|
||||
static void ZeroPageAttr (const Declaration* D, DeclAttr* A);
|
||||
static void NoReturnAttr (Declaration* D);
|
||||
|
||||
|
||||
|
||||
/* Attribute table */
|
||||
typedef struct AttrDesc AttrDesc;
|
||||
struct AttrDesc {
|
||||
const char Name[12];
|
||||
void (*Handler) (const Declaration*, DeclAttr*);
|
||||
const char Name[15];
|
||||
void (*Handler) (Declaration*);
|
||||
};
|
||||
static const AttrDesc AttrTable [atCount] = {
|
||||
{ "alias", AliasAttr },
|
||||
{ "unused", UnusedAttr },
|
||||
{ "zeropage", ZeroPageAttr },
|
||||
static const AttrDesc AttrTable [] = {
|
||||
{ "__noreturn__", NoReturnAttr },
|
||||
{ "noreturn", NoReturnAttr },
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* 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;
|
||||
|
||||
/* 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) {
|
||||
/* Found */
|
||||
return AttrTable + A;
|
||||
|
@ -98,72 +120,54 @@ static const AttrDesc* FindAttribute (const char* Attr)
|
|||
|
||||
|
||||
|
||||
static void AliasAttr (const Declaration* D, DeclAttr* A)
|
||||
/* Handle the "alias" attribute */
|
||||
static void ErrorSkip (void)
|
||||
{
|
||||
SymEntry* Sym;
|
||||
/* List of tokens to skip */
|
||||
static const token_t SkipList[] = { TOK_RPAREN, TOK_SEMI };
|
||||
|
||||
/* Comma expected */
|
||||
ConsumeComma ();
|
||||
/* Skip until closing brace or semicolon */
|
||||
SkipTokens (SkipList, sizeof (SkipList) / sizeof (SkipList[0]));
|
||||
|
||||
/* The next identifier is the name of the alias symbol */
|
||||
if (CurTok.Tok != TOK_IDENT) {
|
||||
Error ("Identifier expected");
|
||||
return;
|
||||
/* If we have a closing brace, read it, otherwise bail out */
|
||||
if (CurTok.Tok == TOK_RPAREN) {
|
||||
/* Read the two closing braces */
|
||||
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)
|
||||
/* Handle the "unused" attribute */
|
||||
static void AddAttr (Declaration* D, DeclAttr* A)
|
||||
/* Add an attribute to a declaration */
|
||||
{
|
||||
/* No parameters */
|
||||
A->AttrType = atUnused;
|
||||
/* Allocate the list if necessary, the add the attribute */
|
||||
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 */
|
||||
A->AttrType = atZeroPage;
|
||||
/* Add the noreturn attribute */
|
||||
AddAttr (D, NewDeclAttr (atNoReturn));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ParseAttribute (const Declaration* D, DeclAttr* A)
|
||||
void ParseAttribute (Declaration* D)
|
||||
/* 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? */
|
||||
if (CurTok.Tok != TOK_ATTRIBUTE) {
|
||||
/* No attribute, bail out */
|
||||
|
@ -177,45 +181,59 @@ void ParseAttribute (const Declaration* D, DeclAttr* A)
|
|||
ConsumeLParen ();
|
||||
ConsumeLParen ();
|
||||
|
||||
/* Identifier follows */
|
||||
if (CurTok.Tok != TOK_IDENT) {
|
||||
Error ("Identifier expected");
|
||||
/* We should *really* try to recover here, but for now: */
|
||||
return;
|
||||
/* Read a list of attributes */
|
||||
while (1) {
|
||||
|
||||
ident AttrName;
|
||||
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 */
|
||||
strcpy (AttrName, CurTok.Ident);
|
||||
Attr = FindAttribute (AttrName);
|
||||
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 ();
|
||||
}
|
||||
}
|
||||
/* The declaration is terminated with two closing braces */
|
||||
ConsumeRParen ();
|
||||
ConsumeRParen ();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2002 Ullrich von Bassewitz */
|
||||
/* Wacholderweg 14 */
|
||||
/* D-70597 Stuttgart */
|
||||
/* EMail: uz@musoftware.de */
|
||||
/* (C) 1998-2009, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* 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 */
|
||||
typedef enum {
|
||||
atNone = -1, /* No attribute */
|
||||
atAlias, /* Alias declaration */
|
||||
atUnused, /* Variable is unused */
|
||||
atZeroPage, /* Zero page symbol */
|
||||
atNone = -1, /* No attribute */
|
||||
atNoReturn, /* Function does not return */
|
||||
|
||||
atCount /* Number of attributes */
|
||||
} attrib_t;
|
||||
atCount /* Number of attributes */
|
||||
} DeclAttrType;
|
||||
|
||||
/* An actual attribute description */
|
||||
typedef struct DeclAttr DeclAttr;
|
||||
struct DeclAttr {
|
||||
attrib_t AttrType; /* Type of attribute */
|
||||
|
||||
union {
|
||||
struct SymEntry* Sym; /* Symbol for alias */
|
||||
} V;
|
||||
DeclAttrType AttrType; /* Type of attribute */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
void ParseAttribute (const Declaration* D, DeclAttr* A);
|
||||
void ParseAttribute (struct Declaration* D);
|
||||
/* Parse an additional __attribute__ modifier */
|
||||
|
||||
|
||||
|
|
|
@ -486,6 +486,12 @@ static void FunctionCall (ExprDesc* Expr)
|
|||
}
|
||||
|
||||
} 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 */
|
||||
if (Expr->Name != 0) {
|
||||
int StdFunc = FindStdFunc ((const char*) Expr->Name);
|
||||
|
|
|
@ -40,6 +40,8 @@
|
|||
|
||||
/* cc65 */
|
||||
#include "anonname.h"
|
||||
#include "declare.h"
|
||||
#include "error.h"
|
||||
#include "symentry.h"
|
||||
|
||||
|
||||
|
@ -67,6 +69,7 @@ SymEntry* NewSymEntry (const char* Name, unsigned Flags)
|
|||
E->Owner = 0;
|
||||
E->Flags = Flags;
|
||||
E->Type = 0;
|
||||
E->Attr = 0;
|
||||
E->AsmName = 0;
|
||||
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)
|
||||
/* Convert a register variable to an auto variable */
|
||||
{
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2000-2009 Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* (C) 2000-2009, Ullrich von Bassewitz */
|
||||
/* Roemerstrasse 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
|
@ -41,10 +41,12 @@
|
|||
#include <stdio.h>
|
||||
|
||||
/* common */
|
||||
#include "coll.h"
|
||||
#include "inline.h"
|
||||
|
||||
/* cc65 */
|
||||
#include "datatype.h"
|
||||
#include "declattr.h"
|
||||
|
||||
|
||||
|
||||
|
@ -65,31 +67,33 @@ struct Segments;
|
|||
|
||||
|
||||
/* Storage classes and flags */
|
||||
#define SC_AUTO 0x0001U
|
||||
#define SC_REGISTER 0x0002U /* Register variable, is in static storage */
|
||||
#define SC_STATIC 0x0004U
|
||||
#define SC_EXTERN 0x0008U
|
||||
#define SC_AUTO 0x0001U /* Auto variable */
|
||||
#define SC_REGISTER 0x0002U /* Register variable */
|
||||
#define SC_STATIC 0x0004U /* Static */
|
||||
#define SC_EXTERN 0x0008U /* Extern linkage */
|
||||
|
||||
#define SC_ENUM 0x0030U /* An enum (numeric constant) */
|
||||
#define SC_CONST 0x0020U /* A numeric constant with a type */
|
||||
#define SC_LABEL 0x0040U /* A goto label */
|
||||
#define SC_PARAM 0x0080U /* This is a function parameter */
|
||||
#define SC_FUNC 0x0100U /* Function entry */
|
||||
#define SC_ENUM 0x0030U /* An enum */
|
||||
#define SC_CONST 0x0020U /* A numeric constant with a type */
|
||||
#define SC_LABEL 0x0040U /* A goto label */
|
||||
#define SC_PARAM 0x0080U /* A function parameter */
|
||||
#define SC_FUNC 0x0100U /* A function */
|
||||
|
||||
#define SC_DEFTYPE 0x0200U /* Parameter has default type (=int, old style) */
|
||||
#define SC_STORAGE 0x0400U /* Symbol with associated storage */
|
||||
#define SC_DEFAULT 0x0800U /* Flag: default storage class was used */
|
||||
#define SC_DEFTYPE 0x0200U /* Parameter has default type (=int, old style) */
|
||||
#define SC_STORAGE 0x0400U /* Symbol with associated storage */
|
||||
#define SC_DEFAULT 0x0800U /* Flag: default storage class was used */
|
||||
|
||||
#define SC_DEF 0x1000U /* Symbol is defined */
|
||||
#define SC_REF 0x2000U /* Symbol is referenced */
|
||||
#define SC_DEF 0x1000U /* Symbol is defined */
|
||||
#define SC_REF 0x2000U /* Symbol is referenced */
|
||||
|
||||
#define SC_TYPE 0x4000U /* This is a type, struct, typedef, etc. */
|
||||
#define SC_STRUCT 0x4001U /* Struct or union */
|
||||
#define SC_STRUCTFIELD 0x4002U /* Struct or union field */
|
||||
#define SC_BITFIELD 0x4004U /* A bit-field inside a struct or union */
|
||||
#define SC_TYPEDEF 0x4008U /* A typedef */
|
||||
#define SC_TYPE 0x4000U /* This is a type, struct, typedef, etc. */
|
||||
#define SC_STRUCT 0x4001U /* Struct or union */
|
||||
#define SC_STRUCTFIELD 0x4002U /* Struct or union field */
|
||||
#define SC_BITFIELD 0x4004U /* A bit-field inside a struct or union */
|
||||
#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 */
|
||||
unsigned Flags; /* Symbol flags */
|
||||
Type* Type; /* Symbol type */
|
||||
Collection* Attr; /* Attribute list if any */
|
||||
char* AsmName; /* Assembler name if any */
|
||||
|
||||
/* Data that differs for the different symbol types */
|
||||
|
@ -226,6 +231,12 @@ INLINE const char* SymGetAsmName (const SymEntry* Sym)
|
|||
# define SymGetAsmName(Sym) ((Sym)->AsmName)
|
||||
#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);
|
||||
/* Convert a register variable to an auto variable */
|
||||
|
||||
|
|
|
@ -181,7 +181,7 @@ static void CheckSymTable (SymTable* Tab)
|
|||
/* Undefined label */
|
||||
Error ("Undefined label: `%s'", Entry->Name);
|
||||
} else if (!SymIsRef (Entry)) {
|
||||
/* Defined but not used */
|
||||
/* Defined but not used */
|
||||
if (IS_Get (&WarnUnusedLabel)) {
|
||||
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) {
|
||||
/* Types not identical: Conflicting types */
|
||||
Error ("Conflicting types for `%s'", Name);
|
||||
return Entry;
|
||||
return Entry;
|
||||
} else {
|
||||
/* Check if we have a size in the existing definition */
|
||||
if (ESize == UNSPECIFIED) {
|
||||
|
@ -781,7 +781,7 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags)
|
|||
/* New type must be identical */
|
||||
if (TypeCmp (EType, T) < TC_EQUAL) {
|
||||
Error ("Conflicting types for `%s'", Name);
|
||||
return Entry;
|
||||
return Entry;
|
||||
}
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
if (IsFunc) {
|
||||
/* Get the function descriptor from the new type */
|
||||
FuncDesc* F = GetFuncDesc (T);
|
||||
/* Use this new function descriptor if it doesn't contain
|
||||
/* Get the function descriptor from the new type */
|
||||
FuncDesc* F = GetFuncDesc (T);
|
||||
/* Use this new function descriptor if it doesn't contain
|
||||
* an empty parameter list.
|
||||
*/
|
||||
if ((F->Flags & FD_EMPTY) == 0) {
|
||||
|
|
Loading…
Add table
Reference in a new issue