diff options
Diffstat (limited to 'usr.bin/xlint/lint1/decl.c')
-rw-r--r-- | usr.bin/xlint/lint1/decl.c | 3140 |
1 files changed, 0 insertions, 3140 deletions
diff --git a/usr.bin/xlint/lint1/decl.c b/usr.bin/xlint/lint1/decl.c deleted file mode 100644 index c40ba5b47db..00000000000 --- a/usr.bin/xlint/lint1/decl.c +++ /dev/null @@ -1,3140 +0,0 @@ -/* $OpenBSD: decl.c,v 1.30 2011/09/21 18:08:07 jsg Exp $ */ -/* $NetBSD: decl.c,v 1.11 1995/10/02 17:34:16 jpo Exp $ */ - -/* - * Copyright (c) 1994, 1995 Jochen Pohl - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Jochen Pohl for - * The NetBSD Project. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/param.h> -#include <limits.h> -#include <stdlib.h> -#include <string.h> -#include <stdbool.h> -#include <complex.h> - -#include "lint1.h" - -const char *unnamed = "<unnamed>"; - -/* contains various information and classification on types */ -ttab_t ttab[NTSPEC]; - -/* shared type structures for arithmetic types and void */ -static type_t *typetab; - -/* value of next enumerator during declaration of enum types */ -int enumval; - -/* - * pointer to top element of a stack which contains informations local - * to nested declarations - */ -dinfo_t *dcs; - -static type_t *tdeferr(type_t *, tspec_t); -static void settdsym(type_t *, sym_t *); -static tspec_t mrgtspec(tspec_t, tspec_t); -static void align(int, int); -static sym_t *newtag(sym_t *, scl_t, int, int); -static int eqargs(type_t *, type_t *, int *); -static int mnoarg(type_t *, int *); -static int chkosdef(sym_t *, sym_t *); -static int chkptdecl(sym_t *, sym_t *); -static sym_t *nsfunc(sym_t *, sym_t *); -static void osfunc(sym_t *, sym_t *); -static void ledecl(sym_t *); -static int chkinit(sym_t *); -static void chkausg(int, sym_t *); -static void chkvusg(int, sym_t *); -static void chklusg(sym_t *); -static void chktusg(sym_t *); -static void chkglvar(sym_t *); -static void glchksz(sym_t *); - -/* - * initializes all global vars used in declarations - */ -void -initdecl(void) -{ - int i; - static struct { - tspec_t it_tspec; - ttab_t it_ttab; - } ittab[] = { - { SIGNED, { 0, 0, 0, - SIGNED, UNSIGN, - 0, 0, 0, 0, 0, "signed" } }, - { UNSIGN, { 0, 0, 0, - SIGNED, UNSIGN, - 0, 0, 0, 0, 0, "unsigned" } }, - { BOOL, { sizeof (_Bool) * CHAR_BIT, CHAR_BIT, 1, - BOOL, BOOL, - 1, 1, 0, 1, 1, "_Bool" } }, - { CHAR, { CHAR_BIT, CHAR_BIT, 20, - SCHAR, UCHAR, - 1, 0, 0, 1, 1, "char" } }, - { SCHAR, { CHAR_BIT, CHAR_BIT, 20, - SCHAR, UCHAR, - 1, 0, 0, 1, 1, "signed char" } }, - { UCHAR, { CHAR_BIT, CHAR_BIT, 20, - SCHAR, UCHAR, - 1, 1, 0, 1, 1, "unsigned char" } }, - { SHORT, { sizeof (short) * CHAR_BIT, 2 * CHAR_BIT, 30, - SHORT, USHORT, - 1, 0, 0, 1, 1, "short" } }, - { USHORT, { sizeof (u_short) * CHAR_BIT, 2 * CHAR_BIT, 30, - SHORT, USHORT, - 1, 1, 0, 1, 1, "unsigned short" } }, - { INT, { sizeof (int) * CHAR_BIT, 3 * CHAR_BIT, 40, - INT, UINT, - 1, 0, 0, 1, 1, "int" } }, - { UINT, { sizeof (u_int) * CHAR_BIT, 3 * CHAR_BIT, 40, - INT, UINT, - 1, 1, 0, 1, 1, "unsigned int" } }, - { LONG, { sizeof (long) * CHAR_BIT, 4 * CHAR_BIT, 50, - LONG, ULONG, - 1, 0, 0, 1, 1, "long" } }, - { ULONG, { sizeof (u_long) * CHAR_BIT, 4 * CHAR_BIT, 50, - LONG, ULONG, - 1, 1, 0, 1, 1, "unsigned long" } }, - { QUAD, { sizeof (quad_t) * CHAR_BIT, 8 * CHAR_BIT, 60, - QUAD, UQUAD, - 1, 0, 0, 1, 1, "long long" } }, - { UQUAD, { sizeof (u_quad_t) * CHAR_BIT, 8 * CHAR_BIT, 60, - QUAD, UQUAD, - 1, 1, 0, 1, 1, "unsigned long long" } }, - { FLOAT, { sizeof (float) * CHAR_BIT, 4 * CHAR_BIT, -1, - FLOAT, FLOAT, - 0, 0, 1, 1, 1, "float" } }, - { DOUBLE, { sizeof (double) * CHAR_BIT, 8 * CHAR_BIT, -1, - DOUBLE, DOUBLE, - 0, 0, 1, 1, 1, "double" } }, - { LDOUBLE, { sizeof (ldbl_t) * CHAR_BIT, 16 * CHAR_BIT, -1, - LDOUBLE, LDOUBLE, - 0, 0, 1, 1, 1, "long double" } }, - { COMPLEX, { sizeof (float _Complex) * CHAR_BIT, - 8 * CHAR_BIT, -1, - COMPLEX, COMPLEX, - 0, 0, 1, 1, 3, "float _Complex" } }, - { DCOMPLEX, { sizeof (double _Complex) * CHAR_BIT, - 16 * CHAR_BIT, -1, - DCOMPLEX, DCOMPLEX, - 0, 0, 1, 1, 3, "double _Complex" } }, - { LDCOMPLEX,{ sizeof (long double _Complex) * CHAR_BIT, - 32 * CHAR_BIT, -1, - LDCOMPLEX, LDCOMPLEX, - 0, 0, 1, 1, 3, "long double _Complex" } }, -#if 0 - { IMAGINARY,{ sizeof (float _Imaginary) * CHAR_BIT, - 4 * CHAR_BIT, -1, - IMAGINARY, IMAGINARY, - 0, 0, 1, 1, 2, "float _Imaginary" } }, - { DIMAGINARY,{ sizeof (double _Imaginary) * CHAR_BIT, - 8 * CHAR_BIT, -1, - DIMAGINARY, DIMAGINARY, - 0, 0, 1, 1, 2, "double _Imaginary" } }, - { LDIMAGINARY,{ sizeof (long double _Imaginary) * CHAR_BIT, - 16 * CHAR_BIT, -1, - LDIMAGINARY, LDIMAGINARY, - 0, 0, 1, 1, 2, "long double _Imaginary" } }, -#endif - { VOID, { -1, -1, -1, - VOID, VOID, - 0, 0, 0, 0, 0, "void" } }, - { STRUCT, { -1, -1, -1, - STRUCT, STRUCT, - 0, 0, 0, 0, 0, "struct" } }, - { UNION, { -1, -1, -1, - UNION, UNION, - 0, 0, 0, 0, 0, "union" } }, - { ENUM, { sizeof (int) * CHAR_BIT, 3 * CHAR_BIT, 40, - ENUM, ENUM, - 1, 0, 0, 1, 1, "enum" } }, - { PTR, { sizeof (void *) * CHAR_BIT, 4 * CHAR_BIT, -1, - PTR, PTR, - 0, 1, 0, 0, 1, "pointer" } }, - { ARRAY, { -1, -1, -1, - ARRAY, ARRAY, - 0, 0, 0, 0, 0, "array" } }, - { FUNC, { -1, -1, -1, - FUNC, FUNC, - 0, 0, 0, 0, 0, "function" } }, - }; - - /* declaration stack */ - dcs = xcalloc(1, sizeof (dinfo_t)); - dcs->d_ctx = EXTERN; - dcs->d_ldlsym = &dcs->d_dlsyms; - - /* type information and classification */ - for (i = 0; i < sizeof (ittab) / sizeof (ittab[0]); i++) - STRUCT_ASSIGN(ttab[ittab[i].it_tspec], ittab[i].it_ttab); - if (!pflag) { - for (i = 0; i < NTSPEC; i++) - ttab[i].tt_psz = ttab[i].tt_sz; - } - - /* shared type structures */ - typetab = xcalloc(NTSPEC, sizeof (type_t)); - for (i = 0; i < NTSPEC; i++) - typetab[i].t_tspec = NOTSPEC; - typetab[BOOL].t_tspec = BOOL; - typetab[CHAR].t_tspec = CHAR; - typetab[SCHAR].t_tspec = SCHAR; - typetab[UCHAR].t_tspec = UCHAR; - typetab[SHORT].t_tspec = SHORT; - typetab[USHORT].t_tspec = USHORT; - typetab[INT].t_tspec = INT; - typetab[UINT].t_tspec = UINT; - typetab[LONG].t_tspec = LONG; - typetab[ULONG].t_tspec = ULONG; - typetab[QUAD].t_tspec = QUAD; - typetab[UQUAD].t_tspec = UQUAD; - typetab[FLOAT].t_tspec = FLOAT; - typetab[DOUBLE].t_tspec = DOUBLE; - typetab[LDOUBLE].t_tspec = LDOUBLE; - typetab[COMPLEX].t_tspec = COMPLEX; - typetab[DCOMPLEX].t_tspec = DCOMPLEX; - typetab[LDCOMPLEX].t_tspec = LDCOMPLEX; - typetab[IMAGINARY].t_tspec = IMAGINARY; - typetab[DIMAGINARY].t_tspec = DIMAGINARY; - typetab[LDIMAGINARY].t_tspec = LDIMAGINARY; - typetab[VOID].t_tspec = VOID; - /* - * Next two are not real types. They are only used by the parser - * to return keywords "signed" and "unsigned" - */ - typetab[SIGNED].t_tspec = SIGNED; - typetab[UNSIGN].t_tspec = UNSIGN; -} - -/* - * Returns a shared type structure for arithmetic types and void. - * - * It's important to duplicate this structure (using duptyp() or tduptyp()) - * if it is to be modified (adding qualifiers or anything else). - */ -type_t * -gettyp(tspec_t t) -{ - return (&typetab[t]); -} - -type_t * -duptyp(const type_t *tp) -{ - type_t *ntp; - - ntp = getblk(sizeof (type_t)); - STRUCT_ASSIGN(*ntp, *tp); - return (ntp); -} - -/* - * Use tduptyp() instead of duptyp() inside expressions (if the - * allocated memory should be freed after the expr). - */ -type_t * -tduptyp(const type_t *tp) -{ - type_t *ntp; - - ntp = tgetblk(sizeof (type_t)); - STRUCT_ASSIGN(*ntp, *tp); - return (ntp); -} - -/* - * Returns 1 if the argument is void or an incomplete array, - * struct, union or enum type. - */ -int -incompl(type_t *tp) -{ - tspec_t t; - - if ((t = tp->t_tspec) == VOID) { - return (1); - } else if (t == ARRAY) { - return (tp->t_aincompl); - } else if (t == STRUCT || t == UNION) { - return (tp->t_str->sincompl); - } else if (t == ENUM) { - return (tp->t_enum->eincompl); - } - return (0); -} - -/* - * Set the flag for (in)complete array, struct, union or enum - * types. - */ -void -setcompl(type_t *tp, int ic) -{ - tspec_t t; - - if ((t = tp->t_tspec) == ARRAY) { - tp->t_aincompl = ic; - } else if (t == STRUCT || t == UNION) { - tp->t_str->sincompl = ic; - } else { - if (t != ENUM) - lerror("setcompl() 1"); - tp->t_enum->eincompl = ic; - } -} - -/* - * Remember the storage class of the current declaration in dcs->d_scl - * (the top element of the declaration stack) and detect multiple - * storage classes. - */ -void -addscl(scl_t sc) -{ - if (sc == INLINE) { - if (dcs->d_inline) - /* duplicate '%s' */ - warning(10, "inline"); - dcs->d_inline = 1; - return; - } - if (dcs->d_type != NULL || dcs->d_atyp != NOTSPEC || - dcs->d_smod != NOTSPEC || dcs->d_lmod != NOTSPEC) { - /* storage class after type is obsolescent */ - warning(83); - } - if (dcs->d_scl == NOSCL) { - dcs->d_scl = sc; - } else { - /* - * multiple storage classes. An error will be reported in - * deftyp(). - */ - dcs->d_mscl = 1; - } -} - -/* - * Remember the type, modifier or typedef name returned by the parser - * in *dcs (top element of decl stack). This information is used in - * deftyp() to build the type used for all declarators in this - * declaration. - * - * Is tp->t_typedef 1, the type comes from a previously defined typename. - * Otherwise it comes from a type specifier (int, long, ...) or a - * struct/union/enum tag. - */ -void -addtype(type_t *tp) -{ - tspec_t t; - - if (tp->t_typedef) { - if (dcs->d_type != NULL || dcs->d_atyp != NOTSPEC || - dcs->d_lmod != NOTSPEC || dcs->d_smod != NOTSPEC || - dcs->d_dmod != NOTSPEC) { - /* - * something like "typedef int a; int a b;" - * This should not happen with current grammar. - */ - lerror("addtype()"); - } - dcs->d_type = tp; - return; - } - - t = tp->t_tspec; - - if (t == STRUCT || t == UNION || t == ENUM) { - /* - * something like "int struct a ..." - * struct/union/enum with anything else is not allowed - */ - if (dcs->d_type != NULL || dcs->d_atyp != NOTSPEC || - dcs->d_lmod != NOTSPEC || dcs->d_smod != NOTSPEC || - dcs->d_dmod != NOTSPEC) { - /* - * remember that an error must be reported in - * deftyp(). - */ - dcs->d_terr = 1; - dcs->d_atyp = dcs->d_smod = dcs->d_lmod = - dcs->d_dmod = NOTSPEC; - } - dcs->d_type = tp; - return; - } - - if (dcs->d_type != NULL && !dcs->d_type->t_typedef) { - /* - * something like "struct a int" - * struct/union/enum with anything else is not allowed - */ - dcs->d_terr = 1; - return; - } - - if (t == LONG && dcs->d_lmod == LONG) { - /* "long long" or "long ... long" */ - t = QUAD; - dcs->d_lmod = NOTSPEC; - if (!quadflg) - /* %s C does not support 'long long' */ - (void)gnuism(265, "ANSI"); - } - - if (dcs->d_type != NULL && dcs->d_type->t_typedef) { - /* something like "typedef int a; a long ..." */ - dcs->d_type = tdeferr(dcs->d_type, t); - return; - } - - /* now it can be only a combination of arithmetic types and void */ - if (t == SIGNED || t == UNSIGN) { - /* remeber specifiers "signed" and "unsigned" in dcs->d_smod */ - if (dcs->d_smod != NOTSPEC) - /* - * more than one "signed" and/or "unsigned"; print - * an error in deftyp() - */ - dcs->d_terr = 1; - dcs->d_smod = t; - } else if (t == SHORT || t == LONG || t == QUAD) { - /* - * remember specifiers "short", "long" and "long long" in - * dcs->d_lmod - */ - if (dcs->d_lmod != NOTSPEC) - /* more than one, print error in deftyp() */ - dcs->d_terr = 1; - dcs->d_lmod = t; - } else if (t == COMPLEX || t == IMAGINARY) { - /* - * remember specifiers "_Complex" and "_Imaginary" in - * dcs->d_dmod - */ - if (dcs->d_dmod != NOTSPEC) - /* more than one, print error in deftyp() */ - dcs->d_terr = 1; - dcs->d_dmod = t; - } else { - /* - * remember specifiers "void", "char", "int", "float" or - * "double" int dcs->d_atyp - */ - if (dcs->d_atyp != NOTSPEC) - /* more than one, print error in deftyp() */ - dcs->d_terr = 1; - dcs->d_atyp = t; - } -} - -/* - * called if a list of declaration specifiers contains a typedef name - * and other specifiers (except struct, union, enum, typedef name) - */ -static type_t * -tdeferr(type_t *td, tspec_t t) -{ - tspec_t t2; - - t2 = td->t_tspec; - - switch (t) { - case SIGNED: - case UNSIGN: - if (t2 == CHAR || t2 == SHORT || t2 == INT || t2 == LONG || - t2 == QUAD) { - /* modifying typedef with ... */ - warning(5, ttab[t].tt_name); - td = duptyp(gettyp(mrgtspec(t2, t))); - td->t_typedef = 1; - return (td); - } - break; - case SHORT: - if (t2 == INT || t2 == UINT) { - /* modifying typedef with ... */ - warning(5, "short"); - td = duptyp(gettyp(t2 == INT ? SHORT : USHORT)); - td->t_typedef = 1; - return (td); - } - break; - case LONG: - if (t2 == INT || t2 == UINT || t2 == LONG || t2 == ULONG || - t2 == FLOAT || t2 == DOUBLE || t2 == COMPLEX || - t2 == IMAGINARY) { - /* modifying typedef with ... */ - warning(5, "long"); - if (t2 == INT) { - td = gettyp(LONG); - } else if (t2 == UINT) { - td = gettyp(ULONG); - } else if (t2 == LONG) { - td = gettyp(QUAD); - } else if (t2 == ULONG) { - td = gettyp(UQUAD); - } else if (t2 == FLOAT) { - td = gettyp(DOUBLE); - } else if (t2 == DOUBLE) { - td = gettyp(LDOUBLE); - } else if (t2 == COMPLEX) { - td = gettyp(DCOMPLEX); - } else if (t2 == DCOMPLEX) { - td = gettyp(LDCOMPLEX); - } else if (t2 == IMAGINARY) { - td = gettyp(DIMAGINARY); - } else if (t2 == DIMAGINARY) { - td = gettyp(LDIMAGINARY); - } - td = duptyp(td); - td->t_typedef = 1; - return (td); - } - break; - /* LINTED (enumeration values not handled in switch) */ - } - - /* Anything other is not accepted. */ - - dcs->d_terr = 1; - return (td); -} - -/* - * Remember the symbol of a typedef name (2nd arg) in a struct, union - * or enum tag if the typedef name is the first defined for this tag. - * - * If the tag is unnamed, the typdef name is used for identification - * of this tag in lint2. Although its possible that more than one typedef - * name is defined for one tag, the first name defined should be unique - * if the tag is unnamed. - */ -static void -settdsym(type_t *tp, sym_t *sym) -{ - tspec_t t; - - if ((t = tp->t_tspec) == STRUCT || t == UNION) { - if (tp->t_str->stdef == NULL) - tp->t_str->stdef = sym; - } else if (t == ENUM) { - if (tp->t_enum->etdef == NULL) - tp->t_enum->etdef = sym; - } -} - -/* - * Remember a qualifier which is part of the declaration specifiers - * (and not the declarator) in the top element of the declaration stack. - * Also detect multiple qualifiers of the same kind. - - * The remembered qualifier is used by deftyp() to construct the type - * for all declarators. - */ -void -addqual(tqual_t q) -{ - if (q == CONST) { - if (dcs->d_const) { - /* duplicate "%s" */ - warning(10, "const"); - } - dcs->d_const = 1; - } else if (q == VOLATILE) { - if (dcs->d_volatile) { - /* duplicate "%s" */ - warning(10, "volatile"); - } - dcs->d_volatile = 1; - } else if (q == RESTRICT) { - if (dcs->d_restrict) { - /* duplicate "%s" */ - warning(10, "restrict"); - } - dcs->d_restrict = 1; - } else - lerror("addqual() 1"); -} - -/* - * Go to the next declaration level (structs, nested structs, blocks, - * argument declaration lists ...) - */ -void -pushdecl(scl_t sc) -{ - dinfo_t *di; - - if (dflag) - (void)printf("pushdecl(%d)\n", (int)sc); - - /* put a new element on the declaration stack */ - di = xcalloc(1, sizeof (dinfo_t)); - di->d_nxt = dcs; - dcs = di; - di->d_ctx = sc; - di->d_ldlsym = &di->d_dlsyms; -} - -/* - * Go back to previous declaration level - */ -void -popdecl(void) -{ - dinfo_t *di; - - if (dflag) - (void)printf("popdecl(%d)\n", (int)dcs->d_ctx); - - if (dcs->d_nxt == NULL) - lerror("popdecl() 1"); - di = dcs; - dcs = di->d_nxt; - switch (di->d_ctx) { - case EXTERN: - /* there is nothing after external declarations */ - lerror("popdecl() 2"); - /* NOTREACHED */ - case MOS: - case MOU: - case ENUMCON: - /* - * Symbols declared in (nested) structs or enums are - * part of the next level (they are removed from the - * symbol table if the symbols of the outher level are - * removed) - */ - if ((*dcs->d_ldlsym = di->d_dlsyms) != NULL) - dcs->d_ldlsym = di->d_ldlsym; - break; - case ARG: - /* - * All symbols in dcs->d_dlsyms are introduced in old style - * argument declarations (it's not clean, but possible). - * They are appended to the list of symbols declared in - * an old style argument identifier list or a new style - * parameter type list. - */ - if (di->d_dlsyms != NULL) { - *di->d_ldlsym = dcs->d_fpsyms; - dcs->d_fpsyms = di->d_dlsyms; - } - break; - case ABSTRACT: - /* - * casts and sizeof - * Append all symbols declared in the abstract declaration - * to the list of symbols declared in the surounding decl. - * or block. - * XXX I'm not sure whether they should be removed from the - * symbol table now or later. - */ - if ((*dcs->d_ldlsym = di->d_dlsyms) != NULL) - dcs->d_ldlsym = di->d_ldlsym; - break; - case AUTO: - /* check usage of local vars */ - chkusage(di); - /* FALLTHROUGH */ - case PARG: - /* usage of arguments will be checked by funcend() */ - rmsyms(di->d_dlsyms); - break; - default: - lerror("popdecl() 3"); - } - free(di); -} - -/* - * Set flag d_asm in all declaration stack elements up to the - * outermost one. - * - * This is used to mark compound statements which have, possibly in - * nested compound statements, asm statements. For these compound - * statements no warnings about unused or unitialized variables are - * printed. - * - * There is no need to clear d_asm in dinfo structs with context AUTO, - * because these structs are freed at the end of the compound statement. - * But it must be cleard in the outermost dinfo struct, which has - * context EXTERN. This could be done in clrtyp() and would work for - * C, but not for C++ (due to mixed statements and declarations). Thus - * we clear it in glclup(), which is used to do some cleanup after - * global declarations/definitions. - */ -void -setasm(void) -{ - dinfo_t *di; - - for (di = dcs; di != NULL; di = di->d_nxt) - di->d_asm = 1; -} - -/* - * Clean all elements of the top element of declaration stack which - * will be used by the next declaration - */ -void -clrtyp(void) -{ - dcs->d_atyp = dcs->d_smod = dcs->d_lmod = dcs->d_dmod = NOTSPEC; - dcs->d_scl = NOSCL; - dcs->d_type = NULL; - dcs->d_const = dcs->d_volatile = 0; - dcs->d_inline = 0; - dcs->d_mscl = dcs->d_terr = 0; - dcs->d_nedecl = 0; - dcs->d_notyp = 0; -} - -/* - * Merge the domain (_Complex or _Imaginary) into a type. Returns non-zero - * if the merge doesn't make sense. e.g., no "int _Complex". - */ -int -mergedomain(tspec_t *tp, tspec_t domain) -{ - if (domain == NOTSPEC) - return (0); - if (domain != COMPLEX && domain != IMAGINARY) - lerror("mergedomain()"); - switch (*tp) { - case FLOAT: - *tp = domain; - break; - case DOUBLE: - *tp = domain == COMPLEX ? DCOMPLEX : DIMAGINARY; - break; - case LDOUBLE: - *tp = domain == COMPLEX ? LDCOMPLEX : LDIMAGINARY; - break; - default: - return (1); - } - return (0); -} - -/* - * Create a type structure from the informations gathered in - * the declaration stack. - * Complain about storage classes which are not possible in current - * context. - */ -void -deftyp(void) -{ - tspec_t t, s, l, d; - type_t *tp; - scl_t scl; - - t = dcs->d_atyp; /* BOOL, CHAR, INT, FLOAT, - DOUBLE, VOID */ - s = dcs->d_smod; /* SIGNED, UNSIGNED */ - l = dcs->d_lmod; /* SHORT, LONG, QUAD */ - d = dcs->d_dmod; /* COMPLEX, IMAGINARY */ - tp = dcs->d_type; - scl = dcs->d_scl; - - if (t == NOTSPEC && s == NOTSPEC && l == NOTSPEC && tp == NULL) - dcs->d_notyp = 1; - - if (tp != NULL && (t != NOTSPEC || s != NOTSPEC || l != NOTSPEC)) { - /* should never happen */ - lerror("deftyp() 1"); - } - - if (tp == NULL) { - switch (t) { - case NOTSPEC: - t = INT; - /* FALLTHROUGH */ - case BOOL: - break; - case INT: - if (s == NOTSPEC) - s = SIGNED; - break; - case CHAR: - if (l != NOTSPEC) { - dcs->d_terr = 1; - l = NOTSPEC; - } - break; - case FLOAT: - if (l == LONG) { - l = NOTSPEC; - t = DOUBLE; - /* use 'double' instead of ... */ - warning(6); - } - break; - case DOUBLE: - if (l == LONG) { - l = NOTSPEC; - t = LDOUBLE; - } - break; - case VOID: - break; - default: - lerror("deftyp() 2"); - } - if (mergedomain(&t, d)) - dcs->d_terr = 1; - if (t != INT && t != CHAR && (s != NOTSPEC || l != NOTSPEC)) { - dcs->d_terr = 1; - l = s = NOTSPEC; - } - if (l != NOTSPEC) - t = l; - dcs->d_type = gettyp(mrgtspec(t, s)); - } - - if (dcs->d_mscl) { - /* only one storage class allowed */ - error(7); - } - if (dcs->d_terr) { - /* illegal type combination */ - error(4); - } - - if (dcs->d_ctx == EXTERN) { - if (scl == REG || scl == AUTO) { - /* illegal storage class */ - error(8); - scl = NOSCL; - } - } else if (dcs->d_ctx == ARG || dcs->d_ctx == PARG) { - if (scl != NOSCL && scl != REG) { - /* only "register" valid ... */ - error(9); - scl = NOSCL; - } - } - - dcs->d_scl = scl; - - if (dcs->d_const && dcs->d_type->t_const) { - if (!dcs->d_type->t_typedef) - lerror("deftyp() 3"); - /* typedef already qualified with "%s" */ - warning(68, "const"); - } - if (dcs->d_volatile && dcs->d_type->t_volatile) { - if (!dcs->d_type->t_typedef) - lerror("deftyp() 4"); - /* typedef already qualified with "%s" */ - warning(68, "volatile"); - } - - if (dcs->d_const || dcs->d_volatile) { - dcs->d_type = duptyp(dcs->d_type); - dcs->d_type->t_const |= dcs->d_const; - dcs->d_type->t_volatile |= dcs->d_volatile; - } -} - -/* - * Merge type specifiers (char, ..., long long, signed, unsigned). - */ -static tspec_t -mrgtspec(tspec_t t, tspec_t s) -{ - if (s == SIGNED || s == UNSIGN) { - if (t == CHAR) { - t = s == SIGNED ? SCHAR : UCHAR; - } else if (t == SHORT) { - t = s == SIGNED ? SHORT : USHORT; - } else if (t == INT) { - t = s == SIGNED ? INT : UINT; - } else if (t == LONG) { - t = s == SIGNED ? LONG : ULONG; - } else if (t == QUAD) { - t = s == SIGNED ? QUAD : UQUAD; - } - } - - return (t); -} - -/* - * Return the length of a type in bit. - * - * Printing a message if the outhermost dimension of an array is 0 must - * be done by the caller. All other problems are reported by length() - * if name is not NULL. - */ -int -length(type_t *tp, const char *name) -{ - int elem, elsz; - - elem = 1; - while (tp && tp->t_tspec == ARRAY) { - elem *= tp->t_dim; - tp = tp->t_subt; - } - if (tp == NULL) - return (-1); - - switch (tp->t_tspec) { - case FUNC: - /* compiler takes size of function */ - lerror(msgs[12]); - /* NOTREACHED */ - case STRUCT: - case UNION: - if (incompl(tp) && name != NULL) { - /* incomplete structure or union %s: %s */ - error(31, tp->t_str->stag->s_name, name); - } - elsz = tp->t_str->size; - break; - case ENUM: - if (incompl(tp) && name != NULL) { - /* incomplete enum type: %s */ - warning(13, name); - } - /* FALLTHROUGH */ - default: - elsz = size(tp->t_tspec); - if (elsz <= 0) - lerror("length()"); - break; - } - return (elem * elsz); -} - -/* - * Get the alignment of the given type in bits. - */ -int -getbound(type_t *tp) -{ - int a; - tspec_t t; - - while (tp && tp->t_tspec == ARRAY) - tp = tp->t_subt; - - if (tp == NULL) - return (-1); - - if ((t = tp->t_tspec) == STRUCT || t == UNION) { - a = tp->t_str->align; - } else if (t == FUNC) { - /* compiler takes alignment of function */ - error(14); - a = ALIGN(1) * CHAR_BIT; - } else { - if ((a = size(t)) == 0) { - a = CHAR_BIT; - } else if (a > ALIGN(1) * CHAR_BIT) { - a = ALIGN(1) * CHAR_BIT; - } - } - if (a < CHAR_BIT || a > ALIGN(1) * CHAR_BIT) - lerror("getbound() 1"); - return (a); -} - -/* - * Concatenate two lists of symbols by s_nxt. Used by declarations of - * struct/union/enum elements and parameters. - */ -sym_t * -lnklst(sym_t *l1, sym_t *l2) -{ - sym_t *l; - - if ((l = l1) == NULL) - return (l2); - while (l1->s_nxt != NULL) - l1 = l1->s_nxt; - l1->s_nxt = l2; - return (l); -} - -/* - * Check if the type of the given symbol is valid and print an error - * message if it is not. - * - * Invalid types are: - * - arrays of incomlete types or functions - * - functions returning arrays or functions - * - void types other than type of function or pointer - */ -void -chktyp(sym_t *sym) -{ - tspec_t to, t; - type_t **tpp, *tp; - - tpp = &sym->s_type; - to = NOTSPEC; - while ((tp = *tpp) != NULL) { - t = tp->t_tspec; - /* - * If this is the type of an old style function definition, - * a better warning is printed in funcdef(). - */ - if (t == FUNC && !tp->t_proto && - !(to == NOTSPEC && sym->s_osdef)) { - if (sflag && hflag) - /* function declaration is not a prototype */ - warning(287); - } - if (to == FUNC) { - if (t == FUNC || t == ARRAY) { - /* function returns illegal type */ - error(15); - if (t == FUNC) { - *tpp = incref(*tpp, PTR); - } else { - *tpp = incref((*tpp)->t_subt, PTR); - } - return; - } else if (tp->t_const || tp->t_volatile) { - if (sflag) { - /* function cannot return const... */ - warning(228); - } - } - } if (to == ARRAY) { - if (t == FUNC) { - /* array of function is illegal */ - error(16); - *tpp = gettyp(INT); - return; - } else if (t == ARRAY && tp->t_dim == 0) { - /* null dimension */ - error(17); - return; - } else if (t == VOID) { - /* illegal use of void */ - error(18); - *tpp = gettyp(INT); -#if 0 /* errors are produced by length() */ - } else if (incompl(tp)) { - /* array of incomplete type */ - if (sflag) { - error(301); - } else { - warning(301); - } -#endif - } - } else if (to == NOTSPEC && t == VOID) { - if (dcs->d_ctx == PARG) { - if (sym->s_scl != ABSTRACT) { - if (sym->s_name == unnamed) - lerror("chktyp()"); - /* void param cannot have name: %s */ - error(61, sym->s_name); - *tpp = gettyp(INT); - } - } else if (dcs->d_ctx == ABSTRACT) { - /* ok */ - } else if (sym->s_scl != TYPEDEF) { - /* void type for %s */ - error(19, sym->s_name); - *tpp = gettyp(INT); - } - } - if (t == VOID && to != PTR) { - if (tp->t_const || tp->t_volatile || tp->t_restrict) { - /* inappropriate qualifiers with "void" */ - warning(69); - tp->t_const = tp->t_volatile = 0; - tp->t_restrict = 0; - } - } - tpp = &tp->t_subt; - to = t; - } -} - -/* - * Process the declarator of a struct/union element. - */ -sym_t * -decl1str(sym_t *dsym) -{ - type_t *tp; - tspec_t t; - int sz, o, len; - scl_t sc; - - if ((sc = dsym->s_scl) != MOS && sc != MOU) - lerror("decl1str() 1"); - - if (dcs->d_rdcsym != NULL) { - if ((sc = dcs->d_rdcsym->s_scl) != MOS && sc != MOU) - /* should be ensured by storesym() */ - lerror("decl1str() 2"); - if (dsym->s_styp == dcs->d_rdcsym->s_styp) { - /* duplicate member name: %s */ - error(33, dsym->s_name); - rmsym(dcs->d_rdcsym); - } - } - - chktyp(dsym); - - t = (tp = dsym->s_type)->t_tspec; - - if (dsym->s_field) { - /* - * bit field - * - * only unsigned and signed int are portable bit-field types - * (at least in ANSI C, in traditional C only unsigned int) - */ - if (t == CHAR || t == UCHAR || t == SCHAR || - t == SHORT || t == USHORT || t == ENUM) { - if (sflag) { - /* bit-field type '%s' invalid in ANSI C */ - warning(273, tyname(tp)); - } else if (pflag) { - /* nonportable bit-field type */ - warning(34); - } - if (isutyp(t)) - tp->t_tspec = UINT; - else - tp->t_tspec = INT; - - tp->t_isenum = 0; - } else if (t == INT && dcs->d_smod == NOTSPEC) { - if (pflag) { - /* nonportable bit-field type */ - warning(34); - } - } else if (t != INT && t != UINT && t != LONG && - t != ULONG && t != QUAD && t != UQUAD && t != BOOL) { - /* illegal bit-field type */ - error(35); - sz = tp->t_flen; - dsym->s_type = tp = duptyp(gettyp(t = INT)); - if ((tp->t_flen = sz) > size(t)) - tp->t_flen = size(t); - } - if ((len = tp->t_flen) < 0 || len > size(t)) { - /* illegal bit-field size */ - error(36); - tp->t_flen = size(t); - } else if (len == 0 && dsym->s_name != unnamed) { - /* zero size bit-field */ - error(37); - tp->t_flen = size(t); - } - if (dsym->s_scl == MOU) { - /* illegal use of bit-field */ - error(41); - dsym->s_type->t_isfield = 0; - dsym->s_field = 0; - } - } else if (t == FUNC) { - /* function illegal in structure or union */ - error(38); - dsym->s_type = tp = incref(tp, t = PTR); - } - - /* - * bit-fields of length 0 are not warned about because length() - * does not return the length of the bit-field but the length - * of the type the bit-field is packed in (its ok) - */ - if ((sz = length(dsym->s_type, dsym->s_name)) == 0) { - if (t == ARRAY && dsym->s_type->t_dim == 0) { - /* illegal zero sized structure member: %s */ - warning(39, dsym->s_name); - } - } - - if (dcs->d_ctx == MOU) { - o = dcs->d_offset; - dcs->d_offset = 0; - } - if (dsym->s_field) { - align(getbound(tp), tp->t_flen); - dsym->s_value.v_quad = (dcs->d_offset / size(t)) * size(t); - tp->t_foffs = dcs->d_offset - (int)dsym->s_value.v_quad; - dcs->d_offset += tp->t_flen; - } else { - align(getbound(tp), 0); - dsym->s_value.v_quad = dcs->d_offset; - dcs->d_offset += sz; - } - if (dcs->d_ctx == MOU) { - if (o > dcs->d_offset) - dcs->d_offset = o; - } - - chkfdef(dsym, 0); - - return (dsym); -} - -/* - * Aligns next structure element as required. - * - * al contains the required alignment, len the length of a bit-field. - */ -static void -align(int al, int len) -{ - int no; - - /* - * The alignment of the current element becomes the alignment of - * the struct/union if it is larger than the current alignment - * of the struct/union. - */ - if (al > dcs->d_stralign) - dcs->d_stralign = al; - - no = (dcs->d_offset + (al - 1)) & ~(al - 1); - if (len == 0 || dcs->d_offset + len > no) - dcs->d_offset = no; -} - -/* - * Remember the width of the field in its type structure. - */ -sym_t * -bitfield(sym_t *dsym, int len) -{ - if (dsym == NULL) { - dsym = getblk(sizeof (sym_t)); - dsym->s_name = unnamed; - dsym->s_kind = FMOS; - dsym->s_scl = MOS; - dsym->s_type = gettyp(INT); - dsym->s_blklev = -1; - } - dsym->s_type = duptyp(dsym->s_type); - dsym->s_type->t_isfield = 1; - dsym->s_type->t_proto = 0; - dsym->s_type->t_isenum = 0; - dsym->s_type->t_flen = len; - dsym->s_field = 1; - return (dsym); -} - -/* - * Collect informations about a sequence of asterisks and qualifiers - * in a list of type pqinf_t. - * Qualifiers refer always to the left asterisk. The rightmost asterisk - * will be at the top of the list. - */ -pqinf_t * -mergepq(pqinf_t *p1, pqinf_t *p2) -{ - pqinf_t *p; - - if (p2->p_pcnt != 0) { - /* left '*' at the end of the list */ - for (p = p2; p->p_nxt != NULL; p = p->p_nxt) ; - p->p_nxt = p1; - return (p2); - } else { - if (p2->p_const) { - if (p1->p_const) { - /* duplicate %s */ - warning(10, "const"); - } - p1->p_const = 1; - } - if (p2->p_volatile) { - if (p1->p_volatile) { - /* duplicate %s */ - warning(10, "volatile"); - } - p1->p_volatile = 1; - } - free(p2); - return (p1); - } -} - -/* - * Followint 3 functions extend the type of a declarator with - * pointer, function and array types. - * - * The current type is the type built by deftyp() (dcs->d_type) and - * pointer, function and array types already added for this - * declarator. The new type extension is inserted between both. - */ -sym_t * -addptr(sym_t *decl, pqinf_t *pi) -{ - type_t **tpp, *tp; - pqinf_t *npi; - - tpp = &decl->s_type; - while (*tpp && *tpp != dcs->d_type) - tpp = &(*tpp)->t_subt; - if (*tpp == NULL) - return (decl); - - while (pi != NULL) { - *tpp = tp = getblk(sizeof (type_t)); - tp->t_tspec = PTR; - tp->t_const = pi->p_const; - tp->t_volatile = pi->p_volatile; - *(tpp = &tp->t_subt) = dcs->d_type; - npi = pi->p_nxt; - free(pi); - pi = npi; - } - return (decl); -} - -/* - * If a dimension was specified, dim is 1, otherwise 0 - * n is the specified dimension - */ -sym_t * -addarray(sym_t *decl, int dim, int n) -{ - type_t **tpp, *tp; - - tpp = &decl->s_type; - while (*tpp && *tpp != dcs->d_type) - tpp = &(*tpp)->t_subt; - if (*tpp == NULL) - return (decl); - - *tpp = tp = getblk(sizeof (type_t)); - tp->t_tspec = ARRAY; - tp->t_subt = dcs->d_type; - tp->t_dim = n; - - if (n < 0) { - /* zero or negative array dimension */ - error(20); - n = 0; - } else if (n == 0 && dim) { - /* zero or negative array dimension */ - warning(20); - } else if (n == 0 && !dim) { - /* is incomplete type */ - setcompl(tp, 1); - } - - return (decl); -} - -sym_t * -addfunc(sym_t *decl, sym_t *args) -{ - type_t **tpp, *tp; - - if (dcs->d_proto) { - args = nsfunc(decl, args); - } else { - osfunc(decl, args); - } - - /* - * The symbols are removed from the symbol table by popdecl() after - * addfunc(). To be able to restore them if this is a function - * definition, a pointer to the list of all symbols is stored in - * dcs->d_nxt->d_fpsyms. Also a list of the arguments (concatenated - * by s_nxt) is stored in dcs->d_nxt->d_fargs. - * (dcs->d_nxt must be used because *dcs is the declaration stack - * element created for the list of params and is removed after - * addfunc()) - */ - if (dcs->d_nxt->d_ctx == EXTERN && - decl->s_type == dcs->d_nxt->d_type) { - dcs->d_nxt->d_fpsyms = dcs->d_dlsyms; - dcs->d_nxt->d_fargs = args; - } - - tpp = &decl->s_type; - while (*tpp && *tpp != dcs->d_nxt->d_type) - tpp = &(*tpp)->t_subt; - if (*tpp == NULL) - return (decl); - - *tpp = tp = getblk(sizeof (type_t)); - tp->t_tspec = FUNC; - tp->t_subt = dcs->d_nxt->d_type; - if ((tp->t_proto = dcs->d_proto) != 0) - tp->t_args = args; - tp->t_vararg = dcs->d_vararg; - - return (decl); -} - -/* - * Called for new style function declarations. - */ -/* ARGSUSED */ -static sym_t * -nsfunc(sym_t *decl, sym_t *args) -{ - sym_t *arg, *sym; - scl_t sc; - int n; - - /* - * Declarations of structs/unions/enums in param lists are legal, - * but senseless. - */ - for (sym = dcs->d_dlsyms; sym != NULL; sym = sym->s_dlnxt) { - sc = sym->s_scl; - if (sc == STRTAG || sc == UNIONTAG || sc == ENUMTAG) { - /* dubious tag declaration: %s %s */ - warning(85, scltoa(sc), sym->s_name); - } - } - - n = 1; - for (arg = args; arg != NULL; arg = arg->s_nxt) { - if (arg->s_type->t_tspec == VOID) { - if (n > 1 || arg->s_nxt != NULL) { - /* "void" must be sole parameter */ - error(60); - arg->s_type = gettyp(INT); - } - } - n++; - } - - /* return NULL if first param is VOID */ - return (args != NULL && args->s_type->t_tspec != VOID ? args : NULL); -} - -/* - * Called for old style function declarations. - */ -static void -osfunc(sym_t *decl, sym_t *args) -{ - /* - * Remember list of params only if this is really seams to be - * a function definition. - */ - if (dcs->d_nxt->d_ctx == EXTERN && - decl->s_type == dcs->d_nxt->d_type) { - /* - * We assume that this becomes a function definition. If - * we are wrong, its corrected in chkfdef(). - */ - if (args != NULL) { - decl->s_osdef = 1; - decl->s_args = args; - } - } else { - if (args != NULL) - /* function prototype parameters must have types */ - warning(62); - } -} - -/* - * Lists of Identifiers in functions declarations are allowed only if - * its also a function definition. If this is not the case, print a - * error message. - */ -void -chkfdef(sym_t *sym, int msg) -{ - if (sym->s_osdef) { - if (msg) { - /* incomplete or misplaced function definition */ - error(22); - } - sym->s_osdef = 0; - sym->s_args = NULL; - } -} - -/* - * Process the name in a declarator. - * If the symbol does already exists, a new one is created. - * The symbol becomes one of the storage classes EXTERN, STATIC, AUTO or - * TYPEDEF. - * s_def and s_reg are valid after dname(). - */ -sym_t * -dname(sym_t *sym) -{ - scl_t sc = NOSCL; - - if (sym->s_scl == NOSCL) { - dcs->d_rdcsym = NULL; - } else if (sym->s_defarg) { - sym->s_defarg = 0; - dcs->d_rdcsym = NULL; - } else { - dcs->d_rdcsym = sym; - sym = pushdown(sym); - } - - switch (dcs->d_ctx) { - case MOS: - case MOU: - /* Parent setzen */ - sym->s_styp = dcs->d_tagtyp->t_str; - sym->s_def = DEF; - sym->s_value.v_tspec = INT; - sc = dcs->d_ctx; - break; - case EXTERN: - /* - * static and external symbols without "extern" are - * considered to be tentative defined, external - * symbols with "extern" are declared, and typedef names - * are defined. Tentative defined and declared symbols - * may become defined if an initializer is present or - * this is a function definition. - */ - if ((sc = dcs->d_scl) == NOSCL) { - sc = EXTERN; - sym->s_def = TDEF; - } else if (sc == STATIC) { - sym->s_def = TDEF; - } else if (sc == TYPEDEF) { - sym->s_def = DEF; - } else if (sc == EXTERN) { - sym->s_def = DECL; - } else { - lerror("dname() 1"); - } - break; - case PARG: - sym->s_arg = 1; - /* FALLTHROUGH */ - case ARG: - if ((sc = dcs->d_scl) == NOSCL) { - sc = AUTO; - } else if (sc == REG) { - sym->s_reg = 1; - sc = AUTO; - } else { - lerror("dname() 2"); - } - sym->s_def = DEF; - break; - case AUTO: - if ((sc = dcs->d_scl) == NOSCL) { - /* - * XXX somewhat ugly because we dont know whether - * this is AUTO or EXTERN (functions). If we are - * wrong it must be corrected in decl1loc(), where - * we have the necessary type information. - */ - sc = AUTO; - sym->s_def = DEF; - } else if (sc == AUTO || sc == STATIC || sc == TYPEDEF) { - sym->s_def = DEF; - } else if (sc == REG) { - sym->s_reg = 1; - sc = AUTO; - sym->s_def = DEF; - } else if (sc == EXTERN) { - sym->s_def = DECL; - } else { - lerror("dname() 3"); - } - break; - default: - lerror("dname() 4"); - } - sym->s_scl = sc; - - sym->s_type = dcs->d_type; - - dcs->d_fpsyms = NULL; - - return (sym); -} - -/* - * Process a name in the list of formal params in an old style function - * definition. - */ -sym_t * -iname(sym_t *sym) -{ - if (sym->s_scl != NOSCL) { - if (blklev == sym->s_blklev) { - /* redeclaration of formal parameter %s */ - error(21, sym->s_name); - if (!sym->s_defarg) - lerror("iname()"); - } - sym = pushdown(sym); - } - sym->s_type = gettyp(INT); - sym->s_scl = AUTO; - sym->s_def = DEF; - sym->s_defarg = sym->s_arg = 1; - return (sym); -} - -/* - * Create the type of a tag. - * - * tag points to the symbol table entry of the tag - * kind is the kind of the tag (STRUCT/UNION/ENUM) - * decl is 1 if the type of the tag will be completed in this declaration - * (the following token is T_LBRACE) - * semi is 1 if the following token is T_SEMI - */ -type_t * -mktag(sym_t *tag, tspec_t kind, int decl, int semi) -{ - scl_t scl = NOSCL; - type_t *tp; - - if (kind == STRUCT) { - scl = STRTAG; - } else if (kind == UNION) { - scl = UNIONTAG; - } else if (kind == ENUM) { - scl = ENUMTAG; - } else { - lerror("mktag()"); - } - - if (tag != NULL) { - if (tag->s_scl != NOSCL) { - tag = newtag(tag, scl, decl, semi); - } else { - /* a new tag, no empty declaration */ - dcs->d_nxt->d_nedecl = 1; - if (scl == ENUMTAG && !decl) { - if (sflag || pflag) - /* forward reference to enum type */ - warning(42); - } - } - if (tag->s_scl == NOSCL) { - tag->s_scl = scl; - tag->s_type = tp = getblk(sizeof (type_t)); - } else { - tp = tag->s_type; - } - } else { - tag = getblk(sizeof (sym_t)); - tag->s_name = unnamed; - STRUCT_ASSIGN(tag->s_dpos, curr_pos); - tag->s_kind = FTAG; - tag->s_scl = scl; - tag->s_blklev = -1; - tag->s_type = tp = getblk(sizeof (type_t)); - dcs->d_nxt->d_nedecl = 1; - } - - if (tp->t_tspec == NOTSPEC) { - tp->t_tspec = kind; - if (kind != ENUM) { - tp->t_str = getblk(sizeof (str_t)); - tp->t_str->align = CHAR_BIT; - tp->t_str->stag = tag; - } else { - tp->t_isenum = 1; - tp->t_enum = getblk(sizeof (enum_t)); - tp->t_enum->etag = tag; - } - /* is incomplete type */ - setcompl(tp, 1); - } - - return (tp); -} - -/* - * Checks all possible cases of tag redeclarations. - * decl is 1 if T_LBRACE follows - * semi is 1 if T_SEMI follows - */ -static sym_t * -newtag(sym_t *tag, scl_t scl, int decl, int semi) -{ - if (tag->s_blklev < blklev) { - if (semi) { - /* "struct a;" */ - if (!sflag) - /* decl. introduces new type ... */ - warning(44, scltoa(scl), tag->s_name); - tag = pushdown(tag); - dcs->d_nxt->d_nedecl = 1; - } else if (decl) { - /* "struct a { ..." */ - if (hflag) - /* redefinition hides earlier one: %s */ - warning(43, tag->s_name); - tag = pushdown(tag); - dcs->d_nxt->d_nedecl = 1; - } else if (tag->s_scl != scl) { - /* base type is really "%s %s" */ - warning(45, scltoa(tag->s_scl), tag->s_name); - /* declaration introduces new type in ANSI C: %s %s */ - if (!sflag) - warning(44, scltoa(scl), tag->s_name); - tag = pushdown(tag); - dcs->d_nxt->d_nedecl = 1; - } - } else { - if (tag->s_scl != scl) { - /* (%s) tag redeclared */ - error(46, scltoa(tag->s_scl)); - prevdecl(-1, tag); - tag = pushdown(tag); - dcs->d_nxt->d_nedecl = 1; - } else if (decl && !incompl(tag->s_type)) { - /* (%s) tag redeclared */ - error(46, scltoa(tag->s_scl)); - prevdecl(-1, tag); - tag = pushdown(tag); - dcs->d_nxt->d_nedecl = 1; - } else if (semi || decl) { - dcs->d_nxt->d_nedecl = 1; - } - } - return (tag); -} - -const char * -scltoa(scl_t sc) -{ - const char *s; - - switch (sc) { - case EXTERN: s = "extern"; break; - case STATIC: s = "static"; break; - case AUTO: s = "auto"; break; - case REG: s = "register"; break; - case TYPEDEF: s = "typedef"; break; - case STRTAG: s = "struct"; break; - case UNIONTAG: s = "union"; break; - case ENUMTAG: s = "enum"; break; - default: lerror("tagttoa()"); - } - return (s); -} - -/* - * Completes the type of a tag in a struct/union/enum declaration. - * tp points to the type of the, tag, fmem to the list of members/enums. - */ -type_t * -compltag(type_t *tp, sym_t *fmem) -{ - tspec_t t; - str_t *sp; - int n; - sym_t *mem; - - /* from now a complete type */ - setcompl(tp, 0); - - if ((t = tp->t_tspec) != ENUM) { - align(dcs->d_stralign, 0); - sp = tp->t_str; - sp->align = dcs->d_stralign; - sp->size = dcs->d_offset; - sp->memb = fmem; - if (sp->size == 0) { - if (sflag) { - /* zero sized %s */ - warning(47, ttab[t].tt_name); - } - } else { - n = 0; - for (mem = fmem; mem != NULL; mem = mem->s_nxt) { - if (mem->s_name != unnamed) - n++; - } - if (n == 0) { - /* %s has no named members */ - warning(65, - t == STRUCT ? "structure" : "union"); - } - } - } else { - tp->t_enum->elem = fmem; - } - return (tp); -} - -/* - * Processes the name of an enumerator in en enum declaration. - * - * sym points to the enumerator - * val is the value of the enumerator - * impl is 1 if the value of the enumerator was not explicitly specified. - */ -sym_t * -ename(sym_t *sym, int val, int impl) -{ - if (sym->s_scl) { - if (sym->s_blklev == blklev) { - /* no hflag, because this is illegal!!! */ - if (sym->s_arg) { - /* enumeration constant hides parameter: %s */ - warning(57, sym->s_name); - } else { - /* redeclaration of %s */ - error(27, sym->s_name); - /* - * inside blocks it should not too complicated - * to find the position of the previous - * declaration - */ - if (blklev == 0) - prevdecl(-1, sym); - } - } else { - if (hflag) - /* redefinition hides earlier one: %s */ - warning(43, sym->s_name); - } - sym = pushdown(sym); - } - sym->s_scl = ENUMCON; - sym->s_type = dcs->d_tagtyp; - sym->s_value.v_tspec = INT; - sym->s_value.v_quad = val; - if (impl && val - 1 == INT_MAX) { - /* overflow in enumeration values: %s */ - warning(48, sym->s_name); - } - enumval = val + 1; - return (sym); -} - -/* - * Process a single external declarator. - */ -void -decl1ext(sym_t *dsym, int initflg) -{ - int warn, rval, redec; - sym_t *rdsym; - - chkfdef(dsym, 1); - - chktyp(dsym); - - if (initflg && !(initerr = chkinit(dsym))) - dsym->s_def = DEF; - - /* - * Declarations of functions are marked as "tentative" in dname(). - * This is wrong because there are no tentative function - * definitions. - */ - if (dsym->s_type->t_tspec == FUNC && dsym->s_def == TDEF) - dsym->s_def = DECL; - - if (dcs->d_inline) { - if (dsym->s_type->t_tspec == FUNC) { - dsym->s_inline = 1; - } else { - /* variable declared inline: %s */ - warning(268, dsym->s_name); - } - } - - if (dsym->s_type->t_tspec == FUNC) { - if (noretflg) - dsym->s_noreturn = 1; - } - noretflg = 0; - - /* Write the declaration into the output file */ - if (plibflg && llibflg && - dsym->s_type->t_tspec == FUNC && dsym->s_type->t_proto) { - /* - * With both LINTLIBRARY and PROTOLIB the prototype is - * written as a function definition to the output file. - */ - rval = dsym->s_type->t_subt->t_tspec != VOID; - outfdef(dsym, &dsym->s_dpos, rval, 0, NULL); - } else { - outsym(dsym, dsym->s_scl, dsym->s_def); - } - - if ((rdsym = dcs->d_rdcsym) != NULL) { - /* - * If the old symbol stems from a old style function definition - * we have remembered the params in rdsmy->s_args and compare - * them with the params of the prototype. - */ - if (rdsym->s_osdef && dsym->s_type->t_proto) { - redec = chkosdef(rdsym, dsym); - } else { - redec = 0; - } - - if (!redec && !isredec(dsym, (warn = 0, &warn))) { - if (warn) { - /* redeclaration of %s */ - (*(sflag ? error : warning))(27, dsym->s_name); - prevdecl(-1, rdsym); - } - - /* - * Overtake the rememberd params if the new symbol - * is not a prototype. - */ - if (rdsym->s_osdef && !dsym->s_type->t_proto) { - dsym->s_osdef = rdsym->s_osdef; - dsym->s_args = rdsym->s_args; - STRUCT_ASSIGN(dsym->s_dpos, rdsym->s_dpos); - } - - /* - * Remember the position of the declaration if the - * old symbol was a prototype and the new is not. - * Also remember the position if the old symbol - * was defined and the new is not. - */ - if (rdsym->s_type->t_proto && !dsym->s_type->t_proto) { - STRUCT_ASSIGN(dsym->s_dpos, rdsym->s_dpos); - } else if (rdsym->s_def == DEF && dsym->s_def != DEF) { - STRUCT_ASSIGN(dsym->s_dpos, rdsym->s_dpos); - } - - /* - * Copy informations about usage of the name into - * the new symbol. - */ - cpuinfo(dsym, rdsym); - - /* Once a name is defined, it remains defined. */ - if (rdsym->s_def == DEF) - dsym->s_def = DEF; - - /* once a function is inline, it remains inline */ - if (rdsym->s_inline) - dsym->s_inline = 1; - - compltyp(dsym, rdsym); - - } - - rmsym(rdsym); - } - - if (dsym->s_scl == TYPEDEF) { - dsym->s_type = duptyp(dsym->s_type); - dsym->s_type->t_typedef = 1; - settdsym(dsym->s_type, dsym); - } - -} - -/* - * Copies informations about usage into a new symbol table entry of - * the same symbol. - */ -void -cpuinfo(sym_t *sym, sym_t *rdsym) -{ - sym->s_spos = rdsym->s_spos; - sym->s_upos = rdsym->s_upos; - sym->s_set = rdsym->s_set; - sym->s_used = rdsym->s_used; -} - -/* - * Prints an error and returns 1 if a symbol is redeclared/redefined. - * Otherwise returns 0 and, in some cases of minor problems, prints - * a warning. - */ -int -isredec(sym_t *dsym, int *warn) -{ - sym_t *rsym; - - if ((rsym = dcs->d_rdcsym)->s_scl == ENUMCON) { - /* redeclaration of %s */ - error(27, dsym->s_name); - prevdecl(-1, rsym); - return (1); - } - if (rsym->s_scl == TYPEDEF) { - /* typedef redeclared: %s */ - error(89, dsym->s_name); - prevdecl(-1, rsym); - return (1); - } - if (dsym->s_scl == TYPEDEF) { - /* redeclaration of %s */ - error(27, dsym->s_name); - prevdecl(-1, rsym); - return (1); - } - if (rsym->s_def == DEF && dsym->s_def == DEF) { - /* redefinition of %s */ - error(28, dsym->s_name); - prevdecl(-1, rsym); - return(1); - } - if (!eqtype(rsym->s_type, dsym->s_type, 0, 0, warn)) { - /* redeclaration of %s */ - error(27, dsym->s_name); - prevdecl(-1, rsym); - return(1); - } - if (rsym->s_scl == EXTERN && dsym->s_scl == EXTERN) - return(0); - if (rsym->s_scl == STATIC && dsym->s_scl == STATIC) - return(0); - if (rsym->s_scl == STATIC && dsym->s_def == DECL) - return(0); - if (rsym->s_scl == EXTERN && rsym->s_def == DEF) { - /* - * All cases except "int a = 1; static int a;" are caught - * above with or without a warning - */ - /* redeclaration of %s */ - error(27, dsym->s_name); - prevdecl(-1, rsym); - return(1); - } - if (rsym->s_scl == EXTERN) { - /* previously declared extern, becomes static: %s */ - warning(29, dsym->s_name); - prevdecl(-1, rsym); - return(0); - } - /* - * Now its on of: - * "static a; int a;", "static a; int a = 1;", "static a = 1; int a;" - */ - /* redeclaration of %s; ANSI C requires "static" */ - if (sflag) { - warning(30, dsym->s_name); - prevdecl(-1, rsym); - } - dsym->s_scl = STATIC; - return (0); -} - -/* - * Checks if two types are compatible. Returns 0 if not, otherwise 1. - * - * ignqual ignore qualifiers of type; used for function params - * promot promote left type; used for comparison of params of - * old style function definitions with params of prototypes. - * *warn set to 1 if an old style function declaration is not - * compatible with a prototype - */ -int -eqtype(type_t *tp1, type_t *tp2, int ignqual, int promot, int *warn) -{ - tspec_t t; - - while (tp1 != NULL && tp2 != NULL) { - t = tp1->t_tspec; - if (promot) { - if (t == FLOAT) { - t = DOUBLE; - } else if (t == BOOL) { - t = INT; - } else if (t == CHAR || t == SCHAR) { - t = INT; - } else if (t == UCHAR) { - t = INT; - } else if (t == SHORT) { - t = INT; - } else if (t == USHORT) { - /* CONSTCOND */ - t = INT_MAX < USHRT_MAX ? UINT : INT; - } else if (t == COMPLEX) { - t = DCOMPLEX; - } else if (t == IMAGINARY) { - t = DIMAGINARY; - } - } - - if (t != tp2->t_tspec) - return (0); - - if (tp1->t_const != tp2->t_const && !ignqual) - return (0); - - if (tp1->t_volatile != tp2->t_volatile && !ignqual) - return (0); - - if (tp1->t_restrict != tp2->t_restrict && !ignqual) - return (0); - - if (t == STRUCT || t == UNION) - return (tp1->t_str == tp2->t_str); - - if (t == ARRAY && tp1->t_dim != tp2->t_dim) { - if (tp1->t_dim != 0 && tp2->t_dim != 0) - return (0); - } - - /* dont check prototypes for traditional */ - if (t == FUNC) { - if (tp1->t_proto && tp2->t_proto) { - if (!eqargs(tp1, tp2, warn)) - return (0); - } else if (tp1->t_proto) { - if (!mnoarg(tp1, warn)) - return (0); - } else if (tp2->t_proto) { - if (!mnoarg(tp2, warn)) - return (0); - } - } - - tp1 = tp1->t_subt; - tp2 = tp2->t_subt; - ignqual = promot = 0; - - } - - return (tp1 == tp2); -} - -/* - * Compares the parameter types of two prototypes. - */ -static int -eqargs(type_t *tp1, type_t *tp2, int *warn) -{ - sym_t *a1, *a2; - - if (tp1->t_vararg != tp2->t_vararg) - return (0); - - a1 = tp1->t_args; - a2 = tp2->t_args; - - while (a1 != NULL && a2 != NULL) { - if (eqtype(a1->s_type, a2->s_type, 1, 0, warn) == 0) - return (0); - - a1 = a1->s_nxt; - a2 = a2->s_nxt; - - } - - return (a1 == a2); -} - -/* - * mnoarg() (matches functions with no argument type information) - * returns 1 if all parameters of a prototype are compatible with - * and old style function declaration. - * This is the case if following conditions are met: - * 1. the prototype must have a fixed number of parameters - * 2. no parameter is of type float - * 3. no parameter is converted to another type if integer promotion - * is applied on it - */ -static int -mnoarg(type_t *tp, int *warn) -{ - sym_t *arg; - tspec_t t; - - if (tp->t_vararg) { - if (warn != NULL) - *warn = 1; - } - for (arg = tp->t_args; arg != NULL; arg = arg->s_nxt) { - if ((t = arg->s_type->t_tspec) == FLOAT || t == BOOL || - t == CHAR || t == SCHAR || t == UCHAR || - t == SHORT || t == USHORT || t == COMPLEX || - t == DCOMPLEX || t == LDCOMPLEX || t == IMAGINARY || - t == DIMAGINARY || t == LDIMAGINARY) { - if (warn != NULL) - *warn = 1; - } - } - return (1); -} - -/* - * Compares a prototype declaration with the remembered arguments of - * a previous old style function definition. - */ -static int -chkosdef(sym_t *rdsym, sym_t *dsym) -{ - sym_t *args, *pargs, *arg, *parg; - int narg, nparg, n; - int warn, msg; - - args = rdsym->s_args; - pargs = dsym->s_type->t_args; - - msg = 0; - - narg = nparg = 0; - for (arg = args; arg != NULL; arg = arg->s_nxt) - narg++; - for (parg = pargs; parg != NULL; parg = parg->s_nxt) - nparg++; - if (narg != nparg) { - /* prototype does not match old-style definition */ - error(63); - msg = 1; - goto end; - } - - arg = args; - parg = pargs; - n = 1; - while (narg--) { - warn = 0; - /* - * If it does not match due to promotion and sflag is - * not set we print only a warning. - */ - if (!eqtype(arg->s_type, parg->s_type, 1, 1, &warn) || warn) { - /* prototype does not match old-style def., arg #%d */ - error(299, n); - msg = 1; - } - arg = arg->s_nxt; - parg = parg->s_nxt; - n++; - } - - end: - if (msg) - /* old style definition */ - prevdecl(300, rdsym); - - return (msg); -} - -/* - * Completes a type by copying the dimension and prototype information - * from a second compatible type. - * - * Following lines are legal: - * "typedef a[]; a b; a b[10]; a c; a c[20];" - * "typedef ft(); ft f; f(int); ft g; g(long);" - * This means that, if a type is completed, the type structure must - * be duplicated. - */ -void -compltyp(sym_t *dsym, sym_t *ssym) -{ - type_t **dstp, *src; - type_t *dst; - - dstp = &dsym->s_type; - src = ssym->s_type; - - while ((dst = *dstp) != NULL) { - if (src == NULL || dst->t_tspec != src->t_tspec) - lerror("compltyp() 1"); - if (dst->t_tspec == ARRAY) { - if (dst->t_dim == 0 && src->t_dim != 0) { - *dstp = dst = duptyp(dst); - dst->t_dim = src->t_dim; - /* now a complete type */ - setcompl(dst, 0); - } - } else if (dst->t_tspec == FUNC) { - if (!dst->t_proto && src->t_proto) { - *dstp = dst = duptyp(dst); - dst->t_proto = 1; - dst->t_args = src->t_args; - } - } - dstp = &dst->t_subt; - src = src->t_subt; - } -} - -/* - * Completes the declaration of a single argument. - */ -sym_t * -decl1arg(sym_t *sym, int initflg) -{ - tspec_t t; - - chkfdef(sym, 1); - - chktyp(sym); - - if (dcs->d_rdcsym != NULL && dcs->d_rdcsym->s_blklev == blklev) { - /* redeclaration of formal parameter %s */ - error(237, sym->s_name); - rmsym(dcs->d_rdcsym); - sym->s_arg = 1; - } - - if (!sym->s_arg) { - /* declared argument %s is missing */ - error(53, sym->s_name); - sym->s_arg = 1; - } - - if (initflg) { - /* cannot initialize parameter: %s */ - error(52, sym->s_name); - initerr = 1; - } - - if ((t = sym->s_type->t_tspec) == ARRAY) { - sym->s_type = incref(sym->s_type->t_subt, PTR); - } else if (t == FUNC) { - sym->s_type = incref(sym->s_type, PTR); - } - - if (dcs->d_inline) - /* argument declared inline: %s */ - warning(269, sym->s_name); - - /* - * Arguments must have complete types. lengths() prints the needed - * error messages (null dimension is impossible because arrays are - * converted to pointers). - */ - if (sym->s_type->t_tspec != VOID) - (void)length(sym->s_type, sym->s_name); - - setsflg(sym); - - return (sym); -} - -/* - * Does some checks for lint directives which apply to functions. - * Processes arguments in old style function definitions which default - * to int. - * Checks compatibility of old style function definition with previous - * prototype. - */ -void -cluparg(void) -{ - sym_t *args, *arg, *pargs, *parg; - int narg, nparg, n, msg; - tspec_t t; - - args = funcsym->s_args; - pargs = funcsym->s_type->t_args; - - /* check for illegal combinations of lint directives */ - if (prflstrg != -1 && scflstrg != -1) { - /* can't be used together: ** PRINTFLIKE ** ** SCANFLIKE ** */ - warning(289); - prflstrg = scflstrg = -1; - } - if (nvararg != -1 && (prflstrg != -1 || scflstrg != -1)) { - /* dubious use of ** VARARGS ** with ** %s ** */ - warning(288, prflstrg != -1 ? "PRINTFLIKE" : "SCANFLIKE"); - nvararg = -1; - } - - /* - * check if the argument of a lint directive is compatible with the - * number of arguments. - */ - narg = 0; - for (arg = dcs->d_fargs; arg != NULL; arg = arg->s_nxt) - narg++; - if (nargusg > narg) { - /* argument number mismatch with directive: ** %s ** */ - warning(283, "ARGSUSED"); - nargusg = 0; - } - if (nvararg > narg) { - /* argument number mismatch with directive: ** %s ** */ - warning(283, "VARARGS"); - nvararg = 0; - } - if (prflstrg > narg) { - /* argument number mismatch with directive: ** %s ** */ - warning(283, "PRINTFLIKE"); - prflstrg = -1; - } else if (prflstrg == 0) { - prflstrg = -1; - } - if (scflstrg > narg) { - /* argument number mismatch with directive: ** %s ** */ - warning(283, "SCANFLIKE"); - scflstrg = -1; - } else if (scflstrg == 0) { - scflstrg = -1; - } - if (prflstrg != -1 || scflstrg != -1) { - narg = prflstrg != -1 ? prflstrg : scflstrg; - arg = dcs->d_fargs; - for (n = 1; n < narg; n++) - arg = arg->s_nxt; - if (arg->s_type->t_tspec != PTR || - ((t = arg->s_type->t_subt->t_tspec) != CHAR && - t != UCHAR && t != SCHAR)) { - /* arg. %d must be 'char *' for PRINTFLIKE/SCANFLIKE */ - warning(293, narg); - prflstrg = scflstrg = -1; - } - } - - /* - * print a warning for each argument of an old style function - * definition which defaults to int - */ - for (arg = args; arg != NULL; arg = arg->s_nxt) { - if (arg->s_defarg) { - /* argument type defaults to int: %s */ - warning(32, arg->s_name); - arg->s_defarg = 0; - setsflg(arg); - } - } - - /* - * If this is an old style function definition and a prototype - * exists, compare the types of arguments. - */ - if (funcsym->s_osdef && funcsym->s_type->t_proto) { - /* - * If the number of arguments does not macht, we need not - * continue. - */ - narg = nparg = 0; - msg = 0; - for (parg = pargs; parg != NULL; parg = parg->s_nxt) - nparg++; - for (arg = args; arg != NULL; arg = arg->s_nxt) - narg++; - if (narg != nparg) { - /* parameter mismatch: %d declared, %d defined */ - error(51, nparg, narg); - msg = 1; - } else { - parg = pargs; - arg = args; - while (narg--) { - msg |= chkptdecl(arg, parg); - parg = parg->s_nxt; - arg = arg->s_nxt; - } - } - if (msg) - /* prototype declaration */ - prevdecl(285, dcs->d_rdcsym); - - /* from now the prototype is valid */ - funcsym->s_osdef = 0; - funcsym->s_args = NULL; - - } - -} - -/* - * Checks compatibility of an old style function definition with a previous - * prototype declaration. - * Returns 1 if the position of the previous declaration should be reported. - */ -static int -chkptdecl(sym_t *arg, sym_t *parg) -{ - type_t *tp, *ptp; - int warn, msg; - - tp = arg->s_type; - ptp = parg->s_type; - - msg = 0; - warn = 0; - - if (!eqtype(tp, ptp, 1, 1, &warn)) { - if (eqtype(tp, ptp, 1, 0, &warn)) { - /* type does not match prototype: %s */ - msg = gnuism(58, arg->s_name); - } else { - /* type does not match prototype: %s */ - error(58, arg->s_name); - msg = 1; - } - } else if (warn) { - /* type does not match prototype: %s */ - (*(sflag ? error : warning))(58, arg->s_name); - msg = 1; - } - - return (msg); -} - -/* - * Completes a single local declaration/definition. - */ -void -decl1loc(sym_t *dsym, int initflg) -{ - /* Correct a mistake done in dname(). */ - if (dsym->s_type->t_tspec == FUNC) { - dsym->s_def = DECL; - if (dcs->d_scl == NOSCL) - dsym->s_scl = EXTERN; - } - - if (dsym->s_type->t_tspec == FUNC) { - if (dsym->s_scl == STATIC) { - /* dubious static function at block level: %s */ - warning(93, dsym->s_name); - dsym->s_scl = EXTERN; - } else if (dsym->s_scl != EXTERN && dsym->s_scl != TYPEDEF) { - /* function has illegal storage class: %s */ - error(94, dsym->s_name); - dsym->s_scl = EXTERN; - } - } - - /* - * functions may be declared inline at local scope, although - * this has no effect for a later definition of the same - * function. - */ - if (dcs->d_inline) { - if (dsym->s_type->t_tspec == FUNC) { - dsym->s_inline = 1; - } else { - /* variable declared inline: %s */ - warning(268, dsym->s_name); - } - } - - chkfdef(dsym, 1); - - chktyp(dsym); - - if (dcs->d_rdcsym != NULL && dsym->s_scl == EXTERN) - ledecl(dsym); - - if (dsym->s_scl == EXTERN) { - /* - * XXX wenn die statische Variable auf Ebene 0 erst - * spaeter definiert wird, haben wir die Brille auf. - */ - if (dsym->s_xsym == NULL) { - outsym(dsym, EXTERN, dsym->s_def); - } else { - outsym(dsym, dsym->s_xsym->s_scl, dsym->s_def); - } - } - - if (dcs->d_rdcsym != NULL) { - if (dcs->d_rdcsym->s_blklev == 0) { - switch (dsym->s_scl) { - case AUTO: - /* automatic hides external declaration: %s */ - if (hflag) - warning(86, dsym->s_name); - break; - case STATIC: - /* static hides external declaration: %s */ - if (hflag) - warning(87, dsym->s_name); - break; - case TYPEDEF: - /* typedef hides external declaration: %s */ - if (hflag) - warning(88, dsym->s_name); - break; - case EXTERN: - /* - * Warnings and errors are printed in ledecl() - */ - break; - default: - lerror("decl1loc() 1"); - } - } else if (dcs->d_rdcsym->s_blklev == blklev) { - /* no hflag, because its illegal! */ - if (dcs->d_rdcsym->s_arg) { - /* - * a "redeclaration of %s" error - * is produced below - */ - } - - } else if (dcs->d_rdcsym->s_blklev < blklev) { - if (hflag) - /* declaration hides earlier one: %s */ - warning(95, dsym->s_name); - } - - if (dcs->d_rdcsym->s_blklev == blklev) { - /* redeclaration of %s */ - error(27, dsym->s_name); - rmsym(dcs->d_rdcsym); - } - } - - if (initflg && !(initerr = chkinit(dsym))) { - dsym->s_def = DEF; - setsflg(dsym); - } - - if (dsym->s_scl == TYPEDEF) { - dsym->s_type = duptyp(dsym->s_type); - dsym->s_type->t_typedef = 1; - settdsym(dsym->s_type, dsym); - } - - /* - * Before we can check the size we must wait for a initialisation - * which may follow. - */ -} - -/* - * Processes (re)declarations of external Symbols inside blocks. - */ -static void -ledecl(sym_t *dsym) -{ - int eqt, warn; - sym_t *esym; - - /* look for a symbol with the same name */ - esym = dcs->d_rdcsym; - while (esym != NULL && esym->s_blklev != 0) { - while ((esym = esym->s_link) != NULL) { - if (esym->s_kind != FVFT) - continue; - if (strcmp(dsym->s_name, esym->s_name) == 0) - break; - } - } - if (esym == NULL) - return; - if (esym->s_scl != EXTERN && esym->s_scl != STATIC) { - /* gcc accepts this without a warning, pcc prints an error. */ - /* redeclaration of %s */ - warning(27, dsym->s_name); - prevdecl(-1, esym); - return; - } - - warn = 0; - eqt = eqtype(esym->s_type, dsym->s_type, 0, 0, &warn); - - if (!eqt || warn) { - if (esym->s_scl == EXTERN) { - /* inconsistent redeclaration of extern: %s */ - warning(90, dsym->s_name); - prevdecl(-1, esym); - } else { - /* inconsistent redeclaration of static: %s */ - warning(92, dsym->s_name); - prevdecl(-1, esym); - } - } - - if (eqt) { - /* - * Remember the external symbol so we can update usage - * information at the end of the block. - */ - dsym->s_xsym = esym; - } -} - -/* - * Print an error or a warning if the symbol can't be initialized due - * to type/storage class. Return value is 1 if an error has been - * detected. - */ -static int -chkinit(sym_t *sym) -{ - int err; - - err = 0; - - if (sym->s_type->t_tspec == FUNC) { - /* cannot initialize function: %s */ - error(24, sym->s_name); - err = 1; - } else if (sym->s_scl == TYPEDEF) { - /* cannot initialize typedef: %s */ - error(25, sym->s_name); - err = 1; - } else if (sym->s_scl == EXTERN && sym->s_def == DECL) { - /* cannot initialize "extern" declaration: %s */ - if (dcs->d_ctx == EXTERN) { - warning(26, sym->s_name); - } else { - error(26, sym->s_name); - err = 1; - } - } - - return (err); -} - -/* - * Create a symbole for an abstract declaration. - */ -sym_t * -aname(void) -{ - sym_t *sym; - - if (dcs->d_ctx != ABSTRACT && dcs->d_ctx != PARG) - lerror("aname()"); - - sym = getblk(sizeof (sym_t)); - - sym->s_name = unnamed; - sym->s_def = DEF; - sym->s_scl = ABSTRACT; - sym->s_blklev = -1; - - if (dcs->d_ctx == PARG) - sym->s_arg = 1; - - sym->s_type = dcs->d_type; - dcs->d_rdcsym = NULL; - dcs->d_vararg = 0; - - return (sym); -} - -/* - * Removes anything which has nothing to do on global level. - */ -void -globclup(void) -{ - while (dcs->d_nxt != NULL) - popdecl(); - - cleanup(); - blklev = 0; - mblklev = 0; - - /* - * remove all information about pending lint directives without - * warnings. - */ - glclup(1); -} - -/* - * Process an abstract type declaration - */ -sym_t * -decl1abs(sym_t *sym) -{ - chkfdef(sym, 1); - chktyp(sym); - return (sym); -} - -/* - * Checks size after declarations of variables and their initialisation. - */ -void -chksz(sym_t *dsym) -{ - /* - * check size only for symbols which are defined and no function and - * not typedef name - */ - if (dsym->s_def != DEF) - return; - if (dsym->s_scl == TYPEDEF) - return; - if (dsym->s_type->t_tspec == FUNC) - return; - - if (length(dsym->s_type, dsym->s_name) == 0 && - dsym->s_type->t_tspec == ARRAY && dsym->s_type->t_dim == 0) { - /* empty array declaration: %s */ - error(190, dsym->s_name); - } -} - -/* - * Mark an object as set if it is not already - */ -void -setsflg(sym_t *sym) -{ - if (!sym->s_set) { - sym->s_set = 1; - STRUCT_ASSIGN(sym->s_spos, curr_pos); - } -} - -/* - * Mark an object as used if it is not already - */ -void -setuflg(sym_t *sym, int fcall, int szof) -{ - if (!sym->s_used) { - sym->s_used = 1; - STRUCT_ASSIGN(sym->s_upos, curr_pos); - } - /* - * for function calls another record is written - * - * XXX Should symbols used in sizeof() treated as used or not? - * Probably not, because there is no sense to declare an - * external variable only to get their size. - */ - if (!fcall && !szof && sym->s_kind == FVFT && sym->s_scl == EXTERN) - outusg(sym); -} - -/* - * Prints warnings for a list of variables and labels (concatenated - * with s_dlnxt) if these are not used or only set. - */ -void -chkusage(dinfo_t *di) -{ - sym_t *sym; - int mknowarn; - - /* for this warnings LINTED has no effect */ - mknowarn = nowarn; - nowarn = 0; - - for (sym = di->d_dlsyms; sym != NULL; sym = sym->s_dlnxt) - chkusg1(di->d_asm, sym); - - nowarn = mknowarn; -} - -/* - * Prints a warning for a single variable or label if it is not used or - * only set. - */ -void -chkusg1(int novar, sym_t *sym) -{ - pos_t cpos; - - if (sym->s_blklev == -1) - return; - - STRUCT_ASSIGN(cpos, curr_pos); - - if (sym->s_kind == FVFT) { - if (sym->s_arg) { - chkausg(novar, sym); - } else { - chkvusg(novar, sym); - } - } else if (sym->s_kind == FLAB) { - chklusg(sym); - } else if (sym->s_kind == FTAG) { - chktusg(sym); - } - - STRUCT_ASSIGN(curr_pos, cpos); -} - -static void -chkausg(int novar, sym_t *arg) -{ - if (!arg->s_set) - lerror("chkausg() 1"); - - if (novar) - return; - - if (!arg->s_used && vflag) { - STRUCT_ASSIGN(curr_pos, arg->s_dpos); - /* argument %s unused in function %s */ - warning(231, arg->s_name, funcsym->s_name); - } -} - -static void -chkvusg(int novar, sym_t *sym) -{ - scl_t sc; - sym_t *xsym; - - if (blklev == 0 || sym->s_blklev == 0) - lerror("chkvusg() 1"); - - /* errors in expressions easily cause lots of these warnings */ - if (nerr != 0) - return; - - /* - * XXX Only variables are checkd, although types should - * probably also be checked - */ - if ((sc = sym->s_scl) != EXTERN && sc != STATIC && - sc != AUTO && sc != REG) { - return; - } - - if (novar) - return; - - if (sc == EXTERN) { - if (!sym->s_used && !sym->s_set) { - STRUCT_ASSIGN(curr_pos, sym->s_dpos); - /* %s unused in function %s */ - warning(192, sym->s_name, funcsym->s_name); - } - } else { - if (sym->s_set && !sym->s_used) { - STRUCT_ASSIGN(curr_pos, sym->s_spos); - /* %s set but not used in function %s */ - warning(191, sym->s_name, funcsym->s_name); - } else if (!sym->s_used) { - STRUCT_ASSIGN(curr_pos, sym->s_dpos); - /* %s unused in function %s */ - warning(192, sym->s_name, funcsym->s_name); - } - } - - if (sc == EXTERN) { - /* - * information about usage is taken over into the symbol - * tabel entry at level 0 if the symbol was locally declared - * as an external symbol. - * - * XXX This is wrong for symbols declared static at level 0 - * if the usage information stems from sizeof(). This is - * because symbols at level 0 only used in sizeof() are - * considered to not be used. - */ - if ((xsym = sym->s_xsym) != NULL) { - if (sym->s_used && !xsym->s_used) { - xsym->s_used = 1; - STRUCT_ASSIGN(xsym->s_upos, sym->s_upos); - } - if (sym->s_set && !xsym->s_set) { - xsym->s_set = 1; - STRUCT_ASSIGN(xsym->s_spos, sym->s_spos); - } - } - } -} - -static void -chklusg(sym_t *lab) -{ - if (blklev != 1 || lab->s_blklev != 1) - lerror("chklusg() 1"); - - if (lab->s_set && !lab->s_used) { - STRUCT_ASSIGN(curr_pos, lab->s_spos); - /* label %s unused in function %s */ - warning(192, lab->s_name, funcsym->s_name); - } else if (!lab->s_set) { - STRUCT_ASSIGN(curr_pos, lab->s_upos); - /* undefined label %s */ - warning(23, lab->s_name); - } -} - -static void -chktusg(sym_t *sym) -{ - if (!incompl(sym->s_type)) - return; - - /* complain always about incomplete tags declared inside blocks */ - if (!zflag || dcs->d_ctx != EXTERN) - return; - - STRUCT_ASSIGN(curr_pos, sym->s_dpos); - switch (sym->s_type->t_tspec) { - case STRUCT: - /* struct %s never defined */ - warning(233, sym->s_name); - break; - case UNION: - /* union %s never defined */ - warning(234, sym->s_name); - break; - case ENUM: - /* enum %s never defined */ - warning(235, sym->s_name); - break; - default: - lerror("chktusg() 1"); - } -} - -/* - * Called after the entire translation unit has been parsed. - * Changes tentative definitions in definitions. - * Performs some tests on global Symbols. Detected Problems are: - * - defined variables of incomplete type - * - constant variables which are not initialized - * - static symbols which are never used - */ -void -chkglsyms(void) -{ - sym_t *sym; - pos_t cpos; - - if (blklev != 0 || dcs->d_nxt != NULL) - norecover(); - - STRUCT_ASSIGN(cpos, curr_pos); - - for (sym = dcs->d_dlsyms; sym != NULL; sym = sym->s_dlnxt) { - if (sym->s_blklev == -1) - continue; - if (sym->s_kind == FVFT) { - chkglvar(sym); - } else if (sym->s_kind == FTAG) { - chktusg(sym); - } else { - if (sym->s_kind != FMOS) - lerror("chkglsyms() 1"); - } - } - - STRUCT_ASSIGN(curr_pos, cpos); -} - -static void -chkglvar(sym_t *sym) -{ - if (sym->s_scl == TYPEDEF || sym->s_scl == ENUMCON) - return; - - if (sym->s_scl != EXTERN && sym->s_scl != STATIC) - lerror("chkglvar() 1"); - - glchksz(sym); - - if (sym->s_scl == STATIC) { - if (sym->s_type->t_tspec == FUNC) { - if (sym->s_used && sym->s_def != DEF) { - STRUCT_ASSIGN(curr_pos, sym->s_upos); - /* static func. called but not def.. */ - error(225, sym->s_name); - } - } - if (!sym->s_used) { - STRUCT_ASSIGN(curr_pos, sym->s_dpos); - if (sym->s_type->t_tspec == FUNC) { - if (sym->s_def == DEF) { - if (!sym->s_inline) - /* static function %s unused */ - warning(236, sym->s_name); - } else { - /* static function %s decl. but ... */ - warning(290, sym->s_name); - } - } else if (!sym->s_set) { - /* static variable %s unused */ - warning(226, sym->s_name); - } else { - /* static variable %s set but not used */ - warning(307, sym->s_name); - } - } - if (sym->s_def == TDEF && sym->s_type->t_const) { - STRUCT_ASSIGN(curr_pos, sym->s_dpos); - /* const object %s should have initializer */ - warning(227, sym->s_name); - } - } -} - -static void -glchksz(sym_t *sym) -{ - if (sym->s_def == TDEF) { - if (sym->s_type->t_tspec == FUNC) - /* - * this can happen if a syntax error occurred - * after a function declaration - */ - return; - STRUCT_ASSIGN(curr_pos, sym->s_dpos); - if (length(sym->s_type, sym->s_name) == 0 && - sym->s_type->t_tspec == ARRAY && sym->s_type->t_dim == 0) { - /* empty array declaration: %s */ - if (sym->s_scl == EXTERN && !sflag) { - warning(190, sym->s_name); - } else { - error(190, sym->s_name); - } - } - } -} - -/* - * Prints information about location of previous definition/declaration. - */ -void -prevdecl(int msg, sym_t *psym) -{ - pos_t cpos; - - if (!rflag) - return; - - STRUCT_ASSIGN(cpos, curr_pos); - STRUCT_ASSIGN(curr_pos, psym->s_dpos); - if (msg != -1) { - message(msg, psym->s_name); - } else if (psym->s_def == DEF || psym->s_def == TDEF) { - /* previous definition of %s */ - message(261, psym->s_name); - } else { - /* previous declaration of %s */ - message(260, psym->s_name); - } - STRUCT_ASSIGN(curr_pos, cpos); -} |