1
0
mirror of https://github.com/cc65/cc65.git synced 2024-12-22 12:30:41 +00:00

Merge pull request #2344 from acqn/Cleanup

[cc65] Cleanup for symbol types and flags
This commit is contained in:
Bob Andrews 2024-01-12 16:02:08 +01:00 committed by GitHub
commit 8c329dfd1a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 364 additions and 255 deletions

View File

@ -80,9 +80,9 @@ static void AsmErrorSkip (void)
static SymEntry* AsmGetSym (unsigned Arg, unsigned Type)
/* Find the symbol with the name currently in NextTok. The symbol must be of
** the given type. On errors, NULL is returned.
static SymEntry* AsmGetSym (unsigned Arg, int OnStack)
/* Find the symbol with the name currently in NextTok. The symbol must be on
** the stack if OnStack is true. On errors, NULL is returned.
*/
{
SymEntry* Sym;
@ -110,8 +110,8 @@ static SymEntry* AsmGetSym (unsigned Arg, unsigned Type)
/* We found the symbol - skip the name token */
NextToken ();
/* Check if we have a global symbol */
if ((Sym->Flags & Type) != Type) {
/* Check if the symbol is on the stack */
if ((Sym->Flags & SC_STORAGEMASK) != SC_AUTO ? OnStack : !OnStack) {
Error ("Type of argument %u differs from format specifier", Arg);
AsmErrorSkip ();
return 0;
@ -218,23 +218,24 @@ static void ParseGVarArg (StrBuf* T, unsigned Arg)
*/
{
/* Parse the symbol name parameter and check the type */
SymEntry* Sym = AsmGetSym (Arg, SC_STATIC);
SymEntry* Sym = AsmGetSym (Arg, 0);
if (Sym == 0) {
/* Some sort of error */
return;
}
/* Check for external linkage */
if (Sym->Flags & (SC_EXTERN | SC_STORAGE | SC_FUNC)) {
/* External linkage or a function */
/* Get the correct asm name */
if ((Sym->Flags & SC_TYPEMASK) == SC_FUNC || SymIsGlobal (Sym)) {
/* External or internal linkage or a function */
SB_AppendChar (T, '_');
SB_AppendStr (T, Sym->Name);
} else if (Sym->Flags & SC_REGISTER) {
} else if ((Sym->Flags & SC_STORAGEMASK) == SC_REGISTER) {
/* Register variable */
char Buf[32];
xsprintf (Buf, sizeof (Buf), "regbank+%d", Sym->V.R.RegOffs);
SB_AppendStr (T, Buf);
} else {
/* Static variable */
/* Local static variable */
SB_AppendStr (T, LocalDataLabelName (Sym->V.L.Label));
}
}
@ -248,7 +249,7 @@ static void ParseLVarArg (StrBuf* T, unsigned Arg)
char Buf [16];
/* Parse the symbol name parameter and check the type */
SymEntry* Sym = AsmGetSym (Arg, SC_AUTO);
SymEntry* Sym = AsmGetSym (Arg, 1);
if (Sym == 0) {
/* Some sort of error */
return;

View File

@ -121,15 +121,13 @@ static void Parse (void)
}
/* Read the declaration specifier */
ParseDeclSpec (&Spec, TS_DEFAULT_TYPE_INT, SC_EXTERN | SC_STATIC);
ParseDeclSpec (&Spec, TS_DEFAULT_TYPE_INT, SC_NONE);
/* Don't accept illegal storage classes */
if ((Spec.StorageClass & SC_TYPEMASK) == 0) {
if ((Spec.StorageClass & SC_AUTO) != 0 ||
(Spec.StorageClass & SC_REGISTER) != 0) {
Error ("Illegal storage class");
Spec.StorageClass = SC_EXTERN | SC_STATIC;
}
if ((Spec.StorageClass & SC_STORAGEMASK) == SC_AUTO ||
(Spec.StorageClass & SC_STORAGEMASK) == SC_REGISTER) {
Error ("Illegal storage class");
Spec.StorageClass &= ~SC_STORAGEMASK;
}
/* Check if this is only a type declaration */
@ -172,26 +170,26 @@ static void Parse (void)
** - if the storage class is explicitly specified as static,
** - or if there is an initialization.
**
** This means that "extern int i;" will not get storage allocated.
** This means that "extern int i;" will not get storage allocated
** in this translation unit.
*/
if ((Decl.StorageClass & SC_FUNC) != SC_FUNC &&
if ((Decl.StorageClass & SC_TYPEMASK) != SC_FUNC &&
(Decl.StorageClass & SC_TYPEMASK) != SC_TYPEDEF) {
if ((Spec.Flags & DS_DEF_STORAGE) != 0 ||
(Decl.StorageClass & (SC_EXTERN|SC_STATIC)) == SC_STATIC ||
((Decl.StorageClass & SC_EXTERN) != 0 &&
/* The variable is visible in the file scope */
if ((Decl.StorageClass & SC_STORAGEMASK) == SC_NONE ||
(Decl.StorageClass & SC_STORAGEMASK) == SC_STATIC ||
((Decl.StorageClass & SC_STORAGEMASK) == SC_EXTERN &&
CurTok.Tok == TOK_ASSIGN)) {
/* We will allocate storage */
Decl.StorageClass |= SC_STORAGE;
} else {
/* It's a declaration */
Decl.StorageClass |= SC_DECL;
/* We will allocate storage in this translation unit */
Decl.StorageClass |= SC_TU_STORAGE;
}
}
/* If this is a function declarator that is not followed by a comma
** or semicolon, it must be followed by a function body.
*/
if ((Decl.StorageClass & SC_FUNC) != 0) {
if ((Decl.StorageClass & SC_TYPEMASK) == SC_FUNC) {
/* The function is now visible in the file scope */
if (CurTok.Tok == TOK_LCURLY) {
/* A definition */
Decl.StorageClass |= SC_DEF;
@ -205,8 +203,6 @@ static void Parse (void)
}
} else {
/* Just a declaration */
Decl.StorageClass |= SC_DECL;
FuncDef = GetFuncDesc (Decl.Type);
if ((FuncDef->Flags & (FD_EMPTY | FD_OLDSTYLE)) == FD_OLDSTYLE) {
/* A parameter list without types is only allowed in a
@ -224,7 +220,7 @@ static void Parse (void)
SymUseAttr (Sym, &Decl);
/* Reserve storage for the variable if we need to */
if (Decl.StorageClass & SC_STORAGE) {
if (Decl.StorageClass & SC_TU_STORAGE) {
/* Get the size of the variable */
unsigned Size = SizeOf (Decl.Type);
@ -327,9 +323,13 @@ static void Parse (void)
}
/* Make the symbol zeropage according to the segment address size */
if ((Sym->Flags & SC_STATIC) != 0) {
if (GetSegAddrSize (GetSegName (CS->CurDSeg)) == ADDR_SIZE_ZP) {
Sym->Flags |= SC_ZEROPAGE;
if ((Sym->Flags & SC_TYPEMASK) == SC_NONE) {
if (SymIsGlobal (Sym) ||
(Sym->Flags & SC_STORAGEMASK) == SC_STATIC ||
(Sym->Flags & SC_STORAGEMASK) == SC_REGISTER) {
if (GetSegAddrSize (GetSegName (CS->CurDSeg)) == ADDR_SIZE_ZP) {
Sym->Flags |= SC_ZEROPAGE;
}
}
}
@ -517,7 +517,10 @@ void Compile (const char* FileName)
** global variables.
*/
for (Entry = GetGlobalSymTab ()->SymHead; Entry; Entry = Entry->NextSym) {
if ((Entry->Flags & (SC_STORAGE | SC_DEF | SC_STATIC)) == (SC_STORAGE | SC_STATIC)) {
/* Is it a global (with or without static) tentative declaration of
** an uninitialized variable?
*/
if ((Entry->Flags & (SC_TU_STORAGE | SC_DEF)) == SC_TU_STORAGE) {
/* Assembly definition of uninitialized global variable */
SymEntry* TagSym = GetESUTagSym (Entry->Type);
unsigned Size = SizeOf (Entry->Type);
@ -552,9 +555,9 @@ void Compile (const char* FileName)
Entry->Name,
GetFullTypeName (Entry->Type));
}
} else if (!SymIsDef (Entry) && (Entry->Flags & SC_FUNC) == SC_FUNC) {
} else if (!SymIsDef (Entry) && (Entry->Flags & SC_TYPEMASK) == SC_FUNC) {
/* Check for undefined functions */
if ((Entry->Flags & (SC_EXTERN | SC_STATIC)) == SC_STATIC && SymIsRef (Entry)) {
if ((Entry->Flags & SC_STORAGEMASK) == SC_STATIC && SymIsRef (Entry)) {
Warning ("Static function '%s' used but never defined",
Entry->Name);
}

View File

@ -91,7 +91,7 @@ static unsigned ParseOneStorageClass (void)
switch (CurTok.Tok) {
case TOK_EXTERN:
StorageClass = SC_EXTERN | SC_STATIC;
StorageClass = SC_EXTERN;
NextToken ();
break;
@ -101,7 +101,7 @@ static unsigned ParseOneStorageClass (void)
break;
case TOK_REGISTER:
StorageClass = SC_REGISTER | SC_STATIC;
StorageClass = SC_REGISTER;
NextToken ();
break;
@ -136,9 +136,9 @@ static int ParseStorageClass (DeclSpec* Spec)
}
while (StorageClass != 0) {
if (Spec->StorageClass == 0) {
Spec->StorageClass = StorageClass;
} else if (Spec->StorageClass == StorageClass) {
if ((Spec->StorageClass & SC_STORAGEMASK) == 0) {
Spec->StorageClass |= StorageClass;
} else if ((Spec->StorageClass & SC_STORAGEMASK) == StorageClass) {
Warning ("Duplicate storage class specifier");
} else {
Error ("Conflicting storage class specifier");
@ -618,12 +618,12 @@ static SymEntry* ForwardESU (const char* Name, unsigned Flags, unsigned* DSFlags
*/
SymEntry* TagEntry = FindTagSym (Name);
if (TagEntry == 0) {
if ((Flags & SC_ESUTYPEMASK) != SC_ENUM) {
if ((Flags & SC_TYPEMASK) != SC_ENUM) {
TagEntry = AddStructSym (Name, Flags, 0, 0, DSFlags);
} else {
TagEntry = AddEnumSym (Name, Flags, 0, 0, DSFlags);
}
} else if ((TagEntry->Flags & SC_TYPEMASK) != (Flags & SC_ESUTYPEMASK)) {
} else if ((TagEntry->Flags & SC_TYPEMASK) != (Flags & SC_TYPEMASK)) {
/* Already defined, but not the same type class */
Error ("Symbol '%s' is already different kind", Name);
}
@ -798,7 +798,7 @@ static SymEntry* ParseEnumSpec (const char* Name, unsigned* DSFlags)
}
/* Add an entry of the enumerator to the symbol table */
AddConstSym (Ident, NewType, SC_ENUMERATOR | SC_CONST, EnumVal);
AddConstSym (Ident, NewType, SC_DEF | SC_ENUMERATOR, EnumVal);
/* Use this type for following members */
MemberType = NewType;
@ -1825,8 +1825,8 @@ static void ParseOldStyleParamDeclList (FuncDesc* F attribute ((unused)))
/* We accept only auto and register as storage class specifiers, but
** we ignore all this, since we use auto anyway.
*/
if ((Spec.StorageClass & SC_AUTO) == 0 &&
(Spec.StorageClass & SC_REGISTER) == 0) {
if ((Spec.StorageClass & SC_STORAGEMASK) != SC_AUTO &&
(Spec.StorageClass & SC_STORAGEMASK) != SC_REGISTER) {
Error ("Illegal storage class");
}
@ -1942,12 +1942,12 @@ static void ParseAnsiParamList (FuncDesc* F)
ParseDeclSpec (&Spec, TS_DEFAULT_TYPE_NONE, SC_AUTO);
/* We accept only auto and register as storage class specifiers */
if ((Spec.StorageClass & SC_AUTO) == SC_AUTO) {
Spec.StorageClass = SC_AUTO | SC_PARAM | SC_DEF;
} else if ((Spec.StorageClass & SC_REGISTER) == SC_REGISTER) {
Spec.StorageClass = SC_REGISTER | SC_STATIC | SC_PARAM | SC_DEF;
if ((Spec.StorageClass & SC_STORAGEMASK) == SC_REGISTER) {
Spec.StorageClass = SC_REGISTER | SC_PARAM | SC_DEF;
} else {
Error ("Illegal storage class");
if ((Spec.StorageClass & SC_STORAGEMASK) != SC_AUTO) {
Error ("Illegal storage class");
}
Spec.StorageClass = SC_AUTO | SC_PARAM | SC_DEF;
}
@ -2355,7 +2355,9 @@ int ParseDecl (DeclSpec* Spec, Declarator* D, declmode_t Mode)
D->StorageClass = Spec->StorageClass;
/* If we have a function, add a special symbol type */
if (IsTypeFunc (D->Type)) {
if (Mode != DM_ACCEPT_PARAM_IDENT &&
IsTypeFunc (D->Type) &&
(D->StorageClass & SC_TYPEMASK) == SC_NONE) {
D->StorageClass |= SC_FUNC;
}
@ -2479,9 +2481,9 @@ void ParseDeclSpec (DeclSpec* Spec, typespec_t TSFlags, unsigned DefStorage)
ParseTypeSpec (Spec, TSFlags | TS_STORAGE_CLASS_SPEC | TS_FUNCTION_SPEC);
/* If no explicit storage class is given, use the default */
if (Spec->StorageClass == 0) {
if ((Spec->StorageClass & SC_STORAGEMASK) == 0) {
Spec->Flags |= DS_DEF_STORAGE;
Spec->StorageClass = DefStorage;
Spec->StorageClass |= DefStorage;
}
}

View File

@ -1223,8 +1223,8 @@ static void Primary (ExprDesc* E)
NextToken ();
/* Check for illegal symbol types */
CHECK ((Sym->Flags & SC_LABEL) != SC_LABEL);
if (Sym->Flags & SC_ESUTYPEMASK) {
CHECK ((Sym->Flags & SC_TYPEMASK) != SC_LABEL);
if ((Sym->Flags & SC_TYPEMASK) == SC_TYPEDEF) {
/* Cannot use type symbols */
Error ("Variable identifier expected");
/* Assume an int type to make E valid */
@ -1244,7 +1244,7 @@ static void Primary (ExprDesc* E)
/* Enum or some other numeric constant */
E->Flags = E_LOC_NONE | E_RTYPE_RVAL;
E->IVal = Sym->V.ConstVal;
} else if ((Sym->Flags & SC_AUTO) == SC_AUTO) {
} else if ((Sym->Flags & SC_STORAGEMASK) == SC_AUTO) {
/* Local variable. If this is a parameter for a variadic
** function, we have to add some address calculations, and the
** address is not const.
@ -1258,26 +1258,25 @@ static void Primary (ExprDesc* E)
E->Flags = E_LOC_STACK | E_RTYPE_LVAL;
E->IVal = Sym->V.Offs;
}
} else if ((Sym->Flags & SC_FUNC) == SC_FUNC) {
} else if ((Sym->Flags & SC_TYPEMASK) == SC_FUNC) {
/* Function */
E->Flags = E_LOC_GLOBAL | E_RTYPE_LVAL;
E->Name = (uintptr_t) Sym->Name;
} else if ((Sym->Flags & SC_REGISTER) == SC_REGISTER) {
} else if ((Sym->Flags & SC_STORAGEMASK) == SC_REGISTER) {
/* Register variable, zero page based */
E->Flags = E_LOC_REGISTER | E_RTYPE_LVAL;
E->Name = Sym->V.R.RegOffs;
} else if ((Sym->Flags & SC_STATIC) == SC_STATIC) {
/* Static variable */
if (Sym->Flags & (SC_EXTERN | SC_STORAGE | SC_DECL)) {
E->Flags = E_LOC_GLOBAL | E_RTYPE_LVAL;
E->Name = (uintptr_t) Sym->Name;
} else {
E->Flags = E_LOC_STATIC | E_RTYPE_LVAL;
E->Name = Sym->V.L.Label;
}
} else {
} else if (SymIsGlobal (Sym)) {
/* Global variable */
E->Flags = E_LOC_GLOBAL | E_RTYPE_LVAL;
E->Name = (uintptr_t) Sym->Name;
} else if ((Sym->Flags & SC_STORAGEMASK) == SC_STATIC) {
/* Local static variable */
E->Flags = E_LOC_STATIC | E_RTYPE_LVAL;
E->Name = Sym->V.L.Label;
} else {
/* Other */
E->Flags = E_LOC_STATIC | E_RTYPE_LVAL;
E->Name = Sym->V.Offs;
}
@ -1311,7 +1310,7 @@ static void Primary (ExprDesc* E)
} else {
Warning ("Call to undeclared function '%s'", Ident);
}
Sym = AddGlobalSym (Ident, GetImplicitFuncType(), SC_EXTERN | SC_REF | SC_FUNC);
Sym = AddGlobalSym (Ident, GetImplicitFuncType(), SC_REF | SC_FUNC);
E->Type = Sym->Type;
E->Flags = E_LOC_GLOBAL | E_RTYPE_RVAL;
E->Name = (uintptr_t) Sym->Name;

View File

@ -98,7 +98,7 @@ enum {
E_LOC_NONE = 0x0000, /* Pure rvalue with no storage */
E_LOC_ABS = 0x0001, /* Absolute numeric addressed variable */
E_LOC_GLOBAL = 0x0002, /* Global variable */
E_LOC_STATIC = 0x0004, /* Static variable */
E_LOC_STATIC = 0x0004, /* Local static variable */
E_LOC_REGISTER = 0x0008, /* Register variable */
E_LOC_STACK = 0x0010, /* Value on the stack */
E_LOC_PRIMARY = 0x0020, /* Temporary in primary register */

View File

@ -92,7 +92,7 @@ void GotoStatement (void)
/* Find array size */
if (!IsTypeArray (arr->Type) || SizeOf (arr->Type) == 0 ||
!(arr->Flags & SC_STATIC) ||
(arr->Flags & SC_STORAGEMASK) != SC_STATIC ||
SizeOf (GetElementType(arr->Type)) != 2) {
Error ("Expected a static array");
} else if (GetElementCount (arr->Type) > 127) {

View File

@ -304,7 +304,7 @@ static void ParseAutoDecl (Declarator* Decl)
/* Static local variables. */
Decl->StorageClass = (Decl->StorageClass & ~SC_AUTO) | SC_STATIC;
Decl->StorageClass = (Decl->StorageClass & ~SC_STORAGEMASK) | SC_STATIC;
/* Generate a label, but don't define it */
DataLabel = GetLocalDataLabel ();
@ -451,24 +451,27 @@ static int ParseOneDecl (DeclSpec* Spec)
/* Read the declarator */
NeedClean = ParseDecl (Spec, &Decl, DM_IDENT_OR_EMPTY);
/* Check if there are any non-extern storage classes set for function
** declarations. Function can only be declared inside functions with the
** 'extern' storage class specifier or no storage class specifier at all.
/* Check if there are explicitly specified non-external storage classes
** for function declarations.
*/
if ((Decl.StorageClass & SC_FUNC) == SC_FUNC) {
/* Check if there are explicitly specified non-external storage classes */
if ((Decl.StorageClass & SC_TYPEMASK) == SC_FUNC) {
/* Function can only be declared inside functions with the 'extern'
** storage class specifier or no storage class specifier at all.
** Note: this declaration is always checked for compatibility with
** other declarations of the same symbol, but does not necessarily
** make the symbol globally visible. This is tricky.
*/
if ((Spec->Flags & DS_DEF_STORAGE) != DS_DEF_STORAGE &&
(Decl.StorageClass & SC_EXTERN) == 0 &&
(Decl.StorageClass & SC_STORAGEMASK) != SC_EXTERN &&
(Decl.StorageClass & SC_STORAGEMASK) != 0) {
Error ("Illegal storage class on function");
}
/* The default storage class could be wrong. Just clear them */
Decl.StorageClass &= ~SC_STORAGEMASK;
/* This is always an extern declaration */
Decl.StorageClass |= SC_DECL | SC_EXTERN;
} else if ((Decl.StorageClass & SC_STORAGEMASK) != SC_EXTERN) {
/* If the symbol is not marked as external, it will be defined now */
Decl.StorageClass |= SC_DEF;
}
/* If we don't have a name, this was flagged as an error earlier.
@ -478,12 +481,6 @@ static int ParseOneDecl (DeclSpec* Spec)
AnonName (Decl.Ident, "param");
}
/* If the symbol is not marked as external, it will be defined now */
if ((Decl.StorageClass & SC_DECL) == 0 &&
(Decl.StorageClass & SC_EXTERN) == 0) {
Decl.StorageClass |= SC_DEF;
}
/* Handle anything that needs storage (no functions, no typdefs) */
if ((Decl.StorageClass & SC_DEF) == SC_DEF &&
(Decl.StorageClass & SC_TYPEMASK) != SC_TYPEDEF) {
@ -492,20 +489,20 @@ static int ParseOneDecl (DeclSpec* Spec)
** convert the declaration to "auto" if this is not possible.
*/
int Reg = 0; /* Initialize to avoid gcc complains */
if ((Decl.StorageClass & SC_REGISTER) != 0 &&
if ((Decl.StorageClass & SC_STORAGEMASK) == SC_REGISTER &&
(Reg = F_AllocRegVar (CurrentFunc, Decl.Type)) < 0) {
/* No space for this register variable, convert to auto */
Decl.StorageClass = (Decl.StorageClass & ~SC_REGISTER) | SC_AUTO;
Decl.StorageClass = (Decl.StorageClass & ~SC_STORAGEMASK) | SC_AUTO;
}
/* Check the variable type */
if ((Decl.StorageClass & SC_REGISTER) == SC_REGISTER) {
if ((Decl.StorageClass & SC_STORAGEMASK) == SC_REGISTER) {
/* Register variable */
ParseRegisterDecl (&Decl, Reg);
} else if ((Decl.StorageClass & SC_AUTO) == SC_AUTO) {
} else if ((Decl.StorageClass & SC_STORAGEMASK) == SC_AUTO) {
/* Auto variable */
ParseAutoDecl (&Decl);
} else if ((Decl.StorageClass & SC_STATIC) == SC_STATIC) {
} else if ((Decl.StorageClass & SC_STORAGEMASK) == SC_STATIC) {
/* Static variable */
ParseStaticDecl (&Decl);
} else {
@ -514,7 +511,7 @@ static int ParseOneDecl (DeclSpec* Spec)
} else {
if ((Decl.StorageClass & SC_EXTERN) == SC_EXTERN) {
if ((Decl.StorageClass & SC_STORAGEMASK) == SC_EXTERN) {
/* External identifier - may not get initialized */
if (CurTok.Tok == TOK_ASSIGN) {
Error ("Cannot initialize extern variable '%s'", Decl.Ident);
@ -524,8 +521,8 @@ static int ParseOneDecl (DeclSpec* Spec)
}
}
if ((Decl.StorageClass & SC_EXTERN) == SC_EXTERN ||
(Decl.StorageClass & SC_FUNC) == SC_FUNC) {
if ((Decl.StorageClass & SC_STORAGEMASK) == SC_EXTERN ||
(Decl.StorageClass & SC_TYPEMASK) == SC_FUNC) {
/* Add the global symbol to both of the global and local symbol
** tables.
*/

View File

@ -630,7 +630,7 @@ static void WrappedCallPragma (pragma_scope_t Scope, StrBuf* B)
Entry = FindSym(Name);
/* Check if the name is valid */
if (Entry && (Entry->Flags & SC_FUNC) == SC_FUNC) {
if (Entry && (Entry->Flags & SC_TYPEMASK) == SC_FUNC) {
PushWrappedCall(Entry, (unsigned int) Val);
Entry->Flags |= SC_REF;

View File

@ -88,7 +88,7 @@ void FreeSymEntry (SymEntry* E)
TypeFree (E->Type);
xfree (E->AsmName);
if (E->Flags & SC_LABEL) {
if ((E->Flags & SC_TYPEMASK) == SC_LABEL) {
for (i = 0; i < CollCount (E->V.L.DefsOrRefs); i++) {
xfree (CollAt (E->V.L.DefsOrRefs, i));
}
@ -109,21 +109,17 @@ void DumpSymEntry (FILE* F, const SymEntry* E)
unsigned Val;
} SCFlagTable;
static SCFlagTable ESUTypes[] = {
{ "SC_TYPEDEF", SC_TYPEDEF },
{ "SC_UNION", SC_UNION },
{ "SC_STRUCT", SC_STRUCT },
{ "SC_ENUM", SC_ENUM },
};
static SCFlagTable Types[] = {
{ "SC_BITFIELD", SC_BITFIELD },
{ "SC_STRUCTFIELD", SC_STRUCTFIELD },
{ "SC_ENUMERATOR", SC_ENUMERATOR },
{ "SC_CONST", SC_CONST },
{ "SC_NONE", SC_NONE },
{ "SC_STRUCT", SC_STRUCT },
{ "SC_UNION", SC_UNION },
{ "SC_ENUM", SC_ENUM },
{ "SC_LABEL", SC_LABEL },
{ "SC_PARAM", SC_PARAM },
{ "SC_BITFIELD", SC_BITFIELD },
{ "SC_TYPEDEF", SC_TYPEDEF },
{ "SC_ENUMERATOR", SC_ENUMERATOR },
{ "SC_FUNC", SC_FUNC },
{ "SC_ARRAY", SC_ARRAY },
};
static SCFlagTable Storages[] = {
@ -131,11 +127,31 @@ void DumpSymEntry (FILE* F, const SymEntry* E)
{ "SC_REGISTER", SC_REGISTER },
{ "SC_STATIC", SC_STATIC },
{ "SC_EXTERN", SC_EXTERN },
{ "SC_STORAGE", SC_STORAGE },
};
static SCFlagTable Properties[] = {
{ "SC_CONST", SC_CONST },
{ "SC_STRUCTFIELD", SC_STRUCTFIELD },
{ "SC_PARAM", SC_PARAM },
{ "SC_DEFTYPE", SC_DEFTYPE },
{ "SC_ZEROPAGE", SC_ZEROPAGE },
{ "SC_DECL", SC_DECL },
{ "SC_HAVEALIGN", SC_HAVEALIGN },
{ "SC_HAVEATTR", SC_HAVEATTR },
{ "SC_TU_STORAGE", SC_TU_STORAGE },
{ "SC_ASSIGN_INIT", SC_ASSIGN_INIT },
{ "SC_ALIAS", SC_ALIAS },
{ "SC_FICTITIOUS", SC_FICTITIOUS },
{ "SC_HAVEFAM", SC_HAVEFAM },
{ "SC_HAVECONST", SC_HAVECONST },
};
static SCFlagTable Status[] = {
{ "SC_DEF", SC_DEF },
{ "SC_REF", SC_REF },
{ "SC_GOTO", SC_GOTO },
{ "SC_GOTO_IND", SC_GOTO_IND },
{ "SC_LOCALSCOPE", SC_LOCALSCOPE },
{ "SC_NOINLINEDEF", SC_NOINLINEDEF },
};
unsigned I;
@ -152,28 +168,38 @@ void DumpSymEntry (FILE* F, const SymEntry* E)
/* Print the flags */
SymFlags = E->Flags;
fprintf (F, " Flags:");
/* Enum, struct, union and typedefs */
if ((SymFlags & SC_ESUTYPEMASK) != 0) {
for (I = 0; I < sizeof (ESUTypes) / sizeof (ESUTypes[0]); ++I) {
if ((SymFlags & SC_ESUTYPEMASK) == ESUTypes[I].Val) {
SymFlags &= ~SC_ESUTYPEMASK;
fprintf (F, " %s", ESUTypes[I].Name);
/* Symbol types */
if ((SymFlags & SC_TYPEMASK) != 0) {
for (I = 0; I < sizeof (Types) / sizeof (Types[0]); ++I) {
if ((SymFlags & SC_TYPEMASK) == Types[I].Val) {
SymFlags &= ~SC_TYPEMASK;
fprintf (F, " %s", Types[I].Name);
break;
}
}
}
/* Other type flags */
for (I = 0; I < sizeof (Types) / sizeof (Types[0]) && SymFlags != 0; ++I) {
if ((SymFlags & Types[I].Val) == Types[I].Val) {
SymFlags &= ~Types[I].Val;
fprintf (F, " %s", Types[I].Name);
/* Storage classes */
if ((SymFlags & SC_STORAGEMASK) != 0) {
for (I = 0; I < sizeof (Storages) / sizeof (Storages[0]); ++I) {
if ((SymFlags & SC_STORAGEMASK) == Storages[I].Val) {
SymFlags &= ~SC_STORAGEMASK;
fprintf (F, " %s", Storages[I].Name);
break;
}
}
}
/* Storage flags */
for (I = 0; I < sizeof (Storages) / sizeof (Storages[0]) && SymFlags != 0; ++I) {
if ((SymFlags & Storages[I].Val) == Storages[I].Val) {
SymFlags &= ~Storages[I].Val;
fprintf (F, " %s", Storages[I].Name);
/* Special property flags */
for (I = 0; I < sizeof (Properties) / sizeof (Properties[0]) && SymFlags != 0; ++I) {
if ((SymFlags & Properties[I].Val) == Properties[I].Val) {
SymFlags &= ~Properties[I].Val;
fprintf (F, " %s", Properties[I].Name);
}
}
/* Status flags */
for (I = 0; I < sizeof (Status) / sizeof (Status[0]) && SymFlags != 0; ++I) {
if ((SymFlags & Status[I].Val) == Status[I].Val) {
SymFlags &= ~Status[I].Val;
fprintf (F, " %s", Status[I].Name);
}
}
if (SymFlags != 0) {
@ -199,9 +225,10 @@ int SymIsOutputFunc (const SymEntry* Sym)
/* Symbol must be a function which is defined and either extern or
** static and referenced.
*/
return IsTypeFunc (Sym->Type) &&
SymIsDef (Sym) &&
(Sym->Flags & (SC_REF | SC_EXTERN));
return IsTypeFunc (Sym->Type) &&
SymIsDef (Sym) &&
((Sym->Flags & SC_REF) ||
(Sym->Flags & SC_STORAGEMASK) != SC_STATIC);
}
@ -272,7 +299,7 @@ void SymCvtRegVarToAuto (SymEntry* Sym)
/* Convert a register variable to an auto variable */
{
/* Change the storage class */
Sym->Flags = (Sym->Flags & ~(SC_REGISTER | SC_STATIC | SC_EXTERN)) | SC_AUTO;
Sym->Flags = (Sym->Flags & ~SC_STORAGEMASK) | SC_AUTO;
/* Transfer the stack offset from register save area to actual offset */
Sym->V.Offs = Sym->V.R.SaveOffs;

View File

@ -68,47 +68,88 @@ struct CodeEntry;
/* Storage classes and flags */
/* Symbol types and flags */
#define SC_NONE 0x0000U /* Nothing */
#define SC_STRUCT 0x0001U /* Struct */
#define SC_UNION 0x0002U /* Union */
#define SC_ENUM 0x0003U /* Enum */
#define SC_TYPEDEF 0x0004U /* Typedef */
#define SC_ESUTYPEMASK 0x0007U /* Mask for above types */
#define SC_ENUMERATOR 0x0008U /* An enumerator */
#define SC_BITFIELD 0x0010U /* A bit-field inside a struct or union */
#define SC_TYPEMASK 0x001FU /* Mask for above types */
#define SC_FUNC 0x0020U /* A function */
#define SC_LABEL 0x0040U /* A goto code label */
#define SC_CONST 0x0080U /* A numeric constant with a type */
#define SC_PARAM 0x0100U /* A function parameter */
#define SC_DEFTYPE 0x0200U /* Parameter has default type (=int, old style) */
#define SC_STRUCTFIELD 0x0400U /* Struct or union field */
/* Types of symbols */
#define SC_STRUCT 0x0001U /* Struct tag */
#define SC_UNION 0x0002U /* Union tag */
#define SC_ENUM 0x0003U /* Enum tag */
#define SC_LABEL 0x0004U /* A goto code label */
#define SC_BITFIELD 0x0005U /* A bit-field inside a struct or union */
#define SC_TYPEDEF 0x0006U /* A typedef */
#define SC_ENUMERATOR 0x0007U /* An enumerator */
#define SC_ZEROPAGE 0x0800U /* Symbol marked as zeropage */
/* Note: These symbol types might be checked as bit-flags occasionally.
** So don't share their unique bits with other symbol types.
*/
#define SC_FUNC 0x0008U /* A function */
#define SC_ARRAY 0x0010U /* UNUSED: An array */
#define SC_TYPEMASK 0x001FU /* Mask for symbol types all above */
#define SC_DEF 0x1000U /* Symbol is defined */
#define SC_REF 0x2000U /* Symbol is referenced */
#define SC_DECL 0x4000U /* Symbol is declared in global scope */
#define SC_STORAGE 0x8000U /* Symbol with associated storage */
/* Additional property of the symbols */
#define SC_CONST 0x0020U /* A numeric constant with a type */
#define SC_STRUCTFIELD 0x0040U /* A struct or union field */
#define SC_PARAM 0x0080U /* A function parameter */
#define SC_DEFTYPE 0x0100U /* An old-style parameter with default type (=int) */
#define SC_AUTO 0x010000U /* Auto variable */
#define SC_REGISTER 0x020000U /* Register variable */
#define SC_STATIC 0x040000U /* Static - not to be confused with other *_STATIC */
#define SC_EXTERN 0x080000U /* Extern linkage */
#define SC_STORAGEMASK 0x0F0000U /* Storage type mask */
/* Address property of the symbol */
#define SC_ZEROPAGE 0x0200U /* Symbol marked as on zeropage */
#define SC_HAVEATTR 0x100000U /* Symbol has attributes */
/* Additional attributes of the symbol */
#define SC_HAVEALIGN 0x0400U /* UNUSED: Symbol has special alignment */
#define SC_HAVEATTR 0x0800U /* Symbol has attributes */
#define SC_GOTO 0x200000U
#define SC_SPADJUSTMENT 0x400000U
#define SC_GOTO_IND 0x800000U /* Indirect goto */
/* Special property of declaration */
#define SC_TU_STORAGE 0x1000U /* Symbol has allocated storage in the TU */
#define SC_ASSIGN_INIT 0x2000U /* Symbol is to be initialized with assignment code */
#define SC_ALIAS 0x01000000U /* Alias of global or anonymous field */
#define SC_FICTITIOUS 0x02000000U /* Symbol is fictitious (for error recovery) */
#define SC_HAVEFAM 0x04000000U /* Type has a Flexible Array Member */
#define SC_HAVECONST 0x08000000U /* Type has a const member */
#define SC_ALIAS 0x4000U /* Symbol is an alias */
#define SC_FICTITIOUS 0x8000U /* Symbol is fictitious (for error recovery) */
#define SC_HAVEFAM 0x010000U /* Struct/union has a Flexible Array Member */
#define SC_HAVECONST 0x020000U /* Struct/union has a const member */
/* Status of the symbol */
#define SC_DEF 0x040000U /* Symbol is defined */
#define SC_REF 0x080000U /* Symbol is referenced */
#define SC_GOTO 0x100000U /* Symbol is destination of a goto */
#define SC_GOTO_IND 0x200000U /* Symbol is destination of an indirect goto */
#define SC_LOCALSCOPE 0x400000U /* Symbol is invisible in file scope */
#define SC_NOINLINEDEF 0x800000U /* Symbol may never have an inline definition */
/* To figure out the linkage of an object or function symbol Sym:
** - external linkage:
** SymIsGlobal (Sym) && (Sym->Flags & SC_STORAGEMASK) != SC_STATIC
** - internal linkage:
** SymIsGlobal (Sym) && (Sym->Flags & SC_STORAGEMASK) == SC_STATIC
** - no linkage:
** !SymIsGlobal (Sym)
**
** To figure out the storage class of a symbol by its SC_ flags:
**
** - no explicit storage class specifiers (in file scope):
** (flags & SC_STORAGEMASK) == SC_NONE
** - no explicit storage class specifiers (in block scope):
** (flags & SC_STORAGEMASK) == SC_AUTO
** - extern:
** (flags & SC_STORAGEMASK) == SC_EXTERN
** - static:
** (flags & SC_STORAGEMASK) == SC_STATIC
** - auto:
** (flags & SC_STORAGEMASK) == SC_AUTO
** - register:
** (flags & SC_STORAGEMASK) == SC_REGISTER
** - typedef (per ISO C):
** (flags & SC_TYPEMASK) == SC_TYPEDEF
**
** Note: SC_TYPEDEF can be also used as a flag.
*/
#define SC_AUTO 0x01000000U /* Auto storage class */
#define SC_REGISTER 0x02000000U /* Register storage class */
#define SC_STATIC 0x03000000U /* Static storage class */
#define SC_EXTERN 0x04000000U /* Extern storage class */
#define SC_THREAD 0x08000000U /* UNSUPPORTED: Thread-local storage class */
#define SC_STORAGEMASK 0x0F000000U /* Storage type mask */
@ -214,14 +255,37 @@ void FreeSymEntry (SymEntry* E);
void DumpSymEntry (FILE* F, const SymEntry* E);
/* Dump the given symbol table entry to the file in readable form */
int SymIsOutputFunc (const SymEntry* Sym);
/* Return true if this is a function that must be output */
#if defined(HAVE_INLINE)
INLINE int SymIsArray (const SymEntry* Sym)
/* Return true if the given entry is an array entry */
{
return ((Sym->Flags & SC_TYPEMASK) == SC_ARRAY);
}
#else
# define SymIsArray(Sym) (((Sym)->Flags & SC_TYPEMASK) == SC_ARRAY)
#endif
#if defined(HAVE_INLINE)
INLINE int SymIsBitField (const SymEntry* Sym)
/* Return true if the given entry is a bit-field entry */
{
return ((Sym->Flags & SC_BITFIELD) == SC_BITFIELD);
return ((Sym->Flags & SC_TYPEMASK) == SC_BITFIELD);
}
#else
# define SymIsBitField(Sym) (((Sym)->Flags & SC_BITFIELD) == SC_BITFIELD)
# define SymIsBitField(Sym) (((Sym)->Flags & SC_TYPEMASK) == SC_BITFIELD)
#endif
#if defined(HAVE_INLINE)
INLINE int SymIsLabel (const SymEntry* Sym)
/* Return true if the given entry is a label entry */
{
return ((Sym)->Flags & SC_TYPEMASK) == SC_LABEL;
}
#else
# define SymIsLabel(Sym) (((Sym)->Flags & SC_TYPEMASK) == SC_LABEL)
#endif
#if defined(HAVE_INLINE)
@ -257,17 +321,13 @@ INLINE int SymIsRef (const SymEntry* Sym)
#if defined(HAVE_INLINE)
INLINE int SymIsRegVar (const SymEntry* Sym)
/* Return true if the given entry is a register variable */
/* ### HACK! Fix the ugly type flags! */
{
return ((Sym->Flags & (SC_REGISTER | SC_TYPEMASK)) == SC_REGISTER);
return ((Sym->Flags & (SC_STORAGEMASK | SC_TYPEMASK)) == (SC_REGISTER | SC_NONE));
}
#else
# define SymIsRegVar(Sym) (((Sym)->Flags & (SC_REGISTER | SC_TYPEMASK)) == SC_REGISTER)
# define SymIsRegVar(Sym) (((Sym)->Flags & (SC_STORAGEMASK | SC_TYPEMASK)) == (SC_REGISTER | SC_NONE))
#endif
int SymIsOutputFunc (const SymEntry* Sym);
/* Return true if this is a function that must be output */
#if defined(HAVE_INLINE)
INLINE int SymHasFlexibleArrayMember (const SymEntry* Sym)
/* Return true if the given entry has a flexible array member */

View File

@ -165,22 +165,22 @@ static void CheckSymTable (SymTable* Tab)
/* Ignore typedef entries */
if (!SymIsTypeDef (Entry)) {
/* Check if the symbol is one with storage, and it if it was
** defined but not used.
*/
if (((Flags & SC_AUTO) || (Flags & SC_STATIC)) && (Flags & SC_EXTERN) == 0) {
/* Check if the symbol has non-external linkage and is defined but not used */
if (!SymIsGlobal (Entry) || (Flags & SC_STORAGEMASK) == SC_STATIC) {
if (SymIsDef (Entry) && !SymIsRef (Entry) &&
!SymHasAttr (Entry, atUnused)) {
if (Flags & SC_PARAM) {
if (IS_Get (&WarnUnusedParam)) {
Warning ("Parameter '%s' is never used", Entry->Name);
}
} else if (Flags & SC_FUNC) {
} else if ((Flags & SC_TYPEMASK) == SC_FUNC) {
if (IS_Get (&WarnUnusedFunc)) {
Warning ("Function '%s' is defined but never used", Entry->Name);
}
} else if (!IsAnonName (Entry->Name)) {
if (IS_Get (&WarnUnusedVar)) {
} else if ((Flags & SC_TYPEMASK) == SC_NONE) {
if (IS_Get (&WarnUnusedVar) &&
!IsAnonName (Entry->Name) &&
(Flags & SC_CONST) != SC_CONST) {
Warning ("Variable '%s' is defined but never used", Entry->Name);
}
}
@ -188,7 +188,7 @@ static void CheckSymTable (SymTable* Tab)
}
/* If the entry is a label, check if it was defined in the function */
if (Flags & SC_LABEL) {
if ((Flags & SC_TYPEMASK) == SC_LABEL) {
if (!SymIsDef (Entry)) {
/* Undefined label */
Error ("Undefined label: '%s'", Entry->Name);
@ -716,7 +716,7 @@ static int HandleSymRedefinition (SymEntry* Sym, const Type* T, unsigned Flags)
Sym = 0;
}
} else if ((Sym->Flags & SC_FUNC) == SC_FUNC) {
} else if ((Sym->Flags & SC_TYPEMASK) == SC_FUNC) {
/* In case of a function, use the new type descriptor, since it
** contains pointers to the new symbol tables that are needed if
@ -863,7 +863,6 @@ SymEntry* AddEnumSym (const char* Name, unsigned Flags, const Type* Type, SymTab
} else {
TagEntry->V.E.SymTab = Tab;
TagEntry->V.E.Type = Type;
TagEntry->Flags &= ~SC_DECL;
TagEntry->Flags |= SC_DEF;
/* Remember this is the first definition of this type */
@ -1047,7 +1046,7 @@ SymEntry* AddConstSym (const char* Name, const Type* T, unsigned Flags, long Val
SymEntry* Entry = FindSymInTable (SymTab, Name, HashStr (Name));
if (Entry) {
if ((Entry->Flags & SC_CONST) != SC_CONST) {
if ((Entry->Flags & SC_TYPEMASK) != (Flags & SC_TYPEMASK)) {
Error ("Symbol '%s' is already different kind", Name);
} else {
Error ("Multiple definition for constant '%s'", Name);
@ -1056,7 +1055,7 @@ SymEntry* AddConstSym (const char* Name, const Type* T, unsigned Flags, long Val
}
/* Create a new entry */
Entry = NewSymEntry (Name, Flags);
Entry = NewSymEntry (Name, Flags | SC_CONST);
/* We only have integer constants for now */
Entry->Type = TypeDup (T);
@ -1167,7 +1166,7 @@ SymEntry* AddLabelSym (const char* Name, unsigned Flags)
/* Optimizer will need the information about the value of SP adjustment
** later, so let's preserve it.
*/
E = NewSymEntry (LocalDataLabelName (DOR->LateSP_Label), SC_SPADJUSTMENT);
E = NewSymEntry (LocalDataLabelName (DOR->LateSP_Label), 0);
E->V.SPAdjustment = StackPtr - DOR->StackPtr;
AddSymEntry (SPAdjustTab, E);
}
@ -1236,38 +1235,32 @@ SymEntry* AddLocalSym (const char* Name, const Type* T, unsigned Flags, int Offs
Entry = FindSymInTable (Tab, Name, HashStr (Name));
if (Entry) {
int CheckExtern = 0;
if ((Flags & SC_STRUCTFIELD) == 0) {
while (Entry && (Entry->Flags & SC_ALIAS) == SC_ALIAS) {
/* Get the aliased entry */
Entry = Entry->V.A.Field;
/* Check for conflict with local storage class */
CheckExtern = 1;
}
}
/* We have a symbol with this name already */
if (HandleSymRedefinition (Entry, T, Flags)) {
Entry = 0;
} else if ((Flags & SC_ESUTYPEMASK) != SC_TYPEDEF) {
} else if ((Flags & SC_TYPEMASK) != SC_TYPEDEF) {
/* Redefinitions are not allowed */
if (SymIsDef (Entry) && (Flags & SC_DEF) == SC_DEF) {
Error ("Multiple definition of '%s'", Entry->Name);
Entry = 0;
} else if (CheckExtern) {
if ((Flags & (SC_AUTO | SC_REGISTER)) != 0) {
Error ("Declaration of '%s' with no linkage follows extern declaration", Name);
Entry = 0;
} else if ((Flags & SC_DEF) != 0 && (Flags & SC_EXTERN) == 0) {
/* If a static declaration follows a non-static declaration,
** then it is an error.
*/
Error ("Static declaration of '%s' follows extern declaration", Name);
Entry = 0;
}
} else if ((Flags & SC_STRUCTFIELD) != 0) {
Error ("Duplicate member '%s'", Entry->Name);
Entry = 0;
} else if (Entry->Owner == SymTab0) {
if ((Flags & SC_STORAGEMASK) == SC_AUTO ||
(Flags & SC_STORAGEMASK) == SC_REGISTER ||
(Flags & SC_STORAGEMASK) == SC_STATIC) {
Error ("Declaration of '%s' with no linkage follows extern declaration",
Name);
Entry = 0;
}
}
}
@ -1290,20 +1283,20 @@ SymEntry* AddLocalSym (const char* Name, const Type* T, unsigned Flags, int Offs
Entry->Type = TypeDup (T);
if ((Flags & SC_STRUCTFIELD) == SC_STRUCTFIELD ||
(Flags & SC_ESUTYPEMASK) == SC_TYPEDEF) {
(Flags & SC_TYPEMASK) == SC_TYPEDEF) {
if ((Flags & SC_ALIAS) != SC_ALIAS) {
Entry->V.Offs = Offs;
}
} else if ((Flags & SC_AUTO) == SC_AUTO) {
} else if ((Flags & SC_STORAGEMASK) == SC_AUTO) {
Entry->V.Offs = Offs;
} else if ((Flags & SC_REGISTER) == SC_REGISTER) {
} else if ((Flags & SC_STORAGEMASK) == SC_REGISTER) {
Entry->V.R.RegOffs = Offs;
Entry->V.R.SaveOffs = StackPtr;
} else if ((Flags & SC_EXTERN) == SC_EXTERN ||
(Flags & SC_FUNC) == SC_FUNC) {
} else if ((Flags & SC_STORAGEMASK) == SC_EXTERN ||
(Flags & SC_TYPEMASK) == SC_FUNC) {
Entry->V.L.Label = Offs;
SymSetAsmName (Entry);
} else if ((Flags & SC_STATIC) == SC_STATIC) {
} else if ((Flags & SC_STORAGEMASK) == SC_STATIC) {
/* Generate the assembler name from the data label number */
Entry->V.L.Label = Offs;
Entry->AsmName = xstrdup (LocalDataLabelName (Entry->V.L.Label));
@ -1348,49 +1341,63 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags)
Entry = FindGlobalSym (Name);
}
/* Do we have a symbol with this name already? */
if (Entry) {
/* We have a symbol with this name already */
/* Check if the symbol refers to some different type of things */
if (HandleSymRedefinition (Entry, T, Flags)) {
Entry = 0;
} else if ((Entry->Flags & (SC_AUTO | SC_REGISTER)) != 0) {
/* Check for local storage class conflict */
} else if (Entry->Owner != SymTab0) {
/* The previous declaration has no linkage. The current declaration
** has either external or internal linkage. Either way it is an
** error since the two declarations would be referring to different
** objects with the same identifier.
*/
Error ("Extern declaration of '%s' follows declaration with no linkage",
Name);
Entry = 0;
} else if ((Flags & SC_ESUTYPEMASK) != SC_TYPEDEF) {
/* If a static declaration follows a non-static declaration, then
** the result is undefined.
** Most compilers choose to either give an error at compile time,
** or remove the extern property for a link time error if used.
} else if ((Flags & SC_TYPEMASK) != SC_TYPEDEF) {
/* The C standard specifies that the result is undefined if the
** same thing has both internal and external linkage. Most
** compilers choose to either give an error at compile time, or
** remove the external linkage for a link time error if used
** outside the current translation unit. We choose to give an
** error at compile time in this case.
*/
if (SymTab == SymTab0 &&
(Flags & SC_EXTERN) == 0 &&
(Entry->Flags & SC_EXTERN) != 0) {
Error ("Static declaration of '%s' follows non-static declaration", Name);
Entry = 0;
} else if ((Flags & SC_EXTERN) != 0 &&
(Entry->Owner == SymTab0 || (Entry->Flags & SC_DEF) != 0) &&
(Entry->Flags & SC_EXTERN) == 0) {
/* It is OK if a global extern declaration follows a global
** non-static declaration, but an error if either of them is
** local, as the two would be referring to different objects.
** It is an error as well if a global non-static declaration
** follows a global static declaration.
if ((Entry->Flags & SC_STORAGEMASK) != SC_STATIC) {
/* The previous declaration is a non-static declaration of an
** object or function that has external linkage.
*/
if (Entry->Owner == SymTab0) {
if ((Flags & SC_STORAGE) == 0) {
/* The C standard specifies that a later extern declaration will keep
** the previously declared internal or external linkage unchanged.
** Though not required by the standard, we are warning on this case.
*/
Flags &= ~SC_EXTERN;
Warning ("Extern declaration of '%s' follows static declaration, linkage unchanged", Name);
} else {
Error ("Non-static declaration of '%s' follows static declaration", Name);
Entry = 0;
}
} else {
Error ("Extern declaration of '%s' follows static declaration", Name);
if ((Flags & SC_STORAGEMASK) == SC_STATIC) {
/* It is a static declaration of an object or function that
** has internal linkage. Conflicted wih the previous one.
*/
Error ("Static declaration of '%s' follows non-static declaration",
Name);
Entry = 0;
}
} else if ((Flags & SC_STORAGEMASK) != SC_STATIC) {
/* The previous declaration is a static declaration of an
** object or function that has internal linkage.
*/
if ((Flags & SC_STORAGEMASK) == SC_EXTERN ||
(Flags & SC_TYPEMASK) == SC_FUNC) {
/* The C standard specifies that an extern declaration
** shall keep the previously declared internal linkage
** unchanged. For a function declaration with no storage
** class specifiers, it is treated as if with 'extern'.
** We give a warning although it is not required by the
** standard.
*/
Flags &= ~SC_STORAGEMASK;
Warning ("Extern declaration of '%s' follows static declaration",
Name);
} else if ((Flags & SC_STORAGEMASK) == SC_NONE) {
/* It is a non-extern-or-static declaration of an object in
** file scope that has external linkage. Conflicted wih the
** previous one.
*/
Error ("Non-static declaration of '%s' follows static declaration",
Name);
Entry = 0;
}
}
@ -1486,14 +1493,22 @@ SymTable* GetLabelSymTab (void)
int SymIsLocal (SymEntry* Sym)
/* Return true if the symbol is defined in the highest lexical level */
int SymIsLocal (const SymEntry* Sym)
/* Return true if the symbol is declared in the highest lexical level */
{
return (Sym->Owner == SymTab || Sym->Owner == TagTab);
}
int SymIsGlobal (const SymEntry* Sym)
/* Return true if the symbol is declared in the file scope level */
{
return (Sym->Owner == SymTab0 || Sym->Owner == TagTab0);
}
void MakeZPSym (const char* Name)
/* Mark the given symbol as zero page symbol */
{
@ -1553,7 +1568,9 @@ void EmitExternals (void)
Entry = SymTab->SymHead;
while (Entry) {
unsigned Flags = Entry->Flags;
if (Flags & SC_EXTERN) {
if (Entry->Owner == SymTab0 &&
(Flags & SC_STORAGEMASK) != SC_STATIC &&
((Flags & SC_TYPEMASK) == SC_FUNC || (Flags & SC_TYPEMASK) == SC_NONE)) {
/* Only defined or referenced externs */
if (SymIsRef (Entry) && !SymIsDef (Entry)) {
/* An import */
@ -1587,18 +1604,18 @@ void EmitDebugInfo (void)
}
Sym = SymTab->SymHead;
while (Sym) {
if ((Sym->Flags & (SC_CONST | SC_TYPEMASK)) == 0) {
if (Sym->Flags & SC_AUTO) {
if ((Sym->Flags & SC_TYPEMASK) == 0) {
if ((Sym->Flags & SC_STORAGEMASK) == SC_AUTO) {
AddTextLine ("%s, \"%s\", \"00\", auto, %d",
Head, Sym->Name, Sym->V.Offs);
} else if (Sym->Flags & SC_REGISTER) {
} else if ((Sym->Flags & SC_STORAGEMASK) == SC_REGISTER) {
AddTextLine ("%s, \"%s\", \"00\", register, \"regbank\", %d",
Head, Sym->Name, Sym->V.R.RegOffs);
} else if (SymIsRef (Sym) && !SymIsDef (Sym)) {
AddTextLine ("%s, \"%s\", \"00\", %s, \"%s\"",
Head, Sym->Name,
(Sym->Flags & SC_EXTERN)? "extern" : "static",
(Sym->Flags & SC_STORAGEMASK) != SC_STATIC ? "extern" : "static",
Sym->AsmName);
}
}

View File

@ -211,8 +211,11 @@ SymTable* GetFieldSymTab (void);
SymTable* GetLabelSymTab (void);
/* Return the label symbol table */
int SymIsLocal (SymEntry* Sym);
/* Return true if the symbol is defined in the highest lexical level */
int SymIsLocal (const SymEntry* Sym);
/* Return true if the symbol is declared in the highest lexical level */
int SymIsGlobal (const SymEntry* Sym);
/* Return true if the symbol is declared in the file scope level */
void MakeZPSym (const char* Name);
/* Mark the given symbol as zero page symbol */