Main Page   Alphabetical List   Compound List   File List   Compound Members   File Members  

clabstract.c

Go to the documentation of this file.
00001 /*
00002 ** LCLint - annotation-assisted static program checker
00003 ** Copyright (C) 1994-2000 University of Virginia,
00004 **         Massachusetts Institute of Technology
00005 **
00006 ** This program is free software; you can redistribute it and/or modify it
00007 ** under the terms of the GNU General Public License as published by the
00008 ** Free Software Foundation; either version 2 of the License, or (at your
00009 ** option) any later version.
00010 ** 
00011 ** This program is distributed in the hope that it will be useful, but
00012 ** WITHOUT ANY WARRANTY; without even the implied warranty of
00013 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 ** General Public License for more details.
00015 ** 
00016 ** The GNU General Public License is available from http://www.gnu.org/ or
00017 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00018 ** MA 02111-1307, USA.
00019 **
00020 ** For information on lclint: lclint-request@cs.virginia.edu
00021 ** To report a bug: lclint-bug@cs.virginia.edu
00022 ** For more information: http://lclint.cs.virginia.edu
00023 */
00024 /*
00025 ** clabstract.c
00026 **
00027 ** ASTs for C grammar
00028 **
00029 */
00030 
00031 # include "lclintMacros.nf"
00032 # include "llbasic.h"
00033 # include "cgrammar.h"
00034 
00035 # ifndef NOLCL
00036 # include "usymtab_interface.h"
00037 # endif
00038 
00039 # include "structNames.h"
00040 # include "nameChecks.h"
00041 
00042 # ifdef SANITIZER
00043 # include "sgrammar_tokens.h"
00044 # else
00045 # include "cgrammar_tokens.h"
00046 # endif
00047 
00048 /*
00049 ** Lots of variables are needed because of interactions with the
00050 ** parser.  This is easier than restructuring the grammar so the
00051 ** right values are available in the right place.
00052 */
00053 
00054 static /*@only@*/ sRefSet fcnModifies = sRefSet_undefined;
00055 static /*@only@*/ /*@null@*/ specialClauses specClauses = specialClauses_undefined;
00056 static bool fcnNoGlobals = FALSE;
00057 static bool ProcessingVars = FALSE;
00058 static bool ProcessingParams = FALSE;
00059 static bool ProcessingGlobals = FALSE;
00060 static bool ProcessingTypedef = FALSE;
00061 static bool ProcessingIterVars = FALSE;
00062 static /*@only@*/ qtype processingType = qtype_undefined;
00063 static uentry currentIter = uentry_undefined;
00064 static globSet currentGlobals = globSet_undefined;
00065 static /*@dependent@*/ uentryList saveParamList;  /* for old style functions */
00066 static /*@owned@*/ uentry saveFunction = uentry_undefined;
00067 static int saveIterParamNo;
00068 static idDecl fixStructDecl (/*@returned@*/ idDecl p_d);
00069 static void checkTypeDecl (uentry p_e, ctype p_rep);
00070 static /*@dependent@*/ fileloc saveStoreLoc = fileloc_undefined;
00071 static storageClassCode storageClass = SCNONE;
00072 static void declareEnumList (/*@temp@*/ enumNameList p_el, ctype p_c, fileloc p_loc);
00073 static void resetGlobals (void);
00074 static qual specialFunctionCode = QU_UNKNOWN;
00075 static bool argsUsed = FALSE;
00076 
00077 static bool hasSpecialCode (void)
00078 {
00079   return (specialFunctionCode != QU_UNKNOWN);
00080 }
00081 
00082 extern void setArgsUsed (void)
00083 {
00084   if (argsUsed)
00085     {
00086       voptgenerror
00087         (FLG_SYNTAX,
00088          cstring_makeLiteral ("Multiple ARGSUSED comments for one function"),
00089          g_currentloc);
00090     }
00091 
00092   argsUsed = TRUE;
00093 }
00094 
00095 static void reflectArgsUsed (uentry ue)
00096 {
00097   if (argsUsed)
00098     {
00099       if (uentry_isFunction (ue))
00100         {
00101           uentryList params = uentry_getParams (ue);
00102 
00103           uentryList_elements (params, el)
00104             {
00105               uentry_setUsed (el, fileloc_undefined);
00106             } end_uentryList_elements ;
00107         }
00108 
00109       argsUsed = FALSE;
00110     }
00111 }
00112               
00113 extern void setSpecialFunction (qual qu)
00114 {
00115   if (specialFunctionCode != QU_UNKNOWN)
00116     {
00117       voptgenerror (FLG_SYNTAX,
00118                     message ("Multiple special function codes: %s, %s "
00119                              "(first code is ignored)",
00120                              qual_unparse (specialFunctionCode),
00121                              qual_unparse (qu)),
00122                     g_currentloc);
00123     }
00124 
00125   specialFunctionCode = qu;
00126 }
00127 
00128 static void reflectSpecialCode (uentry ue)
00129 {
00130   switch (specialFunctionCode)
00131     {
00132     case QU_UNKNOWN: break;
00133     case QU_PRINTFLIKE:
00134       uentry_setPrintfLike (ue);
00135       break;
00136     case QU_SCANFLIKE:
00137       uentry_setScanfLike (ue);
00138       break;
00139     case QU_MESSAGELIKE:
00140       uentry_setMessageLike (ue);
00141       break;
00142     BADDEFAULT;
00143     }
00144 
00145   specialFunctionCode = QU_UNKNOWN;
00146 }
00147 
00148 static void resetStorageClass (void)
00149 {
00150   qtype_free (processingType);
00151   processingType = qtype_undefined;
00152   storageClass = SCNONE;
00153 }
00154 
00155 static void reflectModGlobs (uentry ue)
00156 {
00157   if (fcnNoGlobals)
00158     {
00159       llassert (globSet_isUndefined (currentGlobals));
00160 
00161       uentry_setGlobals (ue, globSet_undefined);
00162       fcnNoGlobals = FALSE;
00163     }
00164   else if (globSet_isDefined (currentGlobals))
00165     {
00166       uentry_setGlobals (ue, currentGlobals);
00167       currentGlobals = globSet_undefined;
00168     }
00169   else
00170     {
00171       ; /* no globals */
00172     }
00173 
00174   if (sRefSet_isDefined (fcnModifies))
00175     {
00176       uentry_setModifies (ue, fcnModifies);
00177       fcnModifies = sRefSet_undefined;
00178     }
00179 
00180   if (uentry_isFunction (ue))
00181     {
00182       uentry_setSpecialClauses (ue, specClauses);
00183       specClauses = NULL;
00184       DPRINTF (("Done with spec clauses"));
00185     }
00186 }
00187 
00188 static void reflectStorageClass (uentry u)
00189 {
00190   if (storageClass == SCSTATIC)
00191     {
00192       uentry_setStatic (u);
00193     }
00194   else if (storageClass == SCEXTERN)
00195     {
00196       uentry_setExtern (u);
00197     }
00198   else
00199     {
00200       ; /* no storage class */
00201     }
00202 
00203   }
00204 
00205 void storeLoc ()
00206 {
00207   saveStoreLoc = g_currentloc;
00208 }
00209 
00210 void setFunctionNoGlobals (void)
00211 {
00212   llassert (globSet_isUndefined (currentGlobals));
00213   fcnNoGlobals = TRUE;
00214 }
00215 
00216 void
00217   setFunctionStateSpecialClause (lltok stok, specialClauseKind kind, 
00218                                  sRefSet s, 
00219                                  /*@unused@*/ lltok etok)
00220 {
00221   int tok = lltok_getTok (stok);
00222 
00223   switch (tok)
00224     {
00225     case QPRECLAUSE:
00226       specClauses = specialClauses_add (specClauses, 
00227                                         specialClause_create (TK_BEFORE, kind, s));
00228       break;
00229     case QPOSTCLAUSE:
00230       specClauses = specialClauses_add (specClauses, 
00231                                         specialClause_create (TK_AFTER, kind, s));
00232       break;
00233     default:
00234       sRefSet_free (s);
00235       BADBRANCH;
00236     }
00237 
00238   DPRINTF (("Added to specclauses: %s", specialClauses_unparse (specClauses)));
00239 }
00240 
00241 void setFunctionSpecialClause (lltok stok, sRefSet s, 
00242                                /*@unused@*/ lltok etok)
00243 {
00244   int tok = lltok_getTok (stok);
00245 
00246   switch (tok)
00247     {
00248     case QUSES:
00249       specClauses = specialClauses_add (specClauses, specialClause_createUses (s));
00250       break;
00251     case QDEFINES:
00252       specClauses = specialClauses_add (specClauses, specialClause_createDefines (s));
00253       break;
00254     case QALLOCATES:
00255       specClauses = specialClauses_add (specClauses, specialClause_createAllocates (s));
00256       break;
00257     case QSETS:
00258       specClauses = specialClauses_add (specClauses, specialClause_createSets (s));
00259       break;
00260     case QRELEASES:
00261       specClauses = specialClauses_add (specClauses, specialClause_createReleases (s));
00262       break;
00263     default:
00264       sRefSet_free (s);
00265       BADBRANCH;
00266     }
00267 
00268   DPRINTF (("Added to specclauses: %s", specialClauses_unparse (specClauses)));
00269 }
00270 
00271 void setFunctionModifies (sRefSet s)
00272 {
00273   sRefSet_free (fcnModifies);
00274   fcnModifies = s;
00275 }
00276 
00277 static void reflectGlobalQualifiers (sRef sr, qualList quals)
00278 {
00279   qualList_elements (quals, qel)
00280     {
00281       if (qual_isGlobalQual (qel)) /* undef, killed */
00282         {
00283           sstate oldstate = sRef_getDefState (sr);
00284           sstate defstate = sstate_fromQual (qel);
00285           
00286           if ((oldstate == SS_UNDEFGLOB && defstate == SS_KILLED)
00287               || (oldstate == SS_KILLED && defstate == SS_UNDEFGLOB))
00288             {
00289               defstate = SS_UNDEFKILLED;
00290             }
00291           else 
00292             {
00293               ; /* any errors? */
00294             }
00295           
00296           sRef_setDefState (sr, defstate, fileloc_undefined);
00297         }
00298       else if (qual_isAllocQual (qel)) /* out, partial, reldef, etc. */
00299         {
00300           ctype realType = sRef_getType (sr);
00301           sstate defstate = sstate_fromQual (qel);
00302           
00303           if (qual_isRelDef (qel))
00304             {
00305               ; /* okay anywhere */
00306             }
00307           else
00308             {
00309               if (!ctype_isAP (realType) 
00310                   && !ctype_isSU (realType)
00311                   && !ctype_isUnknown (realType)
00312                   && !ctype_isAbstract (sRef_getType (sr)))
00313                 {
00314                   llerror 
00315                     (FLG_SYNTAX, 
00316                      message ("Qualifier %s used on non-pointer or struct: %q",
00317                               qual_unparse (qel), sRef_unparse (sr)));
00318                   
00319                 }
00320             }
00321           
00322           sRef_setDefState (sr, defstate, fileloc_undefined);
00323         }
00324       else if (qual_isNull (qel))
00325         {
00326           sRef_setNullState (sr, NS_POSNULL, fileloc_undefined);
00327         }
00328       else if (qual_isRelNull (qel))
00329         {
00330           sRef_setNullState (sr, NS_RELNULL, fileloc_undefined);
00331         }
00332       else if (qual_isNotNull (qel))
00333         {
00334           sRef_setNullState (sr, NS_MNOTNULL, fileloc_undefined);
00335         }
00336       else
00337         {
00338           if (qual_isCQual (qel))
00339             {
00340               ; /* okay */
00341             }
00342           else
00343             {
00344               llerror (FLG_SYNTAX,
00345                        message ("Qualifier %s cannot be used in a globals list",
00346                                 qual_unparse (qel)));
00347             }
00348         }
00349     } end_qualList_elements;
00350 }
00351 
00352 void globListAdd (sRef sr, qualList quals)
00353 {
00354   if (sRef_isValid (sr))
00355     {
00356       sRef sc = sRef_copy (sr);
00357 
00358       reflectGlobalQualifiers (sc, quals);
00359       currentGlobals = globSet_insert (currentGlobals, sc);
00360     }
00361 }
00362 
00363 extern void declareCIter (cstring name, /*@owned@*/ uentryList params)
00364 {
00365   uentry ue;
00366 
00367   ue = uentry_makeIter (name, 
00368                         ctype_makeFunction (ctype_void, params), 
00369                         fileloc_copy (g_currentloc));
00370 
00371   usymtab_supEntry (uentry_makeEndIter (name, fileloc_copy (g_currentloc)));
00372 
00373   reflectModGlobs (ue);
00374 
00375   ue = usymtab_supGlobalEntryReturn (ue);
00376 }
00377 
00378 extern void nextIterParam (void)
00379 {
00380   llassert (ProcessingIterVars);
00381   saveIterParamNo++;
00382 }
00383 
00384 extern int iterParamNo (void)
00385 {
00386   llassert (ProcessingIterVars);
00387   return saveIterParamNo;
00388 }
00389 
00390 /*
00391 ** yucky hacks to put it in the right place
00392 */
00393 
00394 /*@only@*/ uentry 
00395 makeCurrentParam (idDecl t)
00396 {
00397   uentry ue;
00398 
00399   saveStoreLoc = fileloc_undefined;
00400 
00401   /* param number unknown */
00402 
00403   ue = uentry_makeParam (t, 0);
00404   return ue;
00405 }
00406 
00407 ctype
00408 declareUnnamedEnum (enumNameList el)
00409 {
00410   ctype ret = usymtab_enumEnumNameListType (el);
00411   ctype rt;
00412   uentry e;
00413 
00414   if (ctype_isDefined (ret))
00415     {
00416       rt = ret;
00417       e = uentry_makeEnumTagLoc (ctype_enumTag (rt), ret);
00418 
00419       reflectStorageClass (e);
00420       usymtab_supGlobalEntry (e);
00421       
00422       declareEnumList (el, ret, g_currentloc);    
00423       enumNameList_free (el);
00424     }
00425   else
00426     {
00427       ctype ct = ctype_createEnum (fakeTag (), el);
00428 
00429       e = uentry_makeEnumTagLoc (ctype_enumTag (ctype_realType (ct)), ct);
00430       reflectStorageClass (e);
00431 
00432       e = usymtab_supGlobalEntryReturn (e);
00433       rt = uentry_getAbstractType (e);
00434       declareEnumList (el, ct, g_currentloc);    
00435     }
00436   
00437   return (rt);
00438 }
00439 
00440 ctype
00441 declareEnum (cstring ename, enumNameList el)
00442 {
00443   ctype cet;
00444   uentry e;
00445 
00446   llassert (cstring_isDefined (ename));
00447 
00448   cet = ctype_createEnum (ename, el);
00449   e = uentry_makeEnumTagLoc (ename, cet);
00450   reflectStorageClass (e);
00451   e = usymtab_supGlobalEntryReturn (e);
00452   cet = uentry_getType (e);
00453   declareEnumList (el, cet, uentry_whereLast (e));    
00454   return (uentry_getAbstractType (e));
00455 }
00456 
00457 static void
00458 declareEnumList (enumNameList el, ctype c, fileloc loc)
00459 {
00460   bool boolnames = FALSE;
00461   bool othernames = FALSE;
00462 
00463   (void) context_getSaveLocation (); /* undefine it */
00464 
00465   if (context_maybeSet (FLG_NUMENUMMEMBERS))
00466     {
00467       int maxnum = context_getValue (FLG_NUMENUMMEMBERS);
00468       int num = enumNameList_size (el);
00469 
00470       if (num > maxnum)
00471         {
00472           voptgenerror 
00473             (FLG_NUMENUMMEMBERS,
00474              message ("Enumerator %s declared with %d members (limit is set to %d)",
00475                       ctype_unparse (c), num, maxnum),
00476              loc);
00477         }
00478     }
00479 
00480   enumNameList_elements (el, e)
00481     {
00482       uentry ue = usymtab_lookupExposeGlob (e);
00483       ctype ct = uentry_getType (ue);
00484 
00485       llassert (uentry_isEnumConstant (ue));
00486 
00487       if (ctype_isUnknown (ct))
00488         {
00489           uentry_setType (ue, c);
00490         }
00491       else
00492         {
00493           if (cstring_equal (e, context_getFalseName ())
00494               || cstring_equal (e, context_getTrueName ()))
00495             {
00496               if (othernames) 
00497                 {
00498                   if (optgenerror 
00499                       (FLG_INCONDEFS,
00500                        message ("Enumerator mixes boolean name (%s) with "
00501                                 "non-boolean names",
00502                                 e),
00503                        uentry_whereLast (ue)))
00504                     {
00505                       ;
00506                     }
00507                 }
00508               
00509               boolnames = TRUE;
00510               uentry_setType (ue, ctype_bool);
00511               DPRINTF (("Set type: %s / %s",
00512                         uentry_unparse (ue), ctype_unparse (ctype_bool)));
00513             }
00514           else 
00515             {
00516               if (boolnames) 
00517                 {
00518                   if (optgenerror 
00519                       (FLG_INCONDEFS,
00520                        message ("Enumerator mixes boolean names (%s, %s) with "
00521                                 "non-boolean name: %s",
00522                                 context_getTrueName (),
00523                                 context_getFalseName (),
00524                                 e),
00525                        uentry_whereLast (ue)))
00526                     {
00527                       ;
00528                     }
00529                 }
00530 
00531               othernames = TRUE;
00532             }
00533 
00534           if (!ctype_match (c, ct))
00535             {
00536               if (ctype_isDirectBool (ct))
00537                 {
00538                   if (cstring_equal (e, context_getFalseName ())
00539                       || cstring_equal (e, context_getTrueName ()))
00540                     {
00541                       DPRINTF (("Here we are!"));
00542                     }
00543                   else
00544                     {
00545                       if (optgenerror 
00546                           (FLG_INCONDEFS,
00547                            message ("Enumerator member %s declared with "
00548                                     "inconsistent type: %s",
00549                                     e, ctype_unparse (c)),
00550                            uentry_whereLast (ue)))
00551                         {
00552                           uentry_showWhereSpecifiedExtra 
00553                             (ue, cstring_copy (ctype_unparse (ct)));
00554                         }
00555                     }
00556                 }
00557               else
00558                 {
00559                   if (optgenerror 
00560                       (FLG_INCONDEFS,
00561                        message ("Enumerator member %s declared with "
00562                                 "inconsistent type: %s",
00563                                 e, ctype_unparse (c)),
00564                        uentry_whereLast (ue)))
00565                     {
00566                       uentry_showWhereSpecifiedExtra 
00567                         (ue, cstring_copy (ctype_unparse (ct)));
00568                     }
00569                 }
00570             }
00571         }
00572     } end_enumNameList_elements;
00573 }
00574 
00575 static /*@dependent@*/ uentryList currentParamList;
00576 
00577 void setCurrentParams (/*@dependent@*/ uentryList ue)
00578 {
00579   currentParamList = ue;
00580 }
00581 
00582 void clearCurrentParams (void)
00583 {
00584     currentParamList = uentryList_undefined;
00585 }
00586 
00587 /*
00588 ** requires: uentry_isFunction (e)
00589 **           parameter names for current function are in currentParamList
00590 */
00591 
00592 static void enterFunctionParams (uentryList params)
00593 {
00594   int paramno = 0;
00595 
00596   uentryList_elements (params, current)
00597     {
00598       if (uentry_hasName (current)) 
00599         {
00600           uentry_setParamNo (current, paramno);
00601           usymtab_supEntry (uentry_copy (current));
00602         }
00603       
00604       paramno++;
00605     } end_uentryList_elements; 
00606 }
00607  
00608 
00609 extern void enterParamsTemp (void)
00610 {
00611   usymtab_enterScope ();
00612   enterFunctionParams (currentParamList);
00613 }
00614 
00615 extern void exitParamsTemp (void)
00616 {
00617   usymtab_quietPlainExitScope ();
00618 }
00619 
00620 static /*@exposed@*/ uentry globalDeclareFunction (idDecl tid) 
00621 {
00622   ctype deftype = idDecl_getCtype (tid);
00623   ctype rettype;
00624   uentry ue;
00625   
00626   DPRINTF (("Global function: %s", idDecl_unparse (tid)));
00627   
00628   if (ctype_isFunction (deftype))
00629     {
00630       rettype = ctype_returnValue (deftype);
00631     }
00632   else
00633     {
00634       rettype = ctype_unknown;
00635     }
00636 
00637   /*
00638   ** check has been moved here...
00639   */
00640 
00641   if (ctype_isFunction (idDecl_getCtype (tid)))
00642     {
00643       ue = uentry_makeIdFunction (tid);
00644       reflectSpecialCode (ue);
00645       reflectArgsUsed (ue);
00646     }
00647   else
00648     {    
00649       llparseerror (message ("Inconsistent function declaration: %q",
00650                              idDecl_unparse (tid)));
00651 
00652       tid = idDecl_replaceCtype 
00653         (tid, ctype_makeFunction (ctype_unknown, uentryList_undefined));
00654       ue = uentry_makeIdFunction (tid);
00655     }
00656   
00657   reflectStorageClass (ue);
00658 
00659   uentry_checkParams (ue);
00660   reflectModGlobs (ue);
00661 
00662   ue = usymtab_supGlobalEntryReturn (ue);
00663   context_enterFunction (ue);
00664   enterFunctionParams (uentry_getParams (ue));
00665 
00666   resetStorageClass ();
00667   return (ue);
00668 }
00669 
00670 /*
00671 ** for now, no type checking
00672 ** (must check later though!)
00673 */
00674 
00675 static /*@only@*/ uentry globalDeclareOldStyleFunction (idDecl tid)
00676 {
00677   uentry ue;
00678 
00679   /*
00680   ** check has been moved here...
00681   */
00682 
00683   if (cstring_equalLit (idDecl_observeId (tid), "main"))
00684     {
00685       context_setFlagTemp (FLG_MAINTYPE, FALSE);
00686     }
00687 
00688   ue = uentry_makeIdFunction (tid);
00689   reflectStorageClass (ue);
00690   reflectSpecialCode (ue);
00691   reflectArgsUsed (ue);
00692   uentry_setDefined (ue, g_currentloc);
00693 
00694     uentry_checkParams (ue);
00695   
00696   if (ProcessingGlobals)
00697     {
00698       uentry_setGlobals (ue, currentGlobals);
00699     }
00700 
00701   resetStorageClass ();
00702   return (ue);
00703 }
00704 
00705 static void oldStyleDeclareFunction (/*@only@*/ uentry e)
00706 {
00707   uentryList params = saveParamList;
00708   ctype rt = uentry_getType (e);
00709 
00710   llassert (ctype_isFunction (rt));
00711 
00712   e = usymtab_supGlobalEntryReturn (e);
00713 
00714   context_enterFunction (e);
00715   enterFunctionParams (params);
00716   saveParamList = uentryList_undefined;
00717   resetStorageClass ();
00718 }
00719 
00720 void declareFunction (idDecl tid) /*@globals undef saveFunction; @*/
00721 {
00722   uentry ue;
00723 
00724   DPRINTF (("Declare function: %s", idDecl_unparse (tid)));
00725   
00726   if (ProcessingParams)
00727     {
00728       ue = globalDeclareOldStyleFunction (tid);
00729       saveFunction = ue;
00730     }
00731   else
00732     {
00733       saveFunction = uentry_undefined;
00734 
00735       if (context_inRealFunction ())
00736         {
00737           ue = uentry_makeVariableLoc (idDecl_observeId (tid), ctype_unknown);
00738 
00739           llparseerror (message ("Function declared inside function: %q",
00740                                  idDecl_unparse (tid)));
00741           
00742           context_quietExitFunction ();
00743           ue = usymtab_supEntryReturn (ue);
00744         }
00745       else
00746         {
00747           if (context_inInnerScope ())
00748             {
00749               llparseerror (message ("Declaration in inner context: %q",
00750                                      idDecl_unparse (tid)));
00751               
00752               sRef_setGlobalScope ();
00753               ue = uentry_makeVariableLoc (idDecl_observeId (tid), 
00754                                            ctype_unknown);
00755               ue = usymtab_supGlobalEntryReturn (ue);
00756               sRef_clearGlobalScope ();
00757             }
00758           else
00759             {
00760               ue = globalDeclareFunction (tid);
00761             }
00762         }
00763       
00764       resetGlobals ();
00765     }
00766 
00767   resetStorageClass ();
00768   idDecl_free (tid);
00769 }
00770 
00771 void declareStaticFunction (idDecl tid) /*@globals undef saveFunction; @*/
00772 {
00773   uentry ue;
00774 
00775   DPRINTF (("Declare static funciton: %s", idDecl_unparse (tid)));
00776 
00777   if (ProcessingParams)
00778     {
00779       ue = globalDeclareOldStyleFunction (tid);
00780       saveFunction = ue;
00781     }
00782   else
00783     {
00784       saveFunction = uentry_undefined;
00785 
00786       if (context_inRealFunction ())
00787         {
00788           ue = uentry_makeVariableLoc (idDecl_observeId (tid), ctype_unknown);
00789 
00790           llparseerror (message ("Function declared inside function: %q",
00791                                  idDecl_unparse (tid)));
00792           
00793           context_quietExitFunction ();
00794           ue = usymtab_supEntryReturn (ue);
00795         }
00796       else
00797         {
00798           if (context_inInnerScope ())
00799             {
00800               llparseerror (message ("Declaration in inner context: %q",
00801                                      idDecl_unparse (tid)));
00802               
00803               sRef_setGlobalScope ();
00804               ue = uentry_makeVariableLoc (idDecl_observeId (tid), 
00805                                            ctype_unknown);
00806               ue = usymtab_supGlobalEntryReturn (ue);
00807               sRef_clearGlobalScope ();
00808             }
00809           else
00810             {
00811               ctype deftype = idDecl_getCtype (tid);
00812               ctype rettype;
00813               
00814               if (ctype_isFunction (deftype))
00815                 {
00816                   rettype = ctype_returnValue (deftype);
00817                 }
00818               else
00819                 {
00820                   rettype = ctype_unknown;
00821                 }
00822               
00823               /*
00824               ** check has been moved here...
00825               */
00826               
00827               if (ctype_isFunction (idDecl_getCtype (tid)))
00828                 {
00829                   ue = uentry_makeIdFunction (tid);
00830                   reflectSpecialCode (ue);
00831                   reflectArgsUsed (ue);
00832                 }
00833               else
00834                 {    
00835                   llparseerror (message ("Inconsistent function declaration: %q",
00836                                          idDecl_unparse (tid)));
00837                   
00838                   tid = idDecl_replaceCtype 
00839                     (tid, ctype_makeFunction (ctype_unknown, uentryList_undefined));
00840                   ue = uentry_makeIdFunction (tid);
00841                 }
00842               
00843               reflectStorageClass (ue);
00844               uentry_setStatic (ue);
00845 
00846               uentry_checkParams (ue);
00847               reflectModGlobs (ue);
00848         
00849               DPRINTF (("Sub global entry: %s", uentry_unparse (ue)));
00850               ue = usymtab_supGlobalEntryReturn (ue);
00851 
00852               context_enterFunction (ue);
00853               enterFunctionParams (uentry_getParams (ue));
00854               resetStorageClass ();
00855             }
00856         }
00857       
00858       resetGlobals ();
00859     }
00860   
00861   resetStorageClass ();
00862   idDecl_free (tid);
00863 }
00864 
00865 void
00866 checkTypeDecl (uentry e, ctype rep)
00867 {
00868   cstring n = uentry_getName (e);
00869 
00870   DPRINTF (("Check type decl: %s", n));
00871 
00872   if (cstring_equal (context_getBoolName (), n))
00873     {
00874       ctype rrep = ctype_realType (rep);
00875       
00876       /*
00877       ** for abstract enum types, we need to fix the enum members:
00878       ** they should have the abstract type, not the rep type.
00879       */
00880       
00881       if (ctype_isEnum (ctype_realType (rrep)))
00882         {
00883           enumNameList el = ctype_elist (rrep);
00884           
00885           enumNameList_elements (el, ye)
00886             {
00887               if (usymtab_existsGlob (ye))
00888                 {
00889                   uentry ue = usymtab_lookupSafe (ye);
00890                   uentry_setType (ue, ctype_bool);
00891                 }
00892 
00893               if (cstring_equal (context_getTrueName (), ye)
00894                   || cstring_equal (context_getFalseName (), ye))
00895                 {
00896                   ;
00897                 }
00898               else
00899                 {
00900                   vgenhinterror 
00901                     (FLG_SYNTAX,
00902                      message ("Member of boolean enumerated type definition "
00903                               "does not match name set to represent TRUE "
00904                               "or FALSE: %s",
00905                               ye),
00906                      message ("Use -boolfalse and -booltrue to set the "
00907                               "name of false and true boolean values."),
00908                      uentry_whereDefined (e));
00909                 }
00910             } end_enumNameList_elements;
00911         }
00912     }
00913 
00914   if (usymtab_exists (n))
00915     {
00916       usymId llm = usymtab_getId (n);
00917       uentry le  = usymtab_getTypeEntry (llm);
00918 
00919       uentry_setDeclared (e, g_currentloc); 
00920       uentry_setSref (e, sRef_makeGlobal (llm, uentry_getType (le)));
00921 
00922       DPRINTF (("Here we are: %s / %s",
00923                 n, context_getBoolName ()));
00924       
00925       if (uentry_isAbstractDatatype (le))
00926         {
00927           ctype rrep = ctype_realType (rep);
00928 
00929           /*
00930           ** for abstract enum types, we need to fix the enum members:
00931           ** they should have the abstract type, not the rep type.
00932           */
00933 
00934           if (ctype_isEnum (ctype_realType (rrep)))
00935             {
00936               ctype at = uentry_getAbstractType (le);
00937               enumNameList el = ctype_elist (rrep);
00938 
00939               enumNameList_elements (el, ye)
00940                 {
00941                   if (usymtab_existsGlob (ye))
00942                     {
00943                       uentry ue = usymtab_lookupSafe (ye);
00944 
00945                       llassert (uentry_isEitherConstant (ue));
00946                       llassertprint (ctype_match (uentry_getType (ue), rrep),
00947                                      ("Bad enum: %s / %s",
00948                                       uentry_unparse (ue),
00949                                       ctype_unparse (rrep)));
00950                       
00951                       uentry_setType (ue, at);
00952                     }
00953                 } end_enumNameList_elements;
00954             }
00955           
00956           if (uentry_isMutableDatatype (le))
00957             {
00958               /* maybe more complicated if abstract and immutable ? */
00959 
00960               if (!ctype_isRealPointer (rep) && !ctype_isRealAbstract (rep))
00961                 {
00962                   voptgenerror 
00963                     (FLG_MUTREP,
00964                      message ("Mutable abstract type %s declared without pointer "
00965                               "indirection: %s (violates assignment semantics)",
00966                               n, ctype_unparse (rep)),
00967                      uentry_whereDefined (e));
00968                   
00969                   uentry_setMutable (e);
00970                 }
00971             }
00972         }
00973     }
00974   else
00975     {
00976       fileloc fl = uentry_whereDeclared (e);
00977 
00978       if (context_getFlag (FLG_LIKELYBOOL)
00979           && !context_getFlag (FLG_BOOLINT))
00980         {
00981           if ((cstring_equalLit (n, "BOOL")
00982                || cstring_equalLit (n, "Bool")
00983                || cstring_equalLit (n, "bool")
00984                || cstring_equalLit (n, "boolean")
00985                || cstring_equalLit (n, "Boolean")
00986                || cstring_equalLit (n, "BOOLEAN"))
00987               && !(cstring_equal (n, context_getBoolName ())))
00988             {
00989               if (context_setBoolName ()) {
00990                 voptgenerror 
00991                   (FLG_LIKELYBOOL,
00992                    message ("Type %s is probably meant as a boolean type, but does "
00993                             "not match the boolean type name \"%s\".",
00994                             n,
00995                             context_getBoolName ()),
00996                    fl);
00997               } else
00998                 voptgenerror 
00999                   (FLG_LIKELYBOOL,
01000                    message ("Type %s is probably meant as a boolean type, "
01001                             "but the boolean type name is not set. "
01002                             "Use -booltype %s to set it.",
01003                             n,
01004                             n),
01005                    fl);
01006                 }
01007         }
01008 
01009       if (!uentry_isStatic (e)
01010           && !ctype_isFunction (uentry_getType (e)) 
01011           && !fileloc_isLib (fl) 
01012           && !fileloc_isImport (fl)
01013           && fileloc_isHeader (fl))
01014         {
01015           voptgenerror (FLG_EXPORTTYPE,
01016                         message ("Type exported, but not specified: %s\n", n),
01017                         fl);
01018         }
01019     }
01020 
01021   cstring_free (n);
01022 }
01023 
01024 uentryList
01025 fixUentryList (idDeclList tl, qtype q)
01026 {
01027   uentryList f = uentryList_new ();
01028   
01029   idDeclList_elements (tl, i)
01030   {
01031     if (idDecl_isDefined (i))
01032       {
01033         uentry ue;
01034         uentry old;
01035         ctype rt;
01036 
01037         (void) idDecl_fixBase (i, q);
01038 
01039         /*
01040         ** implicit annotations 
01041         */
01042 
01043         (void) fixStructDecl (i);
01044 
01045         ue = uentry_makeIdVariable (i);
01046         rt = ctype_realType (uentry_getType (ue));
01047 
01048         /*
01049         ** where is this here???
01050 
01051         if (ctype_isArray (rt) || ctype_isSU (rt))
01052           {
01053             sRef_setAllocated (uentry_getSref (ue), uentry_whereDefined (ue));
01054           }
01055 
01056         **
01057         */
01058 
01059         if (uentry_isValid (old = uentryList_lookupField (f, uentry_rawName (ue))))
01060           {
01061             if (optgenerror (FLG_SYNTAX,
01062                              message ("Field name reused: %s", uentry_rawName (ue)),
01063                              uentry_whereDefined (ue)))
01064               {
01065                 llgenmsg (message ("Previous use of %s", uentry_rawName (ue)),
01066                           uentry_whereDefined (old));
01067               }
01068           }
01069         
01070         f = uentryList_add (f, ue);
01071       }
01072   } end_idDeclList_elements;
01073 
01074   idDeclList_free (tl);
01075   return (f);
01076 }
01077 
01078 /*
01079 ** This is a hack to support unnamed struct/union fields as done by
01080 ** Microsoft VC++.  It is not supported by the ANSI standard.  
01081 **
01082 ** The inner fields are added to the outer structure.  This is meaningful
01083 ** for nesting structs inside unions, but lclint does no related 
01084 ** checking.
01085 */
01086 
01087 uentryList
01088 fixUnnamedDecl (qtype q)
01089 {
01090   ctype ct = ctype_realType (qtype_getType (q));
01091 
01092   if (ctype_isStruct (ct) || ctype_isUnion (ct))
01093     {
01094       uentryList res = ctype_getFields (ct);
01095 
01096       return (uentryList_copy (res));
01097     }
01098   else
01099     {      
01100       BADBRANCHCONT;
01101     }
01102 
01103   return uentryList_undefined;
01104 }
01105 
01106 void setStorageClass (storageClassCode sc)
01107 {
01108   storageClass = sc;
01109 }
01110 
01111 void
01112 setProcessingIterVars (uentry iter)
01113 {
01114   ProcessingIterVars = TRUE;
01115   currentIter = iter;
01116   saveIterParamNo = 0;
01117 }
01118 
01119 void
01120 setProcessingGlobalsList ()
01121 {
01122   ProcessingGlobals = TRUE;
01123 
01124   llassert (globSet_isUndefined (currentGlobals));
01125   currentGlobals = globSet_undefined;
01126 
01127   llassert (sRefSet_isUndefined (fcnModifies));
01128   fcnModifies = sRefSet_undefined;
01129   
01130   /*
01131   ** No, special clauses might have been processed first!  
01132   llassert (specialClauses_isUndefined (specClauses));
01133   specClauses = specialClauses_undefined;
01134   */
01135 
01136   fcnNoGlobals = FALSE;
01137 }
01138 
01139 static bool ProcessingGlobMods = FALSE;
01140 
01141 void
01142 setProcessingGlobMods ()
01143 {
01144   ProcessingGlobMods = TRUE;
01145 }
01146 
01147 void
01148 clearProcessingGlobMods ()
01149 {
01150   ProcessingGlobMods = FALSE;
01151 }
01152 
01153 bool
01154 isProcessingGlobMods ()
01155 {
01156   return (ProcessingGlobMods);
01157 }
01158 
01159 static void resetGlobals (void)
01160 {
01161   ProcessingGlobals = FALSE;
01162   currentGlobals = globSet_undefined;
01163   llassert (sRefSet_isUndefined (fcnModifies));
01164   fcnModifies = sRefSet_undefined;
01165   fcnNoGlobals = FALSE;
01166 }
01167 
01168 void
01169 unsetProcessingGlobals ()
01170 {
01171   ProcessingGlobals = FALSE;
01172 }
01173 
01174 void
01175 setProcessingVars (/*@only@*/ qtype q)
01176 {
01177   ProcessingVars = TRUE;
01178   qtype_free (processingType);
01179   processingType = q;
01180 }
01181 
01182 static void
01183 setGenericParamList (/*@dependent@*/ uentryList pm)
01184 {
01185   ProcessingParams = TRUE;
01186   saveParamList = pm;
01187 }
01188 
01189 void
01190 setProcessingTypedef (/*@only@*/ qtype q)
01191 {
01192   ProcessingTypedef = TRUE;
01193 
01194   qtype_free (processingType);
01195   processingType = q;
01196 }
01197 
01198 void
01199 unsetProcessingVars ()
01200 {
01201   resetStorageClass ();
01202   ProcessingVars = FALSE;
01203 }
01204 
01205 void 
01206 doneParams ()
01207 {  
01208   if (ProcessingParams)
01209     {
01210       if (uentry_isInvalid (saveFunction))
01211         {
01212           llbuglit ("unsetProcessingVars: no saved function\n");
01213           
01214           if (sRefSet_isDefined (fcnModifies)) {
01215             sRefSet_free (fcnModifies);
01216             fcnModifies = sRefSet_undefined;
01217           }
01218         }
01219       else
01220         {
01221           ctype ct = ctype_returnValue (uentry_getType (saveFunction));
01222           uentryList params = uentryList_copy (saveParamList);
01223           ctype ct2 = ctype_makeFunction (ct, params);
01224 
01225           uentry_setType (saveFunction, ct2);
01226           ProcessingParams = FALSE;
01227 
01228           reflectModGlobs (saveFunction);
01229           oldStyleDeclareFunction (saveFunction);
01230           saveFunction = uentry_undefined;
01231           resetGlobals ();
01232         }
01233     }
01234   else
01235     {
01236       /*
01237       ** If the paramlist used a type name, we could be here.
01238       */
01239 
01240       llfatalerror (message ("%q: Old-style function parameter list uses a "
01241                              "type name.", fileloc_unparse (g_currentloc)));
01242     }
01243 }
01244 
01245 void 
01246 checkDoneParams ()
01247 {
01248   if (uentry_isValid (saveFunction))
01249     {
01250       /*
01251       ** old style declaration
01252       */
01253 
01254       ctype ct = ctype_returnValue (uentry_getType (saveFunction));
01255       ctype ct2;
01256 
01257       uentryList_elements (saveParamList, current)
01258         {
01259           uentry_setType (current, ctype_int); /* all params are ints */
01260         } end_uentryList_elements; 
01261 
01262       ct2 = ctype_makeParamsFunction (ct, uentryList_copy (saveParamList));
01263       
01264       uentry_setType (saveFunction, ct2);
01265       ProcessingParams = FALSE;
01266       
01267       oldStyleDeclareFunction (saveFunction);
01268       saveFunction = uentry_undefined;
01269     }
01270 }
01271 
01272 void
01273 unsetProcessingTypedef ()
01274 {
01275   ProcessingTypedef = FALSE;
01276 }
01277 
01278 void checkConstant (qtype t, idDecl id) 
01279 {
01280   uentry e;
01281 
01282   id = idDecl_fixBase (id, t);
01283   e = uentry_makeIdConstant (id);
01284 
01285   reflectStorageClass (e);
01286   resetStorageClass ();
01287 
01288   usymtab_supGlobalEntry (e);
01289 }
01290 
01291 void checkValueConstant (qtype t, idDecl id, exprNode e) 
01292 {
01293   uentry ue;
01294 
01295   id = idDecl_fixBase (id, t);
01296   ue = uentry_makeIdConstant (id);
01297   reflectStorageClass (ue);
01298   resetStorageClass ();
01299 
01300   if (exprNode_isDefined (e))
01301     {
01302       if (!exprNode_matchType (uentry_getType (ue), e))
01303         {
01304           (void) gentypeerror 
01305             (exprNode_getType (e), e,
01306              uentry_getType (ue), exprNode_undefined,
01307              message ("Constant %q initialized to type %t, expects %t: %s",
01308                       uentry_getName (ue),  
01309                       exprNode_getType (e), 
01310                       uentry_getType (ue),
01311                       exprNode_unparse (e)),
01312              exprNode_loc (e));
01313         }
01314       else
01315         {
01316           if (exprNode_hasValue (e))
01317             {
01318               uentry_mergeConstantValue (ue, multiVal_copy (exprNode_getValue (e)));
01319             }
01320         }
01321     }
01322 
01323   usymtab_supGlobalEntry (ue);
01324 }
01325 
01326 
01327 void processNamedDecl (idDecl t)
01328 {
01329   if (qtype_isUndefined (processingType))
01330     {
01331       llparseerror (message ("No type before declaration name: %q", idDecl_unparse (t)));
01332 
01333       processingType = qtype_create (ctype_unknown);
01334     }
01335 
01336   t = idDecl_fixBase (t, processingType);
01337 
01338   DPRINTF (("Declare: %s", idDecl_unparse (t)));
01339 
01340   if (ProcessingGlobals)
01341     {
01342       cstring id = idDecl_getName (t);
01343       uentry ue = usymtab_lookupSafe (id);
01344 
01345       if (!uentry_isValid (ue))
01346         {
01347           llerror (FLG_UNRECOG,
01348                    message ("Variable used in globals list is undeclared: %s", id));
01349         }
01350       else
01351         {
01352           if (!ctype_match (uentry_getType (ue), idDecl_getCtype (t)))
01353             {
01354               voptgenerror 
01355                 (FLG_INCONDEFS,
01356                  message ("Variable %s used in globals list declared %s, "
01357                           "but listed as %s", 
01358                           id, ctype_unparse (uentry_getType (ue)), 
01359                           ctype_unparse (idDecl_getCtype (t))),
01360                  g_currentloc);
01361             }
01362           else
01363             {
01364               sRef sr = sRef_copy (uentry_getSref (ue));
01365 
01366               reflectGlobalQualifiers (sr, idDecl_getQuals (t));
01367 
01368               currentGlobals = globSet_insert (currentGlobals, sr);
01369             }
01370         }
01371     }
01372   else if (ProcessingVars)
01373     {
01374       uentry e;
01375       ctype ct;
01376       
01377       ct = ctype_realType (idDecl_getCtype (t));
01378 
01379       if (ProcessingParams)
01380         {
01381           cstring id = idDecl_getName (t);
01382           int paramno = uentryList_lookupRealName (saveParamList, id);
01383 
01384           if (paramno >= 0)
01385             {
01386               uentry cparam = uentryList_getN (saveParamList, paramno);
01387 
01388               uentry_setType (cparam, idDecl_getCtype (t));
01389               uentry_reflectQualifiers (cparam, idDecl_getQuals (t));
01390               uentry_setDeclaredOnly (cparam, context_getSaveLocation ());
01391             }
01392           else
01393             {
01394               llfatalerrorLoc
01395                 (message ("Old style declaration uses unlisted parameter: %s", 
01396                           id));
01397             }
01398         }
01399       else
01400         {
01401           fileloc loc;
01402 
01403           if (context_inIterDef ())
01404             {
01405               cstring pname = makeParam (idDecl_observeId (t));
01406               uentry p = usymtab_lookupSafe (pname);
01407 
01408               cstring_free (pname);
01409 
01410               if (uentry_isYield (p))
01411                 {
01412                   e = uentry_makeParam (t, sRef_getParam (uentry_getSref (p)));
01413                   
01414                   uentry_checkYieldParam (p, e);
01415                   
01416                   usymtab_supEntrySref (e);
01417                   return;
01418                 }
01419             }
01420 
01421           if ((hasSpecialCode () || argsUsed)
01422               && ctype_isFunction (idDecl_getCtype (t)))
01423             {
01424               e = uentry_makeIdFunction (t);
01425               reflectSpecialCode (e);
01426               reflectArgsUsed (e);
01427             }
01428           else
01429             {
01430               e = uentry_makeIdVariable (t);
01431             }
01432 
01433           loc = uentry_whereDeclared (e);
01434 
01435           /*
01436           if (context_inGlobalScope ())
01437             {
01438             uentry_checkParams was here!
01439             }
01440             */
01441 
01442           if (ctype_isFunction (uentry_getType (e)))
01443             {
01444               reflectModGlobs (e);
01445             }
01446           else
01447             {
01448               llassert (!globSet_isDefined (currentGlobals)
01449                         && !sRefSet_isDefined (fcnModifies));
01450             }
01451           
01452           e = usymtab_supEntrySrefReturn (e);
01453 
01454           if (uentry_isExtern (e) && !context_inGlobalScope ())
01455             {
01456               voptgenerror 
01457                 (FLG_NESTEDEXTERN,
01458                  message ("Declaration using extern inside function scope: %q",
01459                           uentry_unparse (e)),
01460                  g_currentloc);
01461               
01462               uentry_setDefined (e, fileloc_getExternal ());
01463               sRef_setDefined (uentry_getSref (e), fileloc_getExternal ());
01464             }
01465 
01466           if (uentry_isFunction (e))
01467             {
01468               uentry_checkParams (e);
01469               checkParamNames (e);
01470             }
01471 
01472           if (uentry_isVar (e) 
01473               && uentry_isCheckedUnknown (e))
01474             {
01475               sRef sr = uentry_getSref (e);
01476 
01477               if (sRef_isLocalVar (sr))
01478                 {
01479                   if (context_getFlag (FLG_IMPCHECKMODINTERNALS))
01480                     {
01481                       uentry_setCheckMod (e);
01482                     }
01483                   else
01484                     {
01485                       uentry_setUnchecked (e);
01486                     }
01487                 }
01488               else if (sRef_isFileStatic (sr))
01489                 {
01490                   if (context_getFlag (FLG_IMPCHECKEDSTRICTSTATICS))
01491                     {
01492                       uentry_setCheckedStrict (e);
01493                     }
01494                   else if (context_getFlag (FLG_IMPCHECKEDSTATICS))
01495                     {
01496                       uentry_setChecked (e);
01497                     }
01498                   else if (context_getFlag (FLG_IMPCHECKMODSTATICS))
01499                     {
01500                       uentry_setCheckMod (e);
01501                     }
01502                   else
01503                     {
01504                       ;
01505                     }
01506                 }
01507               else /* real global */
01508                 {
01509                   llassert (sRef_isRealGlobal (sr));
01510 
01511                   if (context_getFlag (FLG_IMPCHECKEDSTRICTGLOBALS))
01512                     {
01513                       uentry_setCheckedStrict (e);
01514                     }
01515                   else if (context_getFlag (FLG_IMPCHECKEDGLOBALS))
01516                     {
01517                       uentry_setChecked (e);
01518                     }
01519                   else if (context_getFlag (FLG_IMPCHECKMODGLOBALS))
01520                     {
01521                       uentry_setCheckMod (e);
01522                     }
01523                   else
01524                     {
01525                       ;
01526                     }
01527                 }
01528             }
01529         }
01530     }
01531   else if (ProcessingTypedef)
01532     {
01533       ctype ct = idDecl_getCtype (t);
01534       uentry e;
01535 
01536       DPRINTF (("Processing typedef: %s", ctype_unparse (ct)));
01537       
01538       e = uentry_makeIdDatatype (t);
01539 
01540       if (cstring_equal (idDecl_getName (t), context_getBoolName ())) {
01541         ctype rt = ctype_realType (ct);
01542         
01543         if (ctype_isEnum (rt)) {
01544           ;
01545         } else {
01546           if (!(ctype_isInt (rt)
01547                 || ctype_isUnknown (rt)
01548                 || ctype_isChar (rt))) {
01549             (void) llgenerror
01550               (FLG_BOOLTYPE, 
01551                message ("Boolean type %s defined using non-standard type %s (integral, char or enum type expected)",
01552                         context_getBoolName (),
01553                         ctype_unparse (ct)),
01554                uentry_whereLast (e));
01555           }
01556           
01557           ct = ctype_bool;
01558           uentry_setType (e, ct);
01559         }
01560       }
01561 
01562       reflectStorageClass (e);
01563       checkTypeDecl (e, ct);
01564       
01565       e = usymtab_supReturnTypeEntry (e);
01566 
01567       if (uentry_isMaybeAbstract (e))
01568         {
01569           if (context_getFlag (FLG_IMPABSTRACT))
01570             {
01571               uentry_setAbstract (e);
01572             }
01573           else
01574             {
01575               uentry_setConcrete (e);
01576             }
01577         }
01578     }
01579   else
01580     {
01581       llparseerror (message ("Suspect missing struct or union keyword: %q",
01582                              idDecl_unparse (t)));
01583     }
01584 
01585   }
01586 
01587 /*
01588 ** moved from grammar
01589 */
01590 
01591 static idDecl fixStructDecl (/*@returned@*/ idDecl d)
01592 {
01593   if (ctype_isVisiblySharable (idDecl_getCtype (d)) 
01594       && context_getFlag (FLG_STRUCTIMPONLY))
01595     {
01596       if (!qualList_hasAliasQualifier (idDecl_getQuals (d)))
01597         {
01598           if (qualList_hasExposureQualifier (idDecl_getQuals (d)))
01599             {
01600               idDecl_addQual (d, qual_createDependent ());
01601             }
01602           else
01603             {
01604               idDecl_addQual (d, qual_createImpOnly ());
01605             }
01606         }
01607     }
01608 
01609   return d;
01610 }
01611 
01612 ctype
01613 declareUnnamedStruct (/*@only@*/ uentryList f)
01614 {
01615   if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
01616     {
01617       int num = uentryList_size (f);
01618       int max = context_getValue (FLG_NUMSTRUCTFIELDS);
01619 
01620       if (num > max)
01621         {
01622           voptgenerror 
01623             (FLG_NUMSTRUCTFIELDS,
01624              message ("Structure declared with %d fields "
01625                       "(limit is set to %d)",
01626                       num, max),
01627              g_currentloc);
01628         }
01629     }
01630 
01631   return (ctype_createUnnamedStruct (f));
01632 }
01633 
01634 ctype
01635 declareUnnamedUnion (/*@only@*/ uentryList f)
01636 {
01637   if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
01638     {
01639       int num = uentryList_size (f);
01640       int max = context_getValue (FLG_NUMSTRUCTFIELDS);
01641 
01642       if (num > max)
01643         {
01644           voptgenerror 
01645             (FLG_NUMSTRUCTFIELDS,
01646              message ("Union declared with %d fields "
01647                       "(limit is set to %d)",
01648                       num, max),
01649              g_currentloc);
01650         }
01651     }
01652 
01653   return (ctype_createUnnamedUnion (f));
01654 }
01655 
01656 ctype declareStruct (cstring id, /*@only@*/ uentryList f)
01657 {
01658   ctype ct; 
01659   uentry ue;
01660   int num = uentryList_size (f);
01661 
01662   ct = ctype_createStruct (cstring_copy (id), f);
01663   ue = uentry_makeStructTagLoc (id, ct);
01664 
01665   if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
01666     {
01667       int max = context_getValue (FLG_NUMSTRUCTFIELDS);
01668 
01669       if (num > max)
01670         {
01671           voptgenerror 
01672             (FLG_NUMSTRUCTFIELDS,
01673              message ("Structure %q declared with %d fields "
01674                       "(limit is set to %d)",
01675                       uentry_getName (ue), num, max),
01676              uentry_whereLast (ue));
01677         }
01678     }
01679 
01680   return (usymtab_supTypeEntry (ue));
01681 }
01682 
01683 ctype declareUnion (cstring id, uentryList f)
01684 {
01685   ctype ct; 
01686   uentry ue;
01687   int num = uentryList_size (f);
01688 
01689   ct = ctype_createUnion (cstring_copy (id), f);
01690   ue = uentry_makeUnionTagLoc (id, ct);
01691 
01692   if (context_maybeSet (FLG_NUMSTRUCTFIELDS))
01693     {
01694       int max = context_getValue (FLG_NUMSTRUCTFIELDS);
01695 
01696       if (num > max)
01697         {
01698           voptgenerror 
01699             (FLG_NUMSTRUCTFIELDS,
01700              message ("Union %q declared with %d fields "
01701                       "(limit is set to %d)",
01702                       uentry_getName (ue), num, max),
01703              uentry_whereLast (ue));
01704         }
01705     }
01706 
01707   return (usymtab_supTypeEntry (ue));
01708 }
01709 
01710 ctype handleStruct (/*@only@*/ cstring id)
01711 {
01712   if (usymtab_existsStructTag (id))
01713     {
01714       ctype ct = uentry_getAbstractType (usymtab_lookupStructTag (id));
01715 
01716       cstring_free (id);
01717       return ct;
01718     }
01719   else
01720     {
01721       return (ctype_createForwardStruct (id));
01722     }
01723 }
01724 
01725 ctype handleUnion (/*@only@*/ cstring id)
01726 {
01727   if (usymtab_existsUnionTag (id))
01728     {
01729       ctype ret = uentry_getAbstractType (usymtab_lookupUnionTag (id));
01730       cstring_free (id);
01731       return (ret);
01732     }
01733   else
01734     {
01735       return (ctype_createForwardUnion (id));
01736     }
01737 }
01738 
01739 ctype
01740 handleEnum (cstring id)
01741 {
01742   if (usymtab_existsEnumTag (id))
01743     {
01744       ctype ret = uentry_getAbstractType (usymtab_lookupEnumTag (id));
01745       cstring_free (id);
01746       return ret;
01747     }
01748   else
01749     {
01750       return (declareEnum (id, enumNameList_new ()));
01751     }
01752 }
01753 
01754 bool processingIterVars (void) 
01755 { 
01756   return ProcessingIterVars; 
01757 }
01758 
01759 uentry getCurrentIter (void) 
01760 {
01761   return currentIter; 
01762 }
01763 
01764 static bool flipOldStyle = FALSE;
01765 static bool flipNewStyle = TRUE;
01766 
01767 void setFlipOldStyle ()          { flipOldStyle = TRUE; }
01768 bool isFlipOldStyle ()           { return flipOldStyle; }
01769 bool isNewStyle ()               { return flipNewStyle; }
01770 void setNewStyle ()              { flipNewStyle = TRUE; }
01771 
01772 /*@dependent@*/ uentryList handleParamIdList (/*@dependent@*/ uentryList params)
01773 {  
01774   int paramno = 0;
01775 
01776   /*
01777   ** this is a really YUCKY hack to handle old style
01778   ** declarations.
01779   */
01780   
01781   voptgenerror (FLG_OLDSTYLE,
01782                 cstring_makeLiteral ("Old style function declaration"),
01783                 g_currentloc); 
01784 
01785   uentryList_elements (params, current)
01786     {
01787       uentry_setParam (current);
01788       uentry_setSref (current, sRef_makeParam (paramno, ctype_unknown));
01789       paramno++;
01790     } end_uentryList_elements;
01791 
01792   setGenericParamList (params);
01793   g_expectingTypeName = TRUE; 
01794 
01795   return params;
01796 }
01797 
01798 /*@dependent@*/ uentryList handleParamTypeList (/*@returned@*/ uentryList params)
01799 {
01800   if (flipOldStyle)
01801     {
01802       uentryList_fixMissingNames (params);
01803 
01804       voptgenerror (FLG_OLDSTYLE, 
01805                     cstring_makeLiteral ("Old style function declaration."), 
01806                     g_currentloc); 
01807       
01808       setGenericParamList (params);
01809       flipOldStyle = FALSE;
01810       g_expectingTypeName = TRUE; 
01811     }
01812  
01813   return (params); 
01814 }
01815 
01816 void
01817 doVaDcl ()
01818 {
01819   ctype c = ctype_unknown;
01820   cstring id = cstring_makeLiteral ("va_alist");
01821   uentry e;
01822 
01823   if (ProcessingParams)
01824     {
01825       int i = uentryList_lookupRealName (saveParamList, id);
01826       
01827       if (i >= 0)
01828         {
01829           e = uentry_makeVariableSrefParam (id, c, sRef_makeParam (i, c));
01830         }
01831       else
01832         {
01833           e = uentry_undefined; /* suppress gcc message */
01834           llfatalerrorLoc (cstring_makeLiteral ("va_dcl used without va_alist"));
01835         }
01836     }
01837   else
01838     {    
01839       llerror (FLG_SYNTAX, cstring_makeLiteral ("va_dcl used outside of function declaration"));
01840       e = uentry_makeVariableLoc (id, c);
01841     }
01842 
01843   cstring_free (id);
01844   uentry_setUsed (e, g_currentloc);  
01845   usymtab_supEntrySref (e);
01846 }
01847 
01848 /*@exposed@*/ sRef modListPointer (sRef s)
01849 {
01850   ctype ct = sRef_getType (s);
01851   ctype rt = ctype_realType (ct);
01852   
01853   if (ctype_isAP (rt))
01854     {
01855       if (context_inHeader () && ctype_isAbstract (ct))
01856         {
01857           voptgenerror 
01858             (FLG_ABSTRACT,
01859              message
01860              ("Modifies clause in header file dereferences abstract "
01861               "type %s (interface modifies clause should not depend "
01862               "on or expose type representation): %q",
01863               ctype_unparse (ct),
01864               sRef_unparse (s)),
01865              g_currentloc);
01866         }
01867 
01868       return (sRef_constructPointer (s));
01869     }
01870   else
01871     {
01872       if (ctype_isKnown (rt))
01873         {
01874           voptgenerror 
01875             (FLG_TYPE,
01876              message ("Implementation modifies clause dereferences non-pointer (type %s): %q",
01877                       ctype_unparse (rt),
01878                       sRef_unparse (s)),
01879              g_currentloc);
01880         }
01881 
01882       return s;
01883     }
01884 }
01885 
01886 /*@exposed@*/ sRef modListFieldAccess (sRef s, cstring f)
01887 {
01888   ctype ct = sRef_getType (s);
01889   ctype rt = ctype_realType (ct);
01890   
01891   if (ctype_isStructorUnion (rt))
01892     {
01893       uentry tf = uentryList_lookupField (ctype_getFields (rt), f);
01894       
01895       if (uentry_isUndefined (tf))
01896         {
01897           voptgenerror (FLG_TYPE,
01898                         message ("Modifies list accesses non-existent "
01899                                  "field %s of %t: %q", f, ct, 
01900                                  sRef_unparse (s)),
01901                         g_currentloc);
01902           
01903           cstring_free (f);
01904           return sRef_undefined;
01905         }
01906       else 
01907         {
01908           if (ctype_isAbstract (ct) && context_inHeader ())
01909             {
01910               voptgenerror 
01911                 (FLG_ABSTRACT,
01912                  message
01913                  ("Modifies clause in header file accesses abstract "
01914                   "type %s (interface modifies clause should not depend "
01915                   "on or expose type representation): %q",
01916                   ctype_unparse (ct),
01917                   sRef_unparse (s)),
01918                  g_currentloc);
01919             }
01920         }
01921       
01922       cstring_markOwned (f);
01923       return (sRef_makeField (s, f));
01924     }
01925   else
01926     {
01927       voptgenerror 
01928         (FLG_TYPE,
01929          message ("Modifies clause dereferences non-pointer (type %s): %q",
01930                   ctype_unparse (rt),
01931                   sRef_unparse (s)),
01932          g_currentloc);
01933       
01934       cstring_free (f);
01935       return s;
01936     }
01937 }
01938 
01939 sRef globListUnrecognized (cstring s)
01940 {
01941   if (cstring_equalLit (s, "nothing"))
01942     {
01943       return sRef_makeNothing ();
01944     }
01945   else if (cstring_equalLit (s, "internalState"))
01946     {
01947       return sRef_makeInternalState ();
01948     }
01949   else if (cstring_equalLit (s, "fileSystem")
01950            || cstring_equalLit (s, "systemState"))
01951     {
01952       return sRef_makeSystemState ();
01953     }
01954   else
01955     {
01956       voptgenerror 
01957         (FLG_UNRECOG, 
01958          message ("Unrecognized identifier in globals list: %s", s), 
01959          g_currentloc);
01960       
01961       return sRef_undefined;
01962     }
01963 }
01964 
01965 /*@exposed@*/ sRef modListArrowAccess (sRef s, cstring f)
01966 {
01967   ctype ct = sRef_getType (s);
01968   ctype rt = ctype_realType (ct);
01969 
01970   if (ctype_isRealPointer (rt))
01971     {
01972       ctype b = ctype_baseArrayPtr (rt);
01973       ctype rb = ctype_realType (b);
01974 
01975       if (ctype_isStructorUnion (rb))
01976         {
01977           uentry tf = uentryList_lookupField (ctype_getFields (rb), f);
01978       
01979           if (uentry_isUndefined (tf))
01980             {
01981               voptgenerror (FLG_TYPE,
01982                             message ("Modifies list arrow accesses non-existent "
01983                                      "field %s of %t: %q", f, b, 
01984                                      sRef_unparse (s)),
01985                             g_currentloc);
01986               
01987               cstring_free (f);
01988               return sRef_undefined;
01989             }
01990           else 
01991             {
01992               if (context_inHeader ())
01993                 {
01994                   if (ctype_isAbstract (b))
01995                     {
01996                       voptgenerror 
01997                         (FLG_ABSTRACT,
01998                          message
01999                          ("Modifies clause in header file arrow accesses abstract "
02000                           "type %s (interface modifies clause should not depend "
02001                           "on or expose type representation): %q",
02002                           ctype_unparse (b),
02003                           sRef_unparse (s)),
02004                          g_currentloc);
02005                     }
02006                 }
02007               else 
02008                 {
02009                   if (ctype_isAbstract (ct))
02010                     {
02011                       voptgenerror 
02012                         (FLG_ABSTRACT,
02013                          message
02014                          ("Modifies clause in header file arrow accesses abstract "
02015                           "type %s (interface modifies clause should not depend "
02016                           "on or expose type representation): %q",
02017                           ctype_unparse (ct),
02018                           sRef_unparse (s)),
02019                          g_currentloc);
02020                     }
02021                 }
02022             }
02023 
02024           cstring_markOwned (f);
02025           return (sRef_makeArrow (s, f));
02026         }
02027       else
02028         {
02029           voptgenerror 
02030             (FLG_TYPE,
02031              message ("Modifies clause arrow accesses pointer to "
02032                       "non-structure (type %s): %q",
02033                       ctype_unparse (rt),
02034                       sRef_unparse (s)),
02035              g_currentloc);
02036         }
02037     }
02038   else
02039     {
02040       voptgenerror 
02041         (FLG_TYPE,
02042          message ("Modifies clause arrow accesses non-pointer (type %s): %q",
02043                   ctype_unparse (rt),
02044                   sRef_unparse (s)),
02045          g_currentloc);
02046     }
02047 
02048   cstring_free (f);
02049   return s;
02050 }
02051 
02052 sRef checkSpecClausesId (uentry ue)
02053 {
02054   cstring s = uentry_rawName (ue);
02055 
02056   if (sRef_isGlobal (uentry_getSref (ue)))
02057     {
02058       voptgenerror 
02059         (FLG_SYNTAX, 
02060          message ("Global variable %s used special clause.  (Global variables "
02061                   "are not recognized in special clauses.  If there is "
02062                   "sufficient interest in support for this, it may be "
02063                   "added to a future release.  Send mail to "
02064                   "lclint@cs.virginia.edu.)",
02065                   s),
02066          g_currentloc);
02067       
02068       return sRef_undefined;
02069     }
02070   else
02071     {
02072       if (cstring_equalLit (s, "result"))
02073         {
02074           if (optgenerror 
02075               (FLG_SYNTAX, 
02076                message ("Special clause list uses %s which is a variable and has special "
02077                         "meaning in a modifies list.  (Special meaning assumed.)", s), 
02078                g_currentloc))
02079             {
02080               uentry_showWhereDeclared (ue);
02081             }
02082         }
02083 
02084       return uentry_getSref (ue);
02085     }
02086 }
02087 
02088 
02089 void checkModifiesId (uentry ue)
02090 {
02091   cstring s = uentry_rawName (ue);
02092 
02093   if (cstring_equalLit (s, "nothing")
02094       || cstring_equalLit (s, "internalState")
02095       || cstring_equalLit (s, "systemState")
02096       || (cstring_equalLit (s, "fileSystem")))
02097     {
02098       if (optgenerror 
02099           (FLG_SYNTAX, 
02100            message ("Modifies list uses %s which is a variable and has special "
02101                     "meaning in a modifies list.  (Special meaning assumed.)", s), 
02102            g_currentloc))
02103         {
02104           uentry_showWhereDeclared (ue);
02105         }
02106     }
02107 }
02108 
02109 /*@exposed@*/ sRef fixModifiesId (cstring s) 
02110 {
02111   sRef ret;
02112   cstring pname = makeParam (s);
02113   uentry ue = usymtab_lookupSafe (pname);
02114 
02115   cstring_free (pname);
02116 
02117   if (cstring_equalLit (s, "nothing"))
02118     {
02119       ret = sRef_makeNothing ();
02120     }
02121   else if (cstring_equalLit (s, "internalState"))
02122     {
02123       ret = sRef_makeInternalState ();
02124     }
02125   else if (cstring_equalLit (s, "fileSystem")
02126            || cstring_equalLit (s, "systemState"))
02127     {
02128       ret = sRef_makeSystemState ();
02129     }
02130   else
02131     {
02132       ret = sRef_undefined;
02133     }
02134 
02135   if (sRef_isValid (ret))
02136     {
02137       if (uentry_isValid (ue))
02138         {
02139           voptgenerror 
02140             (FLG_SYNTAX, 
02141              message ("Modifies list uses %s which is a parameter and has special "
02142                       "meaning in a modifies list.  (Special meaning assumed.)", s), 
02143              g_currentloc);
02144         }
02145     }
02146   else
02147     {
02148       if (uentry_isValid (ue))
02149         {
02150           ret = uentry_getSref (ue);
02151         }
02152       else
02153         {
02154           fileloc loc = fileloc_decColumn (g_currentloc, cstring_length (s));
02155           ret = sRef_undefined;
02156 
02157           voptgenerror 
02158             (FLG_UNRECOG, 
02159              message ("Unrecognized identifier in modifies comment: %s", s), 
02160              loc);
02161 
02162           fileloc_free (loc);
02163         }
02164     }
02165   
02166   return ret;
02167 }
02168 
02169 sRef fixSpecClausesId (cstring s) 
02170 {
02171   sRef ret;
02172   cstring pname = makeParam (s);
02173   uentry ue = usymtab_lookupSafe (pname);
02174 
02175   cstring_free (pname);
02176 
02177   if (cstring_equalLit (s, "result"))
02178     {
02179       ret = sRef_makeResult ();
02180     }
02181   else
02182     {
02183       ret = sRef_undefined;
02184     }
02185 
02186   if (sRef_isValid (ret))
02187     {
02188       if (uentry_isValid (ue))
02189         {
02190           voptgenerror 
02191             (FLG_SYNTAX, 
02192              message ("Special clause uses %s which is a parameter and has special "
02193                       "meaning in a special clause.  (Special meaning assumed.)", s), 
02194              g_currentloc);
02195         }
02196     }
02197   else
02198     {
02199       if (uentry_isValid (ue))
02200         {
02201           ret = uentry_getSref (ue);
02202 
02203           if (sRef_isGlobal (ret))
02204             {
02205               voptgenerror 
02206                 (FLG_SYNTAX, 
02207                  message ("Global variable %s used special clause.  (Global variables "
02208                           "are not recognized in special clauses.  If there is "
02209                           "sufficient interest in support for this, it may be "
02210                           "added to a future release.  Send mail to "
02211                           "lclint@cs.virginia.edu.)",
02212                           s), 
02213                  g_currentloc);
02214               
02215               ret = sRef_undefined;
02216             }
02217         }
02218       else
02219         {
02220           fileloc loc = fileloc_decColumn (g_currentloc, cstring_length (s));
02221           ret = sRef_undefined; 
02222           
02223           voptgenerror 
02224             (FLG_UNRECOG, 
02225              message ("Unrecognized identifier in special clause: %s", s), 
02226              loc);
02227 
02228           fileloc_free (loc);
02229         }
02230     }
02231   
02232   return ret;
02233 }
02234 
02235 sRef modListArrayFetch (sRef s, /*@unused@*/ sRef mexp)
02236 {
02237   ctype ct = sRef_getType (s);
02238   ctype rt = ctype_realType (ct);
02239 
02240   if (ctype_isAP (rt))
02241     {
02242       if (context_inHeader () && ctype_isAbstract (ct))
02243         {
02244           voptgenerror 
02245             (FLG_ABSTRACT,
02246              message
02247              ("Modifies clause in header file indexes abstract "
02248               "type %s (interface modifies clause should not depend "
02249               "on or expose type representation): %q",
02250               ctype_unparse (ct),
02251               sRef_unparse (s)),
02252              g_currentloc);
02253         }
02254       
02255       return (sRef_makeAnyArrayFetch (s));
02256     }
02257   else
02258     {
02259       voptgenerror
02260         (FLG_TYPE,
02261          message
02262          ("Implementation modifies clause uses array fetch on non-array (type %s): %q",
02263           ctype_unparse (ct), sRef_unparse (s)),
02264          g_currentloc);
02265       return s;
02266     }
02267 }
02268 
02269 
02270 
02271 
02272 
02273 
02274 
02275 

Generated at Fri Nov 3 18:57:39 2000 for LCLint by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000