a better type check
authorjohanknol <johanknol@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Tue, 5 Jun 2001 19:05:39 +0000 (19:05 +0000)
committerjohanknol <johanknol@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Tue, 5 Jun 2001 19:05:39 +0000 (19:05 +0000)
git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@870 4a8a32a2-be11-0410-ad9d-d568d2c75423

src/SDCC.y
src/SDCCsymt.c
src/SDCCsymt.h
support/Util/SDCCerr.c
support/Util/SDCCerr.h

index c617e3d982d8de18f2000934924830f13c6215a5..b4907a47eca7cb64e26e5d28200866944de4cefa 100644 (file)
@@ -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();
index bc4aebc0573ea430661bd4f49b6bfd44d3606af2..cb1e29c412891139733ee5a690db41b97b01fc99 100644 (file)
@@ -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 ()
index 87fcbcb224887b556ecc23daef9079ccb5279d41..6e152266503a438e685d2d818b72d672773e2f85 100644 (file)
@@ -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
index 7b7f685199b1ad9d3118cc9398184ec8456f397c..04ec9060aaca38efef6e6383be2a6ebd304b29f8 100644 (file)
@@ -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'" },
 };
 /*
 -------------------------------------------------------------------------------
index 1f5960c40ed6b24b7570d5c3541b4ccbf82ce36f..4398867a92a91d172ecbd9671be2c3c5a0293d42 100644 (file)
@@ -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.