From f4cfabdb276af4ef7328e82d6b184f6dfba0c16d Mon Sep 17 00:00:00 2001 From: johanknol Date: Tue, 5 Jun 2001 19:05:39 +0000 Subject: [PATCH] a better type check git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@870 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- src/SDCC.y | 10 ++++---- src/SDCCsymt.c | 54 ++++++++++++++++++++++++++++++++++++++++-- src/SDCCsymt.h | 16 ++++--------- support/Util/SDCCerr.c | 10 ++++++++ support/Util/SDCCerr.h | 5 ++++ 5 files changed, 76 insertions(+), 19 deletions(-) diff --git a/src/SDCC.y b/src/SDCC.y index c617e3d9..b4907a47 100644 --- a/src/SDCC.y +++ b/src/SDCC.y @@ -565,8 +565,7 @@ type_specifier2 | SHORT { $$=newLink(); $$->class = SPECIFIER ; - SPEC_LONG($$) = 0 ; - SPEC_SHORT($$) = 1 ; + SPEC_SHORT($$) = 1 ; } | INT { $$=newLink(); @@ -576,18 +575,17 @@ type_specifier2 | LONG { $$=newLink(); $$->class = SPECIFIER ; - SPEC_LONG($$) = 1 ; - SPEC_SHORT($$) = 0; + SPEC_LONG($$) = 1 ; } | SIGNED { $$=newLink(); $$->class = SPECIFIER ; - SPEC_USIGN($$) = 0 ; + SPEC_SIGNED($$) = 1 ; } | UNSIGNED { $$=newLink(); $$->class = SPECIFIER ; - SPEC_USIGN($$) = 1 ; + SPEC_USIGN($$) = 1 ; } | VOID { $$=newLink(); diff --git a/src/SDCCsymt.c b/src/SDCCsymt.c index bc4aebc0..cb1e29c4 100644 --- a/src/SDCCsymt.c +++ b/src/SDCCsymt.c @@ -424,12 +424,59 @@ addDecl (symbol * sym, int type, sym_link * p) return; } +/*------------------------------------------------------------------ + checkTypeSanity: prevent the user from doing e.g.: + unsigned float uf; + ------------------------------------------------------------------*/ +void checkTypeSanity(sym_link *dest) { + char *noun; + switch (SPEC_NOUN(dest)) + { + case V_CHAR: noun="char"; break; + case V_INT: noun="int"; break; + case V_FLOAT: noun="float"; break; + case V_DOUBLE: noun="double"; break; + case V_VOID: noun="void"; break; + default: noun="unknown type"; break; + } + + if ((SPEC_NOUN(dest)==V_CHAR || + SPEC_NOUN(dest)==V_FLOAT || + SPEC_NOUN(dest)==V_DOUBLE || + SPEC_NOUN(dest)==V_VOID) && + (SPEC_SHORT(dest) || SPEC_LONG(dest))) { + // long or short for char float double or void + werror (E_LONG_OR_SHORT_INVALID, noun, yylval.yychar); + } + if ((SPEC_NOUN(dest)==V_FLOAT || + SPEC_NOUN(dest)==V_DOUBLE || + SPEC_NOUN(dest)==V_VOID) && + (SPEC_SIGNED(dest) || SPEC_USIGN(dest))) { + // signed or unsigned for float double or void + werror (E_SIGNED_OR_UNSIGNED_INVALID, noun, yylval.yychar); + } + if (SPEC_SIGNED(dest) && SPEC_USIGN(dest)) { + // signed AND unsigned + werror (E_SIGNED_AND_UNSIGNED_INVALID, noun, yylval.yychar); + } + if (SPEC_SHORT(dest) && SPEC_LONG(dest)) { + // short AND long + werror (E_LONG_AND_SHORT_INVALID, noun, yylval.yychar); + } +} + /*------------------------------------------------------------------*/ -/* mergeSpec - merges two specifiers and returns the new one */ +/* mergeSpec - merges two specifiers and returns the new one */ /*------------------------------------------------------------------*/ sym_link * mergeSpec (sym_link * dest, sym_link * src) { + + /* we shouldn't redeclare the type */ + if (SPEC_NOUN (dest) && SPEC_NOUN (src)) { + werror(E_TWO_OR_MORE_DATA_TYPES, yylval.yychar); + } + /* if noun different then src overrides */ if (SPEC_NOUN (dest) != SPEC_NOUN (src) && !SPEC_NOUN (dest)) SPEC_NOUN (dest) = SPEC_NOUN (src); @@ -444,6 +491,7 @@ mergeSpec (sym_link * dest, sym_link * src) SPEC_LONG (dest) |= SPEC_LONG (src); SPEC_SHORT (dest) |= SPEC_SHORT (src); SPEC_USIGN (dest) |= SPEC_USIGN (src); + SPEC_SIGNED (dest) |= SPEC_SIGNED (src); SPEC_STAT (dest) |= SPEC_STAT (src); SPEC_EXTR (dest) |= SPEC_EXTR (src); SPEC_ABSA (dest) |= SPEC_ABSA (src); @@ -463,6 +511,8 @@ mergeSpec (sym_link * dest, sym_link * src) if (IS_STRUCT (dest) && SPEC_STRUCT (dest) == NULL) SPEC_STRUCT (dest) = SPEC_STRUCT (src); + checkTypeSanity(dest); + return dest; } @@ -512,7 +562,7 @@ getSpec (sym_link * p) } /*------------------------------------------------------------------*/ -/* newCharLink() - creates an int type */ +/* newCharLink() - creates an char type */ /*------------------------------------------------------------------*/ sym_link * newCharLink () diff --git a/src/SDCCsymt.h b/src/SDCCsymt.h index 87fcbcb2..6e152266 100644 --- a/src/SDCCsymt.h +++ b/src/SDCCsymt.h @@ -55,14 +55,15 @@ structdef; /* noun definitions */ typedef enum { - V_INT = 0, + V_INT = 1, V_FLOAT, V_CHAR, V_VOID, V_STRUCT, V_LABEL, V_BIT, - V_SBIT + V_SBIT, + V_DOUBLE } NOUN; @@ -88,15 +89,6 @@ typedef enum } STORAGE_CLASS; -#define TF_LONG 0x00000001 /* type long int */ -#define TF_SHORT 0x00000002 /* type short */ -#define TF_UNSIGNED 0x00000004 /* type is unsigned */ -#define TF_STATIC 0x00000008 /* type is static */ -#define TF_EXTERN 0x00000010 /* type is extern */ -#define TF_ABSADDR 0x00000020 /* type has absolute address */ -#define TF_REENT 0x00000040 /* type of func is reentrant func */ -#define TF_INTRRNT 0x00000080 /* is an interrupt routine */ - /* specifier is the last in the type-chain */ typedef struct specifier { @@ -106,6 +98,7 @@ typedef struct specifier unsigned _long:1; /* 1=long */ unsigned _short:1; /* 1=short int */ unsigned _unsigned:1; /* 1=unsigned, 0=signed */ + unsigned _signed:1; /* just for sanity checks only*/ unsigned _static:1; /* 1=static keyword found */ unsigned _extern:1; /* 1=extern found */ unsigned _absadr:1; /* absolute address specfied */ @@ -288,6 +281,7 @@ symbol; #define SPEC_LONG(x) x->select.s._long #define SPEC_SHORT(x) x->select.s._short #define SPEC_USIGN(x) x->select.s._unsigned +#define SPEC_SIGNED(x) x->select.s._signed #define SPEC_SCLS(x) x->select.s.sclass #define SPEC_ENUM(x) x->select.s._isenum #define SPEC_OCLS(x) x->select.s.oclass diff --git a/support/Util/SDCCerr.c b/support/Util/SDCCerr.c index 7b7f6851..04ec9060 100644 --- a/support/Util/SDCCerr.c +++ b/support/Util/SDCCerr.c @@ -335,6 +335,16 @@ struct " Cannot determine which register bank to save." }, { E_NO_SUCH_BANK, ERROR_LEVEL_ERROR, "called function uses unknown register bank %d." }, +{ E_TWO_OR_MORE_DATA_TYPES, ERROR_LEVEL_ERROR, + "two or more data types in declaration for '%s'" }, +{ E_LONG_OR_SHORT_INVALID, ERROR_LEVEL_ERROR, + "long or short specified for %s '%s'" }, +{ E_SIGNED_OR_UNSIGNED_INVALID, ERROR_LEVEL_ERROR, + "signed or unsigned specified for %s '%s'" }, +{ E_LONG_AND_SHORT_INVALID, ERROR_LEVEL_ERROR, + "both long and short specified for %s '%s'" }, +{ E_SIGNED_AND_UNSIGNED_INVALID, ERROR_LEVEL_ERROR, + "both signed and unsigned specified for %s '%s'" }, }; /* ------------------------------------------------------------------------------- diff --git a/support/Util/SDCCerr.h b/support/Util/SDCCerr.h index 1f5960c4..4398867a 100644 --- a/support/Util/SDCCerr.h +++ b/support/Util/SDCCerr.h @@ -156,6 +156,11 @@ SDCCERR - SDCC Standard error handler #define E_INVALID_HEX 138 /* \x used with no following hex digits */ #define W_FUNCPTR_IN_USING_ISR 139 /* Call via function pointer in ISR with using attribute. */ #define E_NO_SUCH_BANK 140 /* 'using' attribute specifies non-existant register bank. */ +#define E_TWO_OR_MORE_DATA_TYPES 141 +#define E_LONG_OR_SHORT_INVALID 142 /* long or short invalid for .. */ +#define E_SIGNED_OR_UNSIGNED_INVALID 143 /* signed or unsigned invalid for .. */ +#define E_LONG_AND_SHORT_INVALID 144 /* long and short invalid for .. */ +#define E_SIGNED_AND_UNSIGNED_INVALID 145 /* signed and unsigned invalid for .. */ /** Describes the maximum error level that will be logged. Any level * includes all of the levels listed after it. -- 2.39.2