]> git.sur5r.net Git - cc65/blobdiff - src/cc65/declare.c
In an old style function definition, print a diagnostic if a type is assigned
[cc65] / src / cc65 / declare.c
index 44b8ddf05454b4b4ad42aa3c4b53274dea6288d2..2b4a09a42a61f2644755c169679236b067ef2b2e 100644 (file)
@@ -6,8 +6,8 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2004 Ullrich von Bassewitz                                       */
-/*               Römerstraße 52                                              */
+/* (C) 1998-2008 Ullrich von Bassewitz                                       */
+/*               Roemerstrasse 52                                            */
 /*               D-70794 Filderstadt                                         */
 /* EMail:        uz@cc65.org                                                 */
 /*                                                                           */
 
 
 
-static void ParseTypeSpec (DeclSpec* D, int Default);
+static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers);
 /* Parse a type specificier */
 
-static unsigned ParseInitInternal (type* T, int AllowFlexibleMembers);
+static unsigned ParseInitInternal (Type* T, int AllowFlexibleMembers);
 /* Parse initialization of variables. Return the number of data bytes. */
 
 
@@ -82,7 +82,7 @@ static unsigned ParseInitInternal (type* T, int AllowFlexibleMembers);
 
 
 
-static type OptionalQualifiers (type Q)
+static TypeCode OptionalQualifiers (TypeCode Q)
 /* Read type qualifiers if we have any */
 {
     while (TokIsTypeQual (&CurTok)) {
@@ -103,6 +103,13 @@ static type OptionalQualifiers (type Q)
                Q |= T_QUAL_VOLATILE;
                break;
 
+            case TOK_RESTRICT:
+                if (Q & T_QUAL_RESTRICT) {
+                    Error ("Duplicate qualifier: `restrict'");
+                }
+                Q |= T_QUAL_RESTRICT;
+                break;
+
            default:
                Internal ("Unexpected type qualifier token: %d", CurTok.Tok);
 
@@ -118,7 +125,7 @@ static type OptionalQualifiers (type Q)
 
 
 
-static void optionalint (void)
+static void OptionalInt (void)
 /* Eat an optional "int" token */
 {
     if (CurTok.Tok == TOK_INT) {
@@ -129,7 +136,7 @@ static void optionalint (void)
 
 
 
-static void optionalsigned (void)
+static void OptionalSigned (void)
 /* Eat an optional "signed" token */
 {
     if (CurTok.Tok == TOK_SIGNED) {
@@ -144,7 +151,7 @@ static void InitDeclSpec (DeclSpec* D)
 /* Initialize the DeclSpec struct for use */
 {
     D->StorageClass     = 0;
-    D->Type[0]          = T_END;
+    D->Type[0].C        = T_END;
     D->Flags            = 0;
 }
 
@@ -153,9 +160,9 @@ static void InitDeclSpec (DeclSpec* D)
 static void InitDeclaration (Declaration* D)
 /* Initialize the Declaration struct for use */
 {
-    D->Ident[0] = '\0';
-    D->Type[0]  = T_END;
-    D->Index    = 0;
+    D->Ident[0]  = '\0';
+    D->Type[0].C = T_END;
+    D->Index     = 0;
 }
 
 
@@ -174,22 +181,59 @@ static void NeedTypeSpace (Declaration* D, unsigned Count)
 
 
 
-static void AddTypeToDeclaration (Declaration* D, type T)
+static void AddTypeToDeclaration (Declaration* D, TypeCode T)
 /* Add a type specifier to the type of a declaration */
 {
     NeedTypeSpace (D, 1);
-    D->Type[D->Index++] = T;
+    D->Type[D->Index++].C = T;
+}
+
+
+
+static void AddFuncTypeToDeclaration (Declaration* D, FuncDesc* F)
+/* Add a function type plus function descriptor to the type of a declaration */
+{
+    NeedTypeSpace (D, 1);
+    D->Type[D->Index].C = T_FUNC;
+    SetFuncDesc (D->Type + D->Index, F);
+    ++D->Index;
 }
 
 
 
-static void AddEncodeToDeclaration (Declaration* D, type T, unsigned long Val)
-/* Add a type plus encoding to the type of a declaration */
+static void AddArrayToDeclaration (Declaration* D, long Size)
+/* Add an array type plus size to the type of a declaration */
 {
-    NeedTypeSpace (D, DECODE_SIZE+1);
-    D->Type[D->Index++] = T;
-    Encode (D->Type + D->Index, Val);
-    D->Index += DECODE_SIZE;
+    NeedTypeSpace (D, 1);
+    D->Type[D->Index].C = T_ARRAY;
+    D->Type[D->Index].A.L = Size;
+    ++D->Index;
+}
+
+
+
+static void FixArrayQualifiers (Type* T)
+/* Using typedefs, it is possible to generate declarations that have
+ * type qualifiers attached to an array, not the element type. Go and
+ * fix these here.
+ */
+{
+    TypeCode Q = T_QUAL_NONE;
+    while (T->C != T_END) {
+        if (IsTypeArray (T)) {
+            /* Extract any type qualifiers */
+            Q |= T->C & T_MASK_QUAL;
+            T->C = UnqualifiedType (T->C);
+        } else {
+            /* Add extracted type qualifiers here */
+            T->C |= Q;
+            Q = T_QUAL_NONE;
+        }
+        ++T;
+    }
+
+    /* Q must be empty now */
+    CHECK (Q == T_QUAL_NONE);
 }
 
 
@@ -259,7 +303,7 @@ static void ParseEnumDecl (void)
        /* We expect an identifier */
        if (CurTok.Tok != TOK_IDENT) {
            Error ("Identifier expected");
-           continue;
+           continue;
        }
 
        /* Remember the identifier and skip it */
@@ -277,7 +321,7 @@ static void ParseEnumDecl (void)
        /* Add an entry to the symbol table */
        AddConstSym (Ident, type_int, SC_ENUM, EnumVal++);
 
-       /* Check for end of definition */
+       /* Check for end of definition */
        if (CurTok.Tok != TOK_COMMA)
            break;
        NextToken ();
@@ -287,7 +331,7 @@ static void ParseEnumDecl (void)
 
 
 
-static SymEntry* ParseStructDecl (const char* Name, type StructType)
+static SymEntry* ParseStructDecl (const char* Name, TypeCode StructType)
 /* Parse a struct/union declaration. */
 {
 
@@ -331,7 +375,7 @@ static SymEntry* ParseStructDecl (const char* Name, type StructType)
        /* Get the type of the entry */
        DeclSpec Spec;
        InitDeclSpec (&Spec);
-       ParseTypeSpec (&Spec, -1);
+       ParseTypeSpec (&Spec, -1, T_QUAL_NONE);
 
        /* Read fields with this type */
        while (1) {
@@ -365,7 +409,7 @@ static SymEntry* ParseStructDecl (const char* Name, type StructType)
                     }
                     FlexibleMember = 1;
                     /* Assume zero for size calculations */
-                    Encode (Decl.Type + 1, FLEXIBLE);
+                    SetElementCount (Decl.Type, FLEXIBLE);
                 } else {
                     StructSize += CheckedSizeOf (Decl.Type);
                 }
@@ -377,7 +421,7 @@ static SymEntry* ParseStructDecl (const char* Name, type StructType)
                if (FieldSize > StructSize) {
                    StructSize = FieldSize;
                }
-           }
+           }
 
            /* Add a field entry to the table */
            AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, Offs);
@@ -387,7 +431,7 @@ static SymEntry* ParseStructDecl (const char* Name, type StructType)
             }
            NextToken ();
        }
-       ConsumeSemi ();
+       ConsumeSemi ();
     }
 
     /* Skip the closing brace */
@@ -403,47 +447,46 @@ static SymEntry* ParseStructDecl (const char* Name, type StructType)
 
 
 
-static void ParseTypeSpec (DeclSpec* D, int Default)
+static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers)
 /* Parse a type specificier */
 {
     ident      Ident;
     SymEntry*  Entry;
-    type       StructType;
-    type       Qualifiers;     /* Type qualifiers */
+    TypeCode    StructType;
 
     /* Assume we have an explicit type */
     D->Flags &= ~DS_DEF_TYPE;
 
     /* Read type qualifiers if we have any */
-    Qualifiers = OptionalQualifiers (T_QUAL_NONE);
+    Qualifiers = OptionalQualifiers (Qualifiers);
 
     /* Look at the data type */
     switch (CurTok.Tok) {
 
        case TOK_VOID:
            NextToken ();
-           D->Type[0] = T_VOID;
-           D->Type[1] = T_END;
+           D->Type[0].C = T_VOID;
+           D->Type[1].C = T_END;
            break;
 
        case TOK_CHAR:
            NextToken ();
-           D->Type[0] = GetDefaultChar();
-           D->Type[1] = T_END;
+           D->Type[0].C = GetDefaultChar();
+           D->Type[1].C = T_END;
            break;
 
        case TOK_LONG:
            NextToken ();
            if (CurTok.Tok == TOK_UNSIGNED) {
                NextToken ();
-               optionalint ();
-               D->Type[0] = T_ULONG;
-               D->Type[1] = T_END;
+               OptionalInt ();
+               D->Type[0].C = T_ULONG;
+               D->Type[1].C = T_END;
            } else {
-               optionalsigned ();
-               optionalint ();
-               D->Type[0] = T_LONG;
-               D->Type[1] = T_END;
+               OptionalSigned ();
+               OptionalInt ();
+               D->Type[0].C = T_LONG;
+               D->Type[1].C = T_END;
            }
            break;
 
@@ -451,21 +494,21 @@ static void ParseTypeSpec (DeclSpec* D, int Default)
            NextToken ();
            if (CurTok.Tok == TOK_UNSIGNED) {
                NextToken ();
-               optionalint ();
-               D->Type[0] = T_USHORT;
-               D->Type[1] = T_END;
+               OptionalInt ();
+               D->Type[0].C = T_USHORT;
+               D->Type[1].C = T_END;
            } else {
-               optionalsigned ();
-               optionalint ();
-               D->Type[0] = T_SHORT;
-               D->Type[1] = T_END;
+               OptionalSigned ();
+               OptionalInt ();
+               D->Type[0].C = T_SHORT;
+               D->Type[1].C = T_END;
            }
-           break;
+           break;
 
        case TOK_INT:
            NextToken ();
-           D->Type[0] = T_INT;
-           D->Type[1] = T_END;
+           D->Type[0].C = T_INT;
+           D->Type[1].C = T_END;
            break;
 
        case TOK_SIGNED:
@@ -474,22 +517,22 @@ static void ParseTypeSpec (DeclSpec* D, int Default)
 
                        case TOK_CHAR:
                    NextToken ();
-                   D->Type[0] = T_SCHAR;
-                   D->Type[1] = T_END;
+                   D->Type[0].C = T_SCHAR;
+                   D->Type[1].C = T_END;
                    break;
 
                case TOK_SHORT:
                    NextToken ();
-                   optionalint ();
-                   D->Type[0] = T_SHORT;
-                   D->Type[1] = T_END;
+                   OptionalInt ();
+                   D->Type[0].C = T_SHORT;
+                   D->Type[1].C = T_END;
                    break;
 
                case TOK_LONG:
                    NextToken ();
-                   optionalint ();
-                   D->Type[0] = T_LONG;
-                   D->Type[1] = T_END;
+                   OptionalInt ();
+                   D->Type[0].C = T_LONG;
+                   D->Type[1].C = T_END;
                    break;
 
                case TOK_INT:
@@ -497,8 +540,8 @@ static void ParseTypeSpec (DeclSpec* D, int Default)
                    /* FALL THROUGH */
 
                default:
-                   D->Type[0] = T_INT;
-                   D->Type[1] = T_END;
+                   D->Type[0].C = T_INT;
+                   D->Type[1].C = T_END;
                    break;
            }
            break;
@@ -509,22 +552,22 @@ static void ParseTypeSpec (DeclSpec* D, int Default)
 
                        case TOK_CHAR:
                    NextToken ();
-                   D->Type[0] = T_UCHAR;
-                   D->Type[1] = T_END;
+                   D->Type[0].C = T_UCHAR;
+                   D->Type[1].C = T_END;
                    break;
 
                case TOK_SHORT:
                    NextToken ();
-                   optionalint ();
-                   D->Type[0] = T_USHORT;
-                   D->Type[1] = T_END;
+                   OptionalInt ();
+                   D->Type[0].C = T_USHORT;
+                   D->Type[1].C = T_END;
                    break;
 
                case TOK_LONG:
                    NextToken ();
-                   optionalint ();
-                   D->Type[0] = T_ULONG;
-                   D->Type[1] = T_END;
+                   OptionalInt ();
+                   D->Type[0].C = T_ULONG;
+                   D->Type[1].C = T_END;
                    break;
 
                case TOK_INT:
@@ -532,22 +575,22 @@ static void ParseTypeSpec (DeclSpec* D, int Default)
                    /* FALL THROUGH */
 
                default:
-                   D->Type[0] = T_UINT;
-                   D->Type[1] = T_END;
+                   D->Type[0].C = T_UINT;
+                   D->Type[1].C = T_END;
                    break;
            }
            break;
 
         case TOK_FLOAT:
            NextToken ();
-           D->Type[0] = T_FLOAT;
-           D->Type[1] = T_END;
+           D->Type[0].C = T_FLOAT;
+           D->Type[1].C = T_END;
            break;
 
         case TOK_DOUBLE:
            NextToken ();
-           D->Type[0] = T_DOUBLE;
-           D->Type[1] = T_END;
+           D->Type[0].C = T_DOUBLE;
+           D->Type[1].C = T_END;
            break;
 
        case TOK_STRUCT:
@@ -566,18 +609,18 @@ static void ParseTypeSpec (DeclSpec* D, int Default)
            /* Declare the struct in the current scope */
            Entry = ParseStructDecl (Ident, StructType);
                    /* Encode the struct entry into the type */
-           D->Type[0] = StructType;
-           EncodePtr (D->Type+1, Entry);
-           D->Type[DECODE_SIZE+1] = T_END;
+           D->Type[0].C = StructType;
+           SetSymEntry (D->Type, Entry);
+           D->Type[1].C = T_END;
            break;
 
        case TOK_ENUM:
            NextToken ();
-           if (CurTok.Tok != TOK_LCURLY) {
+           if (CurTok.Tok != TOK_LCURLY) {
                /* Named enum */
                if (CurTok.Tok == TOK_IDENT) {
                    /* Find an entry with this name */
-                   Entry = FindTagSym (CurTok.Ident);
+                   Entry = FindTagSym (CurTok.Ident);
                    if (Entry) {
                        if (SymIsLocal (Entry) && (Entry->Flags & SC_ENUM) == 0) {
                            Error ("Symbol `%s' is already different kind", Entry->Name);
@@ -587,24 +630,24 @@ static void ParseTypeSpec (DeclSpec* D, int Default)
                    }
                    /* Skip the identifier */
                    NextToken ();
-               } else {
+               } else {
                    Error ("Identifier expected");
-               }
-           }
-           /* Remember we have an extra type decl */
-           D->Flags |= DS_EXTRA_TYPE;
-           /* Parse the enum decl */
+               }
+           }
+           /* Remember we have an extra type decl */
+           D->Flags |= DS_EXTRA_TYPE;
+           /* Parse the enum decl */
            ParseEnumDecl ();
-           D->Type[0] = T_INT;
-           D->Type[1] = T_END;
+           D->Type[0].C = T_INT;
+           D->Type[1].C = T_END;
            break;
 
         case TOK_IDENT:
-           Entry = FindSym (CurTok.Ident);
-           if (Entry && SymIsTypeDef (Entry)) {
+           Entry = FindSym (CurTok.Ident);
+           if (Entry && SymIsTypeDef (Entry)) {
                        /* It's a typedef */
                NextToken ();
-               TypeCpy (D->Type, Entry->Type);
+               TypeCpy (D->Type, Entry->Type);
                break;
            }
            /* FALL THROUGH */
@@ -612,30 +655,29 @@ static void ParseTypeSpec (DeclSpec* D, int Default)
        default:
            if (Default < 0) {
                Error ("Type expected");
-               D->Type[0] = T_INT;
-               D->Type[1] = T_END;
+               D->Type[0].C = T_INT;
+               D->Type[1].C = T_END;
            } else {
-               D->Flags  |= DS_DEF_TYPE;
-               D->Type[0] = (type) Default;
-               D->Type[1] = T_END;
-           }
-           break;
+               D->Flags |= DS_DEF_TYPE;
+               D->Type[0].C = (TypeCode) Default;
+               D->Type[1].C = T_END;
+           }
+           break;
     }
 
     /* There may also be qualifiers *after* the initial type */
-    D->Type[0] |= OptionalQualifiers (Qualifiers);
+    D->Type[0].C |= OptionalQualifiers (Qualifiers);
 }
 
 
 
-static type* ParamTypeCvt (type* T)
+static Type* ParamTypeCvt (Type* T)
 /* If T is an array, convert it to a pointer else do nothing. Return the
  * resulting type.
  */
 {
     if (IsTypeArray (T)) {
-               T += DECODE_SIZE;
-       T[0] = T_PTR;
+               T->C = T_PTR;
     }
     return T;
 }
@@ -654,7 +696,7 @@ static void ParseOldStyleParamList (FuncDesc* F)
        }
 
        /* Create a symbol table entry with type int */
-       AddLocalSym (CurTok.Ident, type_int, SC_AUTO | SC_PARAM | SC_DEF, 0);
+       AddLocalSym (CurTok.Ident, type_int, SC_AUTO | SC_PARAM | SC_DEF | SC_DEFTYPE, 0);
 
        /* Count arguments */
                ++F->ParamCount;
@@ -687,24 +729,34 @@ static void ParseOldStyleParamList (FuncDesc* F)
         * we ignore all this, since we use auto anyway.
         */
        if ((Spec.StorageClass & SC_AUTO) == 0 &&
-           (Spec.StorageClass & SC_REGISTER) == 0) {
+           (Spec.StorageClass & SC_REGISTER) == 0) {
            Error ("Illegal storage class");
        }
 
        /* Parse a comma separated variable list */
        while (1) {
 
-           Declaration         Decl;
+           Declaration         Decl;
 
            /* Read the parameter */
            ParseDecl (&Spec, &Decl, DM_NEED_IDENT);
            if (Decl.Ident[0] != '\0') {
 
-               /* We have a name given. Search for the symbol */
+               /* We have a name given. Search for the symbol */
                SymEntry* Sym = FindLocalSym (Decl.Ident);
                if (Sym) {
-                   /* Found it, change the default type to the one given */
-                   ChangeSymType (Sym, ParamTypeCvt (Decl.Type));
+                    /* Check if we already changed the type for this
+                     * parameter
+                     */
+                    if (Sym->Flags & SC_DEFTYPE) {
+                        /* Found it, change the default type to the one given */
+                        ChangeSymType (Sym, ParamTypeCvt (Decl.Type));
+                        /* Reset the "default type" flag */
+                        Sym->Flags &= ~SC_DEFTYPE;
+                    } else {
+                        /* Type has already been changed */
+                        Error ("Redefinition for parameter `%s'", Sym->Name);
+                    }
                } else {
                    Error ("Unknown identifier: `%s'", Decl.Ident);
                }
@@ -737,7 +789,7 @@ static void ParseAnsiParamList (FuncDesc* F)
 
        /* Allow an ellipsis as last parameter */
        if (CurTok.Tok == TOK_ELLIPSIS) {
-           NextToken ();
+           NextToken ();
            F->Flags |= FD_VARIADIC;
            break;
        }
@@ -807,7 +859,7 @@ static void ParseAnsiParamList (FuncDesc* F)
 
 
 
-static FuncDesc* ParseFuncDecl (const DeclSpec* Spec)
+static FuncDesc* ParseFuncDecl (void)
 /* Parse the argument list of a function. */
 {
     unsigned Offs;
@@ -834,19 +886,11 @@ static FuncDesc* ParseFuncDecl (const DeclSpec* Spec)
         */
        Sym = FindSym (CurTok.Ident);
        if (Sym == 0 || !SymIsTypeDef (Sym)) {
-           /* Old style (K&R) function. Assume variable param list. */
-           F->Flags |= (FD_OLDSTYLE | FD_VARIADIC);
+           /* Old style (K&R) function. */
+           F->Flags |= FD_OLDSTYLE;
        }
     }
 
-    /* Check for an implicit int return in the function */
-    if ((Spec->Flags & DS_DEF_TYPE) != 0 &&
-        Spec->Type[0] == T_INT                  &&
-        Spec->Type[1] == T_END) {
-        /* Function has an implicit int return */
-        F->Flags |= FD_OLDSTYLE_INTRET;
-    }
-
     /* Parse params */
     if ((F->Flags & FD_OLDSTYLE) == 0) {
        /* New style function */
@@ -906,9 +950,9 @@ static unsigned FunctionModifierFlags (void)
         /* Get the flag bit for the next token */
         unsigned F = FD_NONE;
         switch (CurTok.Tok) {
-            case TOK_FASTCALL:  F = FD_FASTCALL;       break;
-            case TOK_NEAR:         F = FD_NEAR;        break;
-            case TOK_FAR:          F = FD_FAR;         break;
+            case TOK_FASTCALL:  F = FD_FASTCALL; break;
+            case TOK_NEAR:             F = FD_NEAR;     break;
+            case TOK_FAR:      F = FD_FAR;      break;
             default:            Internal ("Unexpected token: %d", CurTok.Tok);
         }
 
@@ -934,7 +978,7 @@ static unsigned FunctionModifierFlags (void)
 
 
 
-static void ApplyFunctionModifiers (type* T, unsigned Flags)
+static void ApplyFunctionModifiers (Type* T, unsigned Flags)
 /* Apply a set of function modifier flags to a function */
 {
     /* Get the function descriptor */
@@ -962,19 +1006,19 @@ static void Decl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
     /* Pointer to something */
     if (CurTok.Tok == TOK_STAR) {
 
-       type T;
+       TypeCode C;
 
         /* Skip the star */
                NextToken ();
 
        /* Allow optional const or volatile qualifiers */
-               T = T_PTR | OptionalQualifiers (T_QUAL_NONE);
+               C = T_PTR | OptionalQualifiers (T_QUAL_NONE);
 
         /* Parse the type, the pointer points to */
                Decl (Spec, D, Mode);
 
        /* Add the type */
-       AddTypeToDeclaration (D, T);
+       AddTypeToDeclaration (D, C);
                return;
     }
 
@@ -982,23 +1026,23 @@ static void Decl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
     if (CurTok.Tok == TOK_FASTCALL || CurTok.Tok == TOK_NEAR || CurTok.Tok == TOK_FAR) {
 
        /* Remember the current type pointer */
-       type* T = D->Type + D->Index;
+       Type* T = D->Type + D->Index;
 
-       /* Read the flags */
-       unsigned Flags = FunctionModifierFlags ();
+       /* Read the flags */
+       unsigned Flags = FunctionModifierFlags ();
 
-       /* Parse the function */
-       Decl (Spec, D, Mode);
+       /* Parse the function */
+       Decl (Spec, D, Mode);
 
-       /* Check that we have a function */
-       if (!IsTypeFunc (T) && !IsTypeFuncPtr (T)) {
-           Error ("Function modifier applied to non function");
-       } else {
+       /* Check that we have a function */
+       if (!IsTypeFunc (T) && !IsTypeFuncPtr (T)) {
+           Error ("Function modifier applied to non function");
+       } else {
             ApplyFunctionModifiers (T, Flags);
         }
 
-       /* Done */
-       return;
+       /* Done */
+       return;
     }
 
     if (CurTok.Tok == TOK_LPAREN) {
@@ -1033,19 +1077,19 @@ static void Decl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
                if (CurTok.Tok == TOK_LPAREN) {
 
                    /* Function declaration */
-           FuncDesc* F;
+           FuncDesc* F;
                    NextToken ();
 
-           /* Parse the function declaration */
-                   F = ParseFuncDecl (Spec);
+           /* Parse the function declaration */
+                   F = ParseFuncDecl ();
 
-           /* Add the function type. Be sure to bounds check the type buffer */
-           AddEncodeToDeclaration (D, T_FUNC, (unsigned long) F);
+           /* Add the function type. Be sure to bounds check the type buffer */
+           AddFuncTypeToDeclaration (D, F);
                } else {
-           /* Array declaration */
+           /* Array declaration */
                    long Size = UNSPECIFIED;
                    NextToken ();
-           /* Read the size if it is given */
+           /* Read the size if it is given */
                    if (CurTok.Tok != TOK_RBRACK) {
                ExprDesc Expr;
                        ConstAbsIntExpr (hie1, &Expr);
@@ -1061,8 +1105,8 @@ static void Decl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
                    }
                    ConsumeRBrack ();
 
-           /* Add the type */
-           AddEncodeToDeclaration (D, T_ARRAY, Size);
+           /* Add the array type with the size */
+           AddArrayToDeclaration (D, Size);
                }
     }
 }
@@ -1075,7 +1119,7 @@ static void Decl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
 
 
 
-type* ParseType (type* Type)
+Type* ParseType (Type* T)
 /* Parse a complete type specification */
 {
     DeclSpec Spec;
@@ -1083,16 +1127,16 @@ type* ParseType (type* Type)
 
     /* Get a type without a default */
     InitDeclSpec (&Spec);
-    ParseTypeSpec (&Spec, -1);
+    ParseTypeSpec (&Spec, -1, T_QUAL_NONE);
 
     /* Parse additional declarators */
     ParseDecl (&Spec, &Decl, DM_NO_IDENT);
 
     /* Copy the type to the target buffer */
-    TypeCpy (Type, Decl.Type);
+    TypeCpy (T, Decl.Type);
 
     /* Return a pointer to the target buffer */
-    return Type;
+    return T;
 }
 
 
@@ -1110,32 +1154,81 @@ void ParseDecl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
     NeedTypeSpace (D, TypeLen (Spec->Type) + 1);       /* Bounds check */
     TypeCpy (D->Type + D->Index, Spec->Type);
 
+    /* Fix any type qualifiers attached to an array type */
+    FixArrayQualifiers (D->Type);
+
+    /* Check several things for function or function pointer types */
+    if (IsTypeFunc (D->Type) || IsTypeFuncPtr (D->Type)) {
+
+        /* A function. Check the return type */
+        Type* RetType = GetFuncReturn (D->Type);
+
+        /* Functions may not return functions or arrays */
+        if (IsTypeFunc (RetType)) {
+            Error ("Functions are not allowed to return functions");
+        } else if (IsTypeArray (RetType)) {
+            Error ("Functions are not allowed to return arrays");
+        }
+
+        /* The return type must not be qualified */
+        if (GetQualifier (RetType) != T_QUAL_NONE && RetType[1].C == T_END) {
+
+            if (GetType (RetType) == T_TYPE_VOID) {
+                /* A qualified void type is always an error */
+                Error ("function definition has qualified void return type");
+            } else {
+                /* For others, qualifiers are ignored */
+                Warning ("type qualifiers ignored on function return type");
+                RetType[0].C = UnqualifiedType (RetType[0].C);
+            }
+        }
+
+        /* Warn about an implicit int return in the function */
+        if ((Spec->Flags & DS_DEF_TYPE) != 0 &&
+            RetType[0].C == T_INT && RetType[1].C == T_END) {
+            /* Function has an implicit int return. Output a warning if we don't
+             * have the C89 standard enabled explicitly.
+             */
+            if (IS_Get (&Standard) >= STD_C99) {
+                Warning ("Implicit `int' return type is an obsolete feature");
+            }
+            GetFuncDesc (D->Type)->Flags |= FD_OLDSTYLE_INTRET;
+        }
+
+    }
+
     /* Check the size of the generated type */
     if (!IsTypeFunc (D->Type) && !IsTypeVoid (D->Type)) {
-       unsigned Size = SizeOf (D->Type);
-       if (Size >= 0x10000) {
-           if (D->Ident[0] != '\0') {
-               Error ("Size of `%s' is invalid (0x%06X)", D->Ident, Size);
-           } else {
-               Error ("Invalid size in declaration (0x%06X)", Size);
-           }
-       }
+        unsigned Size = SizeOf (D->Type);
+        if (Size >= 0x10000) {
+            if (D->Ident[0] != '\0') {
+                Error ("Size of `%s' is invalid (0x%06X)", D->Ident, Size);
+            } else {
+                Error ("Invalid size in declaration (0x%06X)", Size);
+            }
+        }
     }
+
 }
 
 
 
-void ParseDeclSpec (DeclSpec* D, unsigned DefStorage, int DefType)
+void ParseDeclSpec (DeclSpec* D, unsigned DefStorage, long DefType)
 /* Parse a declaration specification */
 {
+    TypeCode Qualifiers;
+
     /* Initialize the DeclSpec struct */
     InitDeclSpec (D);
 
-    /* First, get the storage class specifier for this declaration */
+    /* There may be qualifiers *before* the storage class specifier */
+    Qualifiers = OptionalQualifiers (T_QUAL_NONE);
+
+    /* Now get the storage class specifier for this declaration */
     ParseStorageClass (D, DefStorage);
 
-    /* Parse the type specifiers */
-    ParseTypeSpec (D, DefType);
+    /* Parse the type specifiers passing any initial type qualifiers */
+    ParseTypeSpec (D, DefType, Qualifiers);
 }
 
 
@@ -1255,7 +1348,7 @@ static void DefineData (ExprDesc* Expr)
 
 
 
-static unsigned ParseScalarInit (type* T)
+static unsigned ParseScalarInit (Type* T)
 /* Parse initializaton for scalar data types. Return the number of data bytes. */
 {
     ExprDesc ED;
@@ -1286,7 +1379,7 @@ static unsigned ParseScalarInit (type* T)
 
 
 
-static unsigned ParsePointerInit (type* T)
+static unsigned ParsePointerInit (Type* T)
 /* Parse initializaton for pointer data types. Return the number of data bytes. */
 {
     /* Optional opening brace */
@@ -1309,13 +1402,13 @@ static unsigned ParsePointerInit (type* T)
 
 
 
-static unsigned ParseArrayInit (type* T, int AllowFlexibleMembers)
+static unsigned ParseArrayInit (Type* T, int AllowFlexibleMembers)
 /* Parse initializaton for arrays. Return the number of data bytes. */
 {
     int Count;
 
     /* Get the array data */
-    type* ElementType    = GetElementType (T);
+    Type* ElementType    = GetElementType (T);
     unsigned ElementSize = CheckedSizeOf (ElementType);
     long ElementCount    = GetElementCount (T);
 
@@ -1390,10 +1483,9 @@ static unsigned ParseArrayInit (type* T, int AllowFlexibleMembers)
         ConsumeRCurly ();
     }
 
-
     if (ElementCount == UNSPECIFIED) {
         /* Number of elements determined by initializer */
-        Encode (T + 1, Count);
+        SetElementCount (T, Count);
         ElementCount = Count;
     } else if (ElementCount == FLEXIBLE && AllowFlexibleMembers) {
         /* In non ANSI mode, allow initialization of flexible array
@@ -1410,7 +1502,7 @@ static unsigned ParseArrayInit (type* T, int AllowFlexibleMembers)
 
 
 
-static unsigned ParseStructInit (type* Type, int AllowFlexibleMembers)
+static unsigned ParseStructInit (Type* T, int AllowFlexibleMembers)
 /* Parse initialization of a struct or union. Return the number of data bytes. */
 {
     SymEntry* Entry;
@@ -1423,7 +1515,7 @@ static unsigned ParseStructInit (type* Type, int AllowFlexibleMembers)
     ConsumeLCurly ();
 
     /* Get a pointer to the struct entry from the type */
-    Entry = DecodePtr (Type + 1);
+    Entry = GetSymEntry (T);
 
     /* Get the size of the struct from the symbol table entry */
     StructSize = Entry->V.S.Size;
@@ -1495,7 +1587,7 @@ static unsigned ParseVoidInit (void)
     Size = 0;
     do {
        ConstExpr (hie1, &Expr);
-       switch (UnqualifiedType (Expr.Type[0])) {
+       switch (UnqualifiedType (Expr.Type[0].C)) {
 
            case T_SCHAR:
            case T_UCHAR:
@@ -1553,10 +1645,10 @@ static unsigned ParseVoidInit (void)
 
 
 
-static unsigned ParseInitInternal (type* T, int AllowFlexibleMembers)
+static unsigned ParseInitInternal (Type* T, int AllowFlexibleMembers)
 /* Parse initialization of variables. Return the number of data bytes. */
 {
-    switch (UnqualifiedType (*T)) {
+    switch (UnqualifiedType (T->C)) {
 
        case T_SCHAR:
        case T_UCHAR:
@@ -1594,7 +1686,7 @@ static unsigned ParseInitInternal (type* T, int AllowFlexibleMembers)
 
 
 
-unsigned ParseInit (type* T)
+unsigned ParseInit (Type* T)
 /* Parse initialization of variables. Return the number of data bytes. */
 {
     /* Parse the initialization. Flexible array members can only be initialized