fixed bug #460010
[fw/sdcc] / src / SDCCsymt.c
index 2037ea608b518dac9a7f88430ef4d48ed9a1e3b3..361c1db8038023abbf5f39daa0f1bcee53f56b8f 100644 (file)
@@ -318,9 +318,13 @@ pointerTypes (sym_link * ptr, sym_link * type)
     ptr = ptr->next;
 
   /* could not find it */
-  if (!ptr || IS_SPEC (ptr) ||
-      DCL_TYPE (ptr) != UPOINTER)
+  if (!ptr || IS_SPEC (ptr))
     return;
+  
+  if (IS_PTR(ptr) && DCL_TYPE(ptr)!=UPOINTER) {
+    pointerTypes (ptr->next, type);
+    return;
+  }
 
   /* change the pointer type depending on the
      storage class of the type */
@@ -432,13 +436,13 @@ addDecl (symbol * sym, int type, sym_link * p)
        }
     }
 
-  /* if the type is a unknown pointer and has
+  /* if the type is an unknown pointer and has
      a tspec then take the storage class const & volatile
      attribute from the tspec & make it those of this
      symbol */
   if (p &&
       !IS_SPEC (p) &&
-      DCL_TYPE (p) == UPOINTER &&
+      //DCL_TYPE (p) == UPOINTER &&
       DCL_TSPEC (p))
     {
       if (!IS_SPEC (sym->etype))
@@ -524,31 +528,34 @@ void checkTypeSanity(sym_link *etype, char *name) {
 /*------------------------------------------------------------------*/
 /* mergeSpec - merges two specifiers and returns the new one        */
 /*------------------------------------------------------------------*/
-#define LAST_MINUTE_2_3_0_FIX
 sym_link *
 mergeSpec (sym_link * dest, sym_link * src, char *name)
 {
 
-#ifdef LAST_MINUTE_2_3_0_FIX
   sym_link *symlink;
 
   if (!IS_SPEC(dest)) {
-    // This should not happen
-    fprintf (stderr, "*** internal error: can't merge declarators\n");
+    // This can happen for pointers, find the end type
+    while (dest && !IS_SPEC(dest))
+      dest=dest->next;
   }
   if (!IS_SPEC(src)) {
     // here we have a declarator as source, reverse them
     symlink=src;
     src=dest;
     dest=symlink;
-    while (!IS_SPEC(dest)) {
+    while (dest && !IS_SPEC(dest)) {
       // and find the specifier
       dest=dest->next;
     }
   } else {
     symlink=dest;
   }
-#endif
+
+  if (!IS_SPEC(dest) || !IS_SPEC(src)) {
+    werror (E_INTERNAL_ERROR, __FILE__, __LINE__, "cannot merge declarator");
+    exit (1);
+  }
 
   if (getenv("DEBUG_mergeSpec")) {
     fprintf (stderr, "mergeSpec: \"%s\"\n", name);
@@ -614,11 +621,7 @@ mergeSpec (sym_link * dest, sym_link * src, char *name)
   if (IS_STRUCT (dest) && SPEC_STRUCT (dest) == NULL)
     SPEC_STRUCT (dest) = SPEC_STRUCT (src);
 
-#ifdef LAST_MINUTE_2_3_0_FIX
   return symlink;
-#else
-  return dest;
-#endif
 }
 
 /*------------------------------------------------------------------*/
@@ -944,48 +947,36 @@ addSymChain (symbol * symHead)
   symbol *sym = symHead;
   symbol *csym = NULL;
 
-
   for (; sym != NULL; sym = sym->next)
     {
       changePointer(sym);
+      checkTypeSanity(sym->etype, sym->name);
 
       /* if already exists in the symbol table then check if
-         the previous was an extern definition if yes then
+         one of them is an extern definition if yes then
          then check if the type match, if the types match then
          delete the current entry and add the new entry      */
       if ((csym = findSymWithLevel (SymbolTab, sym)) &&
-         csym->level == sym->level)
-       {
-
-         /* previous definition extern ? */
-         if (IS_EXTERN (csym->etype))
-           {
-             /* do types match ? */
-             if (compareType (csym->type, sym->type) != 1)
-               /* no then error */
-               werror (E_DUPLICATE, csym->name);
-
-             /* delete current entry */
-             deleteSym (SymbolTab, csym, csym->name);
-             /* add new entry */
-             addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 1);
-           }
-         else                  /* not extern */
-           werror (E_DUPLICATE, sym->name);
+         csym->level == sym->level) {
+       
+       /* one definition extern ? */
+       if (IS_EXTERN (csym->etype) || IS_EXTERN (sym->etype)) {
+         /* do types match ? */
+         if (compareType (csym->type, sym->type) != 1) {
+           /* no then error */
+           werror (E_EXTERN_MISMATCH, csym->name);
+           continue;
+         }
+         /* delete current entry */
+         deleteSym (SymbolTab, csym, csym->name);
+       } else {
+         /* not extern */
+         werror (E_DUPLICATE, sym->name);
          continue;
        }
+      }
 
-      /* check if previously defined */
-      if (csym && csym->level == sym->level)
-       {
-         /* if the previous one was declared as extern */
-         /* then check the type with the current one         */
-         if (IS_EXTERN (csym->etype))
-           {
-             if (compareType (csym->type, sym->type) <= 0)
-               werror (W_EXTERN_MISMATCH, csym->name);
-           }
-       }
+      /* add new entry */
       addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 1);
     }
 }
@@ -1104,7 +1095,7 @@ compStructSize (int su, structdef * sdef)
            }
        }
        else {
-           checkDecl (loop);
+           checkDecl (loop, 1);
            sum += getSize (loop->type);
        }
 
@@ -1136,7 +1127,7 @@ compStructSize (int su, structdef * sdef)
 /* checkSClass - check the storage class specification              */
 /*------------------------------------------------------------------*/
 static void 
-checkSClass (symbol * sym)
+checkSClass (symbol * sym, int isProto)
 {
   if (getenv("DEBUG_SANITY")) {
     fprintf (stderr, "checkSClass: %s \n", sym->name);
@@ -1204,23 +1195,6 @@ checkSClass (symbol * sym)
       sym->ival = NULL;
     }
 
-#if 0
-  /* if this is an automatic symbol then */
-  /* storage class will be ignored and   */
-  /* symbol will be allocated on stack/  */
-  /* data depending on flag             */
-  if (sym->level &&
-      (options.stackAuto || reentrant) &&
-      (SPEC_SCLS (sym->etype) != S_AUTO &&
-       SPEC_SCLS (sym->etype) != S_FIXED &&
-       SPEC_SCLS (sym->etype) != S_REGISTER &&
-       SPEC_SCLS (sym->etype) != S_STACK &&
-       SPEC_SCLS (sym->etype) != S_XSTACK))
-    {
-      werror (E_AUTO_ASSUMED, sym->name);
-      SPEC_SCLS (sym->etype) = S_AUTO;
-    }
-#else
   /* if this is an atomatic symbol */
   if (sym->level && (options.stackAuto || reentrant)) {
     if ((SPEC_SCLS (sym->etype) == S_AUTO ||
@@ -1236,7 +1210,6 @@ checkSClass (symbol * sym)
       }
     }
   }
-#endif
   
   /* automatic symbols cannot be given   */
   /* an absolute address ignore it      */
@@ -1264,15 +1237,17 @@ checkSClass (symbol * sym)
       SPEC_BSTR (sym->etype) = 0;
     }
 
-  /* variables declared in CODE space must have */
-  /* initializers if not an extern */
-  if (SPEC_SCLS (sym->etype) == S_CODE &&
-      sym->ival == NULL &&
-      !sym->level &&
-      port->mem.code_ro &&
-      !IS_EXTERN (sym->etype) &&
-      !funcInChain (sym->type))
-    werror (E_CODE_NO_INIT, sym->name);
+  if (!isProto) {
+    /* variables declared in CODE space must have */
+    /* initializers if not an extern */
+    if (SPEC_SCLS (sym->etype) == S_CODE &&
+       sym->ival == NULL &&
+       !sym->level &&
+       port->mem.code_ro &&
+       !IS_EXTERN (sym->etype) &&
+       !funcInChain (sym->type))
+      werror (E_CODE_NO_INIT, sym->name);
+  }
 
   /* if parameter or local variable then change */
   /* the storage class to reflect where the var will go */
@@ -1322,10 +1297,10 @@ changePointer (symbol * sym)
 /* checkDecl - does semantic validation of a declaration                   */
 /*------------------------------------------------------------------*/
 int 
-checkDecl (symbol * sym)
+checkDecl (symbol * sym, int isProto)
 {
 
-  checkSClass (sym);           /* check the storage class      */
+  checkSClass (sym, isProto);          /* check the storage class      */
   changePointer (sym);         /* change pointers if required */
 
   /* if this is an array without any dimension