00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 # include "lclintMacros.nf"
00035 # include "llbasic.h"
00036 # include "gram.h"
00037 # include "lclscan.h"
00038 # include "lclsyntable.h"
00039 # include "lslparse.h"
00040 # include "usymtab_interface.h"
00041 # include "structNames.h"
00042
00043 static void
00044 declareFcnAux (fcnNode p_f, qtype p_qt, ctype p_ct, typeId p_tn,
00045 bool p_priv, bool p_spec);
00046
00047 static uentryList paramNodeList_toUentryList (paramNodeList p_p);
00048 static cstring getVarName ( typeExpr p_x);
00049 static qtype convertLclTypeSpecNode ( lclTypeSpecNode p_n);
00050 static ctype convertTypeExpr (ctype p_c, typeExpr p_x);
00051 static ctype convertCTypeExpr (ctype p_c, typeExpr p_x);
00052 static sRef fixTermNode (termNode p_n, fcnNode p_f, uentryList p_cl);
00053 static sRefSet fixModifies (fcnNode p_f, uentryList p_cl);
00054
00055 static uentryList
00056 convertuentryList (stDeclNodeList x)
00057 {
00058 uentryList fl = uentryList_new ();
00059
00060
00061 stDeclNodeList_elements (x, i)
00062 {
00063 declaratorNodeList d = i->declarators;
00064 qtype q = convertLclTypeSpecNode (i->lcltypespec);
00065
00066 declaratorNodeList_elements (d, j)
00067 {
00068 idDecl id;
00069
00070 qtype_setType (q, convertTypeExpr (qtype_getType (q), j->type));
00071 id = idDecl_create (cstring_copy (getVarName (j->type)), qtype_copy (q));
00072 fl = uentryList_add (fl, uentry_makeIdVariable (id));
00073 idDecl_free (id);
00074 } end_declaratorNodeList_elements;
00075
00076 qtype_free (q);
00077 } end_stDeclNodeList_elements;
00078
00079
00080 return (fl);
00081 }
00082
00083 static uentryList
00084 convert_uentryList (paramNodeList x)
00085 {
00086 uentryList p = uentryList_undefined;
00087 bool first_one = TRUE;
00088
00089
00090 paramNodeList_elements (x, i)
00091 {
00092 if (i != (paramNode) 0)
00093 {
00094 if (paramNode_isElipsis (i))
00095 {
00096 first_one = FALSE;
00097 p = uentryList_add (p, uentry_makeElipsisMarker ());
00098 }
00099 else
00100 {
00101 qtype q = convertLclTypeSpecNode (i->type);
00102 typeExpr t = i->paramdecl;
00103
00104 qtype_setType (q, convertTypeExpr (qtype_getType (q), t));
00105
00106
00107
00108 if (first_one)
00109 {
00110 if (ctype_isVoid (qtype_getType (q)))
00111 {
00112 llassert (uentryList_isUndefined (p));
00113 qtype_free (q);
00114 return (p);
00115 }
00116
00117 first_one = FALSE;
00118 }
00119
00120
00121
00122
00123
00124 p = uentryList_add (p, uentry_makeUnnamedVariable (qtype_getType (q)));
00125 qtype_free (q);
00126 }
00127 }
00128 else
00129 {
00130 llbug (cstring_makeLiteral ("convertuentryList: null paramNode"));
00131 }
00132 } end_paramNodeList_elements;
00133
00134 if (first_one)
00135 {
00136 llassert (uentryList_isUndefined (p));
00137
00138 p = uentryList_makeMissingParams ();
00139 }
00140
00141 return p;
00142 }
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 static ctype
00154 convertTypeExpr (ctype c, typeExpr x)
00155 {
00156 if (x == (typeExpr) 0)
00157 {
00158 return c;
00159 }
00160
00161 switch (x->kind)
00162 {
00163 case TEXPR_BASE:
00164 return (c);
00165 case TEXPR_PTR:
00166 return (convertTypeExpr (ctype_makePointer (c), x->content.pointer));
00167 case TEXPR_ARRAY:
00168 return (convertTypeExpr (ctype_makeArray (c), x->content.array.elementtype));
00169 case TEXPR_FCN:
00170 {
00171 ctype rv = convertTypeExpr (c, x->content.function.returntype);
00172 uentryList p = paramNodeList_toUentryList (x->content.function.args);
00173
00174 if (x->content.function.returntype != NULL
00175 && x->content.function.returntype->wrapped == 1
00176 && ctype_isPointer (rv))
00177 {
00178 rv = ctype_baseArrayPtr (rv);
00179 }
00180
00181 return (ctype_makeParamsFunction (rv, p));
00182 }
00183 default:
00184 {
00185 llfatalbug (message ("convertTypeExpr: unknown typeExprKind: %d",
00186 (int) x->kind));
00187 }
00188 }
00189
00190 BADEXIT;
00191 }
00192
00193 static
00194 ctype convertCTypeExpr (ctype c, typeExpr x)
00195 {
00196 if (x == (typeExpr) 0)
00197 {
00198 return c;
00199 }
00200
00201 switch (x->kind)
00202 {
00203 case TEXPR_BASE: return (c);
00204 case TEXPR_PTR: return (convertCTypeExpr (ctype_makePointer (c),
00205 x->content.pointer));
00206 case TEXPR_ARRAY: return (convertCTypeExpr (ctype_makeArray (c),
00207 x->content.array.elementtype));
00208 case TEXPR_FCN:
00209 {
00210 ctype rv = convertCTypeExpr (c, x->content.function.returntype);
00211 uentryList p = convert_uentryList (x->content.function.args);
00212
00213 return (ctype_makeParamsFunction (rv, p));
00214 }
00215 default:
00216 {
00217 llfatalbug (message ("convertCTypeExpr: unknown typeExprKind: %d", (int) x->kind));
00218 }
00219 }
00220 BADEXIT;
00221 }
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237 static ctype
00238 convertLeaves (ltokenList f)
00239 {
00240 ctype c = ctype_unknown;
00241
00242 ltokenList_reset (f);
00243
00244 ltokenList_elements (f, current)
00245 {
00246 switch (ltoken_getCode (current))
00247 {
00248 case LLT_TYPEDEF_NAME:
00249 {
00250 cstring tn = ltoken_getRawString (current);
00251
00252 if (usymtab_existsTypeEither (tn))
00253 {
00254 c = ctype_combine (uentry_getAbstractType
00255 (usymtab_lookupEither (tn)), c);
00256 }
00257 else if (cstring_equalLit (tn, "bool"))
00258 {
00259
00260
00261
00262 c = ctype_bool;
00263 }
00264 else
00265 {
00266 fileloc loc = fileloc_fromTok (current);
00267
00268 voptgenerror (FLG_UNRECOG,
00269 message ("Unrecognized type: %s", tn), loc);
00270 fileloc_free (loc);
00271
00272 usymtab_supEntry
00273 (uentry_makeDatatype
00274 (tn, ctype_unknown, MAYBE, NO, fileloc_getBuiltin ()));
00275
00276 }
00277 break;
00278 }
00279 case LLT_CHAR:
00280 c = ctype_combine (ctype_char, c);
00281 break;
00282
00283 case LLT_DOUBLE:
00284 c = ctype_combine (ctype_double, c);
00285 break;
00286 case LLT_FLOAT:
00287 c = ctype_combine (ctype_float, c);
00288 break;
00289 case LLT_CONST:
00290 case LLT_VOLATILE:
00291 break;
00292 case LLT_INT:
00293 c = ctype_combine (ctype_int, c);
00294 break;
00295 case LLT_LONG:
00296 c = ctype_combine (c, ctype_lint);
00297 break;
00298 case LLT_SHORT:
00299 c = ctype_combine (c, ctype_sint);
00300 break;
00301 case LLT_SIGNED:
00302 c = ctype_combine (c, ctype_int);
00303 break;
00304 case LLT_UNSIGNED:
00305 c = ctype_combine (c, ctype_uint);
00306 break;
00307 case LLT_UNKNOWN:
00308 c = ctype_combine (ctype_unknown, c);
00309 break;
00310 case LLT_VOID:
00311 c = ctype_combine (ctype_void, c);
00312 break;
00313 case LLT_ENUM:
00314 llcontbug (cstring_makeLiteral ("convertLeaves: enum"));
00315 c = ctype_int;
00316 break;
00317 default:
00318 llfatalbug (message ("convertLeaves: bad token: %q",
00319 ltoken_unparseCodeName (current)));
00320 }
00321 } end_ltokenList_elements;
00322
00323 return c;
00324 }
00325
00326 static enumNameList
00327 convertEnumList (ltokenList enums)
00328 {
00329 enumNameList el = enumNameList_new ();
00330
00331 if (ltokenList_isDefined (enums))
00332 {
00333 ltokenList_elements (enums, i)
00334 {
00335 enumNameList_addh
00336 (el, enumName_create (cstring_copy (ltoken_unparse (i))));
00337 } end_ltokenList_elements;
00338 }
00339
00340 return el;
00341 }
00342
00343 static qtype
00344 convertLclTypeSpecNode ( lclTypeSpecNode n)
00345 {
00346
00347 if (n != (lclTypeSpecNode) 0)
00348 {
00349 qtype result;
00350
00351 switch (n->kind)
00352 {
00353 case LTS_CONJ:
00354 {
00355 qtype c1 = convertLclTypeSpecNode (n->content.conj->a);
00356 qtype c2 = convertLclTypeSpecNode (n->content.conj->b);
00357
00358
00359
00360
00361
00362 if (fileloc_isLib (g_currentloc)
00363 || fileloc_isStandardLibrary (g_currentloc))
00364 {
00365 result = qtype_mergeImplicitAlt (c1, c2);
00366 }
00367 else
00368 {
00369 result = qtype_mergeAlt (c1, c2);
00370 }
00371
00372 break;
00373 }
00374 case LTS_TYPE:
00375 llassert (n->content.type != NULL);
00376 result = qtype_create (convertLeaves (n->content.type->ctypes));
00377 break;
00378 case LTS_STRUCTUNION:
00379 {
00380 strOrUnionNode sn;
00381 cstring cn = cstring_undefined;
00382
00383 sn = n->content.structorunion;
00384
00385 llassert (sn != (strOrUnionNode) 0);
00386
00387 if (!ltoken_isUndefined (sn->opttagid))
00388 {
00389 cn = cstring_copy (ltoken_getRawString (sn->opttagid));
00390 }
00391 else
00392 {
00393 cn = fakeTag ();
00394 }
00395
00396 switch (sn->kind)
00397 {
00398 case SU_STRUCT:
00399 if (usymtab_existsStructTag (cn))
00400 {
00401
00402 result = qtype_create (uentry_getAbstractType
00403 (usymtab_lookupStructTag (cn)));
00404 cstring_free (cn);
00405 }
00406 else
00407 {
00408 uentryList fl = convertuentryList (sn->structdecls);
00409 ctype ct;
00410
00411 ct = ctype_createStruct (cstring_copy (cn), fl);
00412
00413
00414
00415
00416
00417
00418 if (usymtab_existsStructTag (cn))
00419 {
00420 result = qtype_create (uentry_getAbstractType
00421 (usymtab_lookupStructTag (cn)));
00422 }
00423 else
00424 {
00425 fileloc loc = fileloc_fromTok (n->content.structorunion->tok);
00426 uentry ue = uentry_makeStructTag (cn, ct, loc);
00427
00428 result = qtype_create (usymtab_supTypeEntry (ue));
00429 }
00430
00431 cstring_free (cn);
00432 }
00433 break;
00434 case SU_UNION:
00435 if (usymtab_existsUnionTag (cn))
00436 {
00437
00438 result = qtype_create (uentry_getAbstractType
00439 (usymtab_lookupUnionTag (cn)));
00440 cstring_free (cn);
00441 }
00442 else
00443 {
00444 uentryList fl;
00445 ctype ct;
00446
00447 fl = convertuentryList (sn->structdecls);
00448 ct = ctype_createUnion (cstring_copy (cn), fl);
00449
00450
00451
00452
00453
00454
00455
00456
00457 if (usymtab_existsUnionTag (cn))
00458 {
00459
00460 result = qtype_create (uentry_getAbstractType
00461 (usymtab_lookupUnionTag (cn)));
00462 }
00463 else
00464 {
00465 fileloc loc = fileloc_fromTok (n->content.structorunion->tok);
00466 uentry ue = uentry_makeUnionTag (cn, ct, loc);
00467
00468 result = qtype_create (usymtab_supTypeEntry (ue));
00469 }
00470
00471 cstring_free (cn);
00472 }
00473 break;
00474 BADDEFAULT
00475 }
00476 break;
00477 }
00478 case LTS_ENUM:
00479 {
00480 enumSpecNode e = n->content.enumspec;
00481 enumNameList el;
00482 cstring ename;
00483 bool first = TRUE;
00484 ctype ta;
00485 ctype cet;
00486
00487 llassert (e != NULL);
00488 el = convertEnumList (e->enums);
00489
00490 if (!ltoken_isUndefined (e->opttagid))
00491 {
00492 ename = cstring_copy (ltoken_getRawString (e->opttagid));
00493 }
00494 else
00495 {
00496 ename = fakeTag ();
00497 }
00498
00499 cet = ctype_createEnum (ename, el);
00500
00501 if (usymtab_existsEnumTag (ename))
00502 {
00503 ta = uentry_getAbstractType (usymtab_lookupEnumTag (ename));
00504 }
00505 else
00506 {
00507 fileloc loc = fileloc_fromTok (e->tok);
00508 uentry ue = uentry_makeEnumTag (ename, cet, loc);
00509
00510 ta = usymtab_supTypeEntry (ue);
00511 }
00512
00513 enumNameList_elements (el, en)
00514 {
00515 uentry ue;
00516 fileloc loc;
00517
00518 if (first)
00519 {
00520 ltokenList_reset (e->enums);
00521 first = FALSE;
00522 }
00523 else
00524 {
00525 ltokenList_advance (e->enums);
00526 }
00527
00528 loc = fileloc_fromTok (ltokenList_current (e->enums));
00529 ue = uentry_makeSpecEnumConstant (en, cet, loc);
00530
00531
00532
00533
00534
00535
00536 ue = usymtab_supGlobalEntryReturn (ue);
00537
00538 if (context_inLCLLib ())
00539 {
00540 uentry_setDefined (ue, loc);
00541 }
00542 } end_enumNameList_elements;
00543
00544 result = qtype_create (ta);
00545 }
00546 break;
00547 default:
00548 {
00549 llfatalbug (message ("convertLclTypeSpecNode: unknown lclTypeSpec kind: %d",
00550 (int) n->kind));
00551 }
00552 }
00553
00554 result = qtype_addQualList (result, n->quals);
00555
00556 if (n->pointers > 0)
00557 {
00558 qtype_adjustPointers (n->pointers, result);
00559 }
00560
00561 return result;
00562 }
00563 else
00564 {
00565 llcontbug (cstring_makeLiteral ("convertLclTypeSpecNode: null"));
00566 return qtype_unknown ();
00567 }
00568 BADEXIT;
00569 }
00570
00571 static multiVal
00572 literalValue (ctype ct, ltoken lit)
00573 {
00574 cstring text = cstring_fromChars (lsymbol_toChars (ltoken_getText (lit)));
00575 char first;
00576
00577 if (cstring_length (text) > 0)
00578 {
00579 first = cstring_firstChar (text);
00580 }
00581 else
00582 {
00583 return multiVal_unknown ();
00584 }
00585
00586
00587 if (first == '\"')
00588 {
00589 int len = cstring_length (text) - 2;
00590 char *val = mstring_create (len);
00591
00592 llassert (cstring_lastChar (text) == '\"');
00593 strncpy (val, cstring_toCharsSafe (text) + 1, size_fromInt (len));
00594 return (multiVal_makeString (cstring_fromCharsO (val)));
00595 }
00596
00597 if (ctype_isDirectInt (ct) || ctype_isPointer (ct))
00598 {
00599 long val = 0;
00600
00601 if (sscanf (cstring_toCharsSafe (text), "%ld", &val) == 1)
00602 {
00603 return multiVal_makeInt (val);
00604 }
00605 }
00606
00607 return multiVal_unknown ();
00608 }
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618 void
00619 doDeclareConstant (constDeclarationNode c, bool priv)
00620 {
00621 lclTypeSpecNode t;
00622 ctype ctx;
00623 qtype qt;
00624
00625 if (c == (constDeclarationNode) 0)
00626 {
00627 return;
00628 }
00629
00630 t = c->type;
00631 qt = convertLclTypeSpecNode (t);
00632
00633 ctx = qtype_getType (qt);
00634
00635 initDeclNodeList_elements (c->decls, i)
00636 {
00637 ctype ct = convertTypeExpr (ctx, i->declarator->type);
00638 cstring s = getVarName (i->declarator->type);
00639
00640 if (ctype_isFunction (ct))
00641 {
00642 fcnNode fcn = fcnNode_fromDeclarator (lclTypeSpecNode_copy (t),
00643 declaratorNode_copy (i->declarator));
00644
00645
00646
00647 doDeclareFcn (fcn, typeId_invalid, priv, FALSE);
00648 fcnNode_free (fcn);
00649 }
00650 else
00651 {
00652 uentry ue;
00653 fileloc loc = fileloc_fromTok (i->declarator->id);
00654
00655 if (i->value != (termNode)0 &&
00656 i->value->kind == TRM_LITERAL)
00657 {
00658 ue = uentry_makeConstantAux (s, ct, loc, priv,
00659 literalValue (ct, i->value->literal));
00660 }
00661 else
00662 {
00663 ue = uentry_makeConstantAux (s, ct, loc, priv, multiVal_unknown ());
00664 }
00665
00666 uentry_reflectQualifiers (ue, qtype_getQuals (qt));
00667
00668
00669 if (context_inLCLLib () && !priv)
00670 {
00671 uentry_setDefined (ue, loc);
00672 }
00673
00674 usymtab_supGlobalEntry (ue);
00675 }
00676 } end_initDeclNodeList_elements;
00677
00678 qtype_free (qt);
00679 }
00680
00681 static cstring
00682 getVarName ( typeExpr x)
00683 {
00684 cstring s = cstring_undefined;
00685
00686 if (x != (typeExpr) 0)
00687 {
00688 switch (x->kind)
00689 {
00690 case TEXPR_BASE:
00691 s = ltoken_getRawString (x->content.base);
00692 break;
00693 case TEXPR_PTR:
00694 s = getVarName (x->content.pointer);
00695 break;
00696 case TEXPR_ARRAY:
00697 s = getVarName (x->content.array.elementtype);
00698 break;
00699 case TEXPR_FCN:
00700 s = getVarName (x->content.function.returntype);
00701 break;
00702 default:
00703 llfatalbug (message ("getVarName: unknown typeExprKind: %d", (int) x->kind));
00704 }
00705 }
00706
00707 return s;
00708 }
00709
00710 void
00711 doDeclareVar (varDeclarationNode v, bool priv)
00712 {
00713 lclTypeSpecNode t;
00714 qtype c;
00715
00716 if (v == (varDeclarationNode) 0)
00717 {
00718 return;
00719 }
00720
00721 t = v->type;
00722 c = convertLclTypeSpecNode (t);
00723
00724 initDeclNodeList_elements (v->decls, i)
00725 {
00726 ctype ct = convertTypeExpr (qtype_getType (c), i->declarator->type);
00727 cstring s = getVarName (i->declarator->type);
00728
00729 qtype_setType (c, ct);
00730
00731 if (ctype_isFunction (ct))
00732 {
00733 fcnNode fcn;
00734
00735
00736 fcn = fcnNode_fromDeclarator (lclTypeSpecNode_copy (t),
00737 declaratorNode_copy (i->declarator));
00738
00739
00740 declareFcnAux (fcn, qtype_unknown (), ct,
00741 typeId_invalid, priv, FALSE);
00742 fcnNode_free (fcn);
00743 }
00744 else
00745 {
00746 fileloc loc = fileloc_fromTok (i->declarator->id);
00747 uentry le = uentry_makeVariable (s, ct, loc, priv);
00748
00749 uentry_reflectQualifiers (le, qtype_getQuals (c));
00750
00751 if (uentry_isCheckedUnknown (le))
00752 {
00753 if (context_getFlag (FLG_IMPCHECKEDSTRICTSPECGLOBALS))
00754 {
00755 uentry_setCheckedStrict (le);
00756 }
00757 else if (context_getFlag (FLG_IMPCHECKEDSPECGLOBALS))
00758 {
00759 uentry_setChecked (le);
00760 }
00761 else if (context_getFlag (FLG_IMPCHECKMODSPECGLOBALS))
00762 {
00763 uentry_setCheckMod (le);
00764 }
00765 else
00766 {
00767 ;
00768 }
00769 }
00770
00771 if (context_inLCLLib () && !priv)
00772 {
00773 uentry_setDefined (le, loc);
00774 }
00775
00776 if (initDeclNode_isRedeclaration (i))
00777 {
00778 usymtab_replaceEntry (le);
00779 }
00780 else
00781 {
00782 le = usymtab_supEntrySrefReturn (le);
00783 }
00784 }
00785 } end_initDeclNodeList_elements;
00786
00787 qtype_free (c);
00788 }
00789
00790 static globSet
00791 processGlob ( globSet globs, varDeclarationNode v)
00792 {
00793 if (v == (varDeclarationNode) 0)
00794 {
00795 return globs;
00796 }
00797
00798 if (v->isSpecial)
00799 {
00800 globs = globSet_insert (globs, v->sref);
00801 }
00802 else
00803 {
00804 lclTypeSpecNode t = v->type;
00805 qtype qt = convertLclTypeSpecNode (t);
00806 ctype c = qtype_getType (qt);
00807 cstring s;
00808
00809 initDeclNodeList_elements (v->decls, i)
00810 {
00811 ctype ct;
00812 uentry ue;
00813 qualList quals = qtype_getQuals (qt);
00814
00815 s = getVarName (i->declarator->type);
00816 ue = usymtab_lookupGlobSafe (s);
00817
00818 if (uentry_isInvalid (ue))
00819 {
00820 ;
00821 }
00822 else
00823 {
00824 if (uentry_isPriv (ue))
00825 {
00826 globs = globSet_insert (globs, sRef_makeSpecState ());
00827 }
00828 else
00829 {
00830 uentry ce = uentry_copy (ue);
00831 ctype lt = uentry_getType (ce);
00832 fileloc loc = fileloc_fromTok (i->declarator->id);
00833
00834 ct = convertTypeExpr (c, i->declarator->type);
00835
00836 if (!ctype_match (lt, ct))
00837 {
00838 (void) gentypeerror
00839 (lt, exprNode_undefined,
00840 ct, exprNode_undefined,
00841 message ("Global type mismatch %s (%t, %t)",
00842 s, lt, ct),
00843 loc);
00844 }
00845
00846 uentry_reflectQualifiers (ce, quals);
00847 globs = globSet_insert (globs,
00848 sRef_copy (uentry_getSref (ce)));
00849 fileloc_free (loc);
00850 uentry_free (ce);
00851 }
00852 }
00853 } end_initDeclNodeList_elements;
00854
00855 qtype_free (qt);
00856 }
00857
00858 return globs;
00859 }
00860
00861 static void
00862 declareAbstractType (abstractNode n, bool priv)
00863 {
00864 cstring tn;
00865 fileloc loc;
00866 uentry ue;
00867 usymId uid;
00868 abstBodyNode ab;
00869
00870 if (n == (abstractNode) 0)
00871 {
00872 return;
00873 }
00874
00875
00876 tn = ltoken_getRawString (n->name);
00877
00878 loc = fileloc_fromTok (n->tok);
00879
00880 ue = uentry_makeDatatypeAux (tn, ctype_unknown,
00881 ynm_fromBool (n->isMutable), YES, loc, priv);
00882
00883 if (n->isRefCounted)
00884 {
00885 uentry_setRefCounted (ue);
00886 }
00887
00888 if (context_inLCLLib () && !priv)
00889 {
00890 uentry_setDefined (ue, loc);
00891 }
00892
00893 uid = usymtab_supAbstractTypeEntry (ue, context_inLCLLib() && !priv);
00894
00895
00896 if (!priv && (ab = n->body) != (abstBodyNode) 0)
00897 {
00898 fcnNodeList ops = ab->fcns;
00899
00900 if (!fcnNodeList_isEmpty (ops))
00901 {
00902 fcnNodeList_elements (ops, i)
00903 {
00904 if (i->typespec == (lclTypeSpecNode) 0)
00905 {
00906 cstring fname = ltoken_getRawString (i->name);
00907
00908 if (usymtab_exists (fname))
00909 {
00910 uentry e = usymtab_lookup (fname);
00911 fileloc floc = fileloc_fromTok (i->declarator->id);
00912
00913 if (uentry_isForward (e))
00914 {
00915 usymtab_supEntry
00916 (uentry_makeTypeListFunction
00917 (fname, typeIdSet_insert (uentry_accessType (e), uid),
00918 floc));
00919 }
00920 else
00921 {
00922 usymtab_supEntry
00923 (uentry_makeSpecFunction
00924 (fname, uentry_getType (e),
00925 typeIdSet_insert (uentry_accessType (e), uid),
00926 globSet_undefined,
00927 sRefSet_undefined,
00928 floc));
00929
00930 if (context_inLCLLib ())
00931 {
00932 llbuglit ("Jolly jeepers Wilma, it ain't dead after all!");
00933 }
00934 }
00935 }
00936 else
00937 {
00938 usymtab_supEntry
00939 (uentry_makeForwardFunction (fname, uid, loc));
00940 }
00941 }
00942 else
00943 {
00944 declareFcn (i, uid);
00945 }
00946 } end_fcnNodeList_elements;
00947 }
00948 }
00949 }
00950
00951 static void
00952 declareExposedType (exposedNode n, bool priv)
00953 {
00954 usymId uid;
00955 qtype c;
00956 cstring s;
00957
00958
00959 if (n == (exposedNode) 0)
00960 {
00961 return;
00962 }
00963
00964 c = convertLclTypeSpecNode (n->type);
00965
00966 declaratorInvNodeList_elements (n->decls, i)
00967 {
00968 ctype realType = convertTypeExpr (qtype_getType (c), i->declarator->type);
00969 fileloc loc = fileloc_fromTok (i->declarator->id);
00970 uentry ue;
00971
00972 s = getVarName (i->declarator->type);
00973
00974 ue = uentry_makeDatatypeAux (s, realType, MAYBE, NO, loc, priv);
00975
00976 uentry_reflectQualifiers (ue, qtype_getQuals (c));
00977
00978 if (context_inLCLLib () && !priv)
00979 {
00980 uentry_setDefined (ue, loc);
00981 }
00982
00983 uid = usymtab_supExposedTypeEntry (ue, context_inLCLLib () && !priv);
00984 } end_declaratorInvNodeList_elements;
00985
00986 qtype_free (c);
00987 }
00988
00989
00990
00991
00992
00993
00994
00995
00996 void
00997 doDeclareType (typeNode t, bool priv)
00998 {
00999
01000 if (t != (typeNode) 0)
01001 {
01002 switch (t->kind)
01003 {
01004 case TK_ABSTRACT:
01005 declareAbstractType (t->content.abstract, priv);
01006 break;
01007
01008 case TK_EXPOSED:
01009 declareExposedType (t->content.exposed, priv);
01010 break;
01011
01012 case TK_UNION:
01013 default:
01014 {
01015 llfatalbug (message ("declareType ERROR: unknown kind: %q",
01016 cstring_fromCharsO (FormatInt ((int)t->kind))));
01017 }
01018 }
01019 }
01020
01021 }
01022
01023 extern void
01024 declareIter (iterNode iter)
01025 {
01026 fileloc loc = fileloc_fromTok (iter->name);
01027 uentry ue =
01028 uentry_makeIter (ltoken_unparse (iter->name),
01029 ctype_makeFunction
01030 (ctype_void,
01031 paramNodeList_toUentryList (iter->params)),
01032 fileloc_copy (loc));
01033
01034 usymtab_supEntry (ue);
01035 usymtab_supEntry
01036 (uentry_makeEndIter (ltoken_unparse (iter->name), loc));
01037 }
01038
01039
01040
01041
01042
01043 static void
01044 declareFcnAux (fcnNode f, qtype qt, ctype ct,
01045 typeId tn, bool priv, bool spec)
01046 {
01047 globalList globals;
01048 typeIdSet acct;
01049 sRefSet sl = sRefSet_undefined;
01050 globSet globlist = globSet_undefined;
01051 cstring s = getVarName (f->declarator->type);
01052 fileloc loc = fileloc_fromTok (f->declarator->id);
01053 uentryList args;
01054
01055
01056
01057
01058
01059 if (ctype_isFunction (ct))
01060 {
01061 args = ctype_argsFunction (ct);
01062 }
01063 else
01064 {
01065 llcontbug (message ("Not function: %s", ctype_unparse (ct)));
01066 args = uentryList_undefined;
01067 }
01068
01069
01070 fileloc_setColumnUndefined (loc);
01071
01072 if (spec)
01073 {
01074 globals = f->globals;
01075
01076 sl = fixModifies (f, args);
01077
01078
01079
01080
01081
01082 varDeclarationNodeList_elements (globals, glob)
01083 {
01084 globlist = processGlob (globlist, glob);
01085 } end_varDeclarationNodeList_elements;
01086
01087
01088 if (f->checks != (lclPredicateNode) 0)
01089
01090
01091 {
01092 uentry ue;
01093
01094 if (!(usymtab_existsVar (cstring_makeLiteralTemp ("stderr"))))
01095 {
01096 ctype tfile;
01097
01098 llmsglit ("Global stderr implied by checks clause, "
01099 "not declared in initializations.");
01100
01101 tfile = usymtab_lookupType (cstring_makeLiteralTemp ("FILE"));
01102
01103 if (ctype_isUndefined (tfile))
01104 {
01105 llmsglit ("FILE datatype implied by checks clause not defined.");
01106 tfile = ctype_unknown;
01107 }
01108
01109 usymtab_supGlobalEntry
01110 (uentry_makeVariable (cstring_makeLiteralTemp ("stderr"),
01111 tfile, fileloc_getBuiltin (), FALSE));
01112 }
01113
01114 ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stderr"));
01115
01116 globlist = globSet_insert (globlist, sRef_copy (uentry_getSref (ue)));
01117 sl = sRefSet_insert (sl, sRef_buildPointer (uentry_getSref (ue)));
01118
01119 }
01120 }
01121
01122 if (usymId_isInvalid (tn))
01123 {
01124 acct = context_fileAccessTypes ();
01125 }
01126 else
01127 {
01128 acct = typeIdSet_single (tn);
01129 }
01130
01131 if (usymtab_exists (s))
01132 {
01133 uentry l = usymtab_lookup (s);
01134 uentry ue;
01135
01136 if (uentry_isForward (l) || (fileloc_isLib (uentry_whereSpecified (l))))
01137 {
01138 typeIdSet accessType;
01139
01140 if (uentry_isFunction (l))
01141 {
01142 accessType = typeIdSet_union (uentry_accessType (l),
01143 context_fileAccessTypes ());
01144 }
01145 else
01146 {
01147 accessType = context_fileAccessTypes ();
01148 }
01149
01150 if (spec)
01151 {
01152 ue = uentry_makeSpecFunction (s, ct, accessType, globlist, sl, loc);
01153 }
01154 else
01155 {
01156 sRefSet_free (sl);
01157 globSet_free (globlist);
01158
01159 ue = uentry_makeUnspecFunction (s, ct, accessType, loc);
01160 }
01161
01162 uentry_reflectQualifiers (ue, qtype_getQuals (qt));
01163
01164 usymtab_supEntry (ue);
01165 }
01166 else
01167 {
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177 fileloc_free (loc);
01178 sRefSet_free (sl);
01179 globSet_free (globlist);
01180 }
01181 }
01182 else
01183 {
01184 uentry le;
01185
01186 if (spec)
01187 {
01188 if (priv)
01189 {
01190 le = uentry_makePrivFunction2 (s, ct, acct, globlist, sl, loc);
01191 }
01192 else
01193 {
01194 le = uentry_makeSpecFunction (s, ct, acct, globlist, sl, loc);
01195 }
01196 }
01197 else
01198 {
01199 le = uentry_makeUnspecFunction (s, ct, acct, loc);
01200
01201 sRefSet_free (sl);
01202 globSet_free (globlist);
01203 }
01204
01205 if (context_inLCLLib () && !priv)
01206 {
01207 uentry_setDefined (le, loc);
01208 }
01209
01210 uentry_reflectQualifiers (le, qtype_getQuals (qt));
01211
01212 switch (f->special)
01213 {
01214 case QU_UNKNOWN: break;
01215 case QU_PRINTFLIKE: uentry_setPrintfLike (le); break;
01216 case QU_SCANFLIKE: uentry_setScanfLike (le); break;
01217 case QU_MESSAGELIKE: uentry_setMessageLike (le); break;
01218 BADDEFAULT;
01219 }
01220
01221 usymtab_supEntry (le);
01222 }
01223
01224 qtype_free (qt);
01225 }
01226
01227 extern void
01228 doDeclareFcn (fcnNode f, typeId tn, bool priv, bool spec)
01229 {
01230 qtype qt = convertLclTypeSpecNode (f->typespec);
01231 ctype ct = convertTypeExpr (qtype_getType (qt), f->declarator->type);
01232
01233 declareFcnAux (f, qt, ct, tn, priv, spec);
01234 }
01235
01236
01237
01238
01239
01240
01241 static int
01242 getParamNo (cstring s, fcnNode f)
01243 {
01244
01245 paramNodeList params;
01246 typeExpr fd = f->declarator->type;
01247
01248
01249
01250 while (fd != NULL && (fd->kind == TEXPR_PTR || fd->kind == TEXPR_ARRAY))
01251 {
01252 if (fd->kind == TEXPR_PTR)
01253 {
01254 fd = fd->content.pointer;
01255 }
01256 else
01257 {
01258 fd = fd->content.array.elementtype;
01259
01260
01261
01262
01263
01264
01265 }
01266 }
01267
01268 llassert (fd != NULL);
01269
01270 if (fd->kind != TEXPR_FCN)
01271 {
01272 llfatalbug (message ("getParamNo: not a function: %q (%d)",
01273 typeExpr_unparse (fd), (int) fd->kind));
01274 }
01275
01276 params = fd->content.function.args;
01277
01278 if (paramNodeList_empty (params))
01279 {
01280 return -1;
01281 }
01282 else
01283 {
01284 int pno = 0;
01285
01286 paramNodeList_elements (params, i)
01287 {
01288 if (i->paramdecl != (typeExpr) 0)
01289 {
01290 if (cstring_equal (s, getVarName (i->paramdecl)))
01291 {
01292 return pno;
01293 }
01294 }
01295 pno++;
01296 } end_paramNodeList_elements;
01297 return -1;
01298 }
01299 }
01300
01301 static termNode
01302 getLetDecl (cstring s, fcnNode f)
01303 {
01304 letDeclNodeList x = f->lets;
01305
01306 letDeclNodeList_elements (x, i)
01307 {
01308 if (cstring_equal (s, ltoken_getRawString (i->varid)))
01309 {
01310 if (i->sortspec != NULL)
01311 {
01312 llbuglit ("getLetDecl: cannot return sort!");
01313 }
01314 else
01315 {
01316 return i->term;
01317 }
01318 }
01319 } end_letDeclNodeList_elements;
01320
01321 return (termNode) 0;
01322 }
01323
01324
01325
01326
01327
01328 static sRef
01329 processTermNode ( opFormNode op, termNodeList args,
01330 fcnNode f, uentryList cl)
01331 {
01332 if (op != (opFormNode) 0)
01333 {
01334 switch (op->kind)
01335 {
01336 case OPF_IF:
01337 llcontbuglit ("processTermNode: OPF_IF: not handled");
01338 break;
01339 case OPF_ANYOP:
01340 llcontbuglit ("processTermNode: OPF_ANYOP: not handled");
01341 break;
01342 case OPF_MANYOP:
01343 {
01344 int size = termNodeList_size (args);
01345
01346 if (size == 1
01347 && (cstring_equalLit (ltoken_getRawString (op->content.anyop), "'") ||
01348 cstring_equalLit (ltoken_getRawString (op->content.anyop), "^")))
01349 {
01350 return (fixTermNode (termNodeList_head (args), f, cl));
01351 }
01352 else
01353 {
01354 ;
01355 }
01356 break;
01357 }
01358 case OPF_ANYOPM:
01359 {
01360 int size = termNodeList_size (args);
01361
01362 if (size == 1
01363 && (cstring_equalLit (ltoken_getRawString (op->content.anyop), "*")))
01364 {
01365 sRef ft;
01366 sRef res;
01367
01368 ft = fixTermNode (termNodeList_head (args), f, cl);
01369 res = sRef_buildPointer (ft);
01370 return (res);
01371 }
01372 else
01373 {
01374 ;
01375 }
01376 break;
01377 }
01378 case OPF_MANYOPM:
01379 llcontbuglit ("OPF_MANYOPM: not handled\n");
01380 break;
01381 case OPF_MIDDLE:
01382 llcontbuglit ("OPF_MIDDLE: not handled\n");
01383 break;
01384 case OPF_MMIDDLE:
01385 llcontbuglit ("OPF_MMIDDLE: not handled\n");
01386 break;
01387 case OPF_MIDDLEM:
01388 llcontbuglit ("OPF_MIDDLEM: not handled\n");
01389 break;
01390 case OPF_MMIDDLEM:
01391 llcontbuglit ("OPF_MMIDDLEM: not handled\n");
01392 break;
01393 case OPF_BMIDDLE:
01394 if (op->content.middle == 1)
01395 llbug (message ("array fetch: [%q]",
01396 termNodeList_unparse (args)));
01397 else
01398 llcontbuglit ("OPF_BMIDDLE: bad\n");
01399 break;
01400
01401 case OPF_BMMIDDLE:
01402 if (op->content.middle <= 1)
01403 {
01404 sRef arr = fixTermNode (termNodeList_head (args), f, cl);
01405 sRef ret;
01406
01407 if (op->content.middle == 1)
01408 {
01409 termNode t = (termNodeList_reset (args),
01410 termNodeList_advance (args),
01411 termNodeList_current (args));
01412
01413 if (t->kind == TRM_LITERAL)
01414 {
01415 int i;
01416
01417 if (sscanf
01418 (cstring_toCharsSafe
01419 (ltoken_getRawString (t->literal)),
01420 "%d", &i) == 1)
01421 {
01422 ret = sRef_buildArrayFetchKnown (arr, i);
01423 }
01424 else
01425 {
01426 ret = sRef_buildArrayFetch (arr);
01427 }
01428
01429 return (ret);
01430 }
01431 }
01432
01433
01434
01435 ret = sRef_buildArrayFetch (arr);
01436
01437 return (ret);
01438 }
01439 else
01440 {
01441 llcontbug (message ("op->content.middle = %d",
01442 op->content.middle));
01443 break;
01444 }
01445
01446 case OPF_BMIDDLEM:
01447 llcontbuglit ("OPF_BMIDDLEM not handled");
01448 break;
01449
01450 case OPF_BMMIDDLEM:
01451 llcontbuglit ("OPF_BMMIDDLEM not handled");
01452 break;
01453
01454 case OPF_SELECT:
01455 llcontbug (message ("select: .%s",
01456 ltoken_getRawString (op->content.id)));
01457 break;
01458
01459 case OPF_MAP:
01460 llcontbug (message ("map: .%s",
01461 ltoken_getRawString (op->content.id)));
01462 break;
01463
01464 case OPF_MSELECT:
01465 {
01466 sRef rec = fixTermNode (termNodeList_head (args), f, cl);
01467 sRef ret;
01468 ctype ct = ctype_realType (sRef_deriveType (rec, cl));
01469 cstring fieldname = ltoken_getRawString (op->content.id);
01470
01471 ct = ctype_realType (ct);
01472
01473
01474
01475
01476
01477
01478
01479
01480 if (ctype_isStructorUnion (ct) &&
01481 uentry_isValid
01482 (uentryList_lookupField (ctype_getFields (ct), fieldname)))
01483 {
01484 cstring fname = cstring_copy (fieldname);
01485
01486 ret = sRef_buildField (rec, fname);
01487 cstring_markOwned (fname);
01488 }
01489 else
01490 {
01491 ret = sRef_undefined;
01492 }
01493
01494 return ret;
01495 }
01496 case OPF_MMAP:
01497 {
01498 sRef rec = fixTermNode (termNodeList_head (args), f, cl);
01499 sRef ret = sRef_undefined;
01500 ctype ct = ctype_realType (sRef_deriveType (rec, cl));
01501 cstring fieldname = ltoken_getRawString (op->content.id);
01502
01503
01504
01505
01506
01507 if (ctype_isPointer (ct))
01508 {
01509 ctype ctb = ctype_realType (ctype_baseArrayPtr (ct));
01510
01511 if (ctype_isStructorUnion (ctb) &&
01512 uentry_isValid (uentryList_lookupField
01513 (ctype_getFields (ctb), fieldname)))
01514 {
01515 cstring fname = cstring_copy (fieldname);
01516
01517 ret = sRef_buildArrow (rec, fname);
01518 cstring_markOwned (fname);
01519 }
01520 }
01521
01522 return ret;
01523 }
01524 }
01525 }
01526
01527 return sRef_undefined;
01528 }
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540 static sRef fixTermNode (termNode n, fcnNode f, uentryList cl)
01541 {
01542 if (n != (termNode) 0)
01543 {
01544 switch (n->kind)
01545 {
01546 case TRM_LITERAL:
01547 break;
01548 case TRM_CONST:
01549 case TRM_VAR:
01550 case TRM_ZEROARY:
01551 {
01552 cstring s = ltoken_getRawString (n->literal);
01553 termNode tl = getLetDecl (s, f);
01554
01555 if (tl != (termNode) 0)
01556 {
01557 return (fixTermNode (tl, f, cl));
01558 }
01559 else
01560 {
01561 int i = getParamNo (s, f);
01562
01563 if (i < 0)
01564 {
01565 usymId usym = usymtab_getId (s);
01566
01567 if (usymId_isInvalid (usym))
01568 {
01569 if (usymtab_existsEither (s))
01570 {
01571 return sRef_makeSpecState ();
01572 }
01573 else
01574 {
01575 llcontbuglit ("Invalid symbol in modifies list");
01576 return sRef_undefined;
01577 }
01578 }
01579 else
01580 return (sRef_makeGlobal (usym, ctype_unknown));
01581 }
01582
01583 else
01584 {
01585 sRef p = sRef_makeParam (i, ctype_unknown);
01586
01587 return (p);
01588 }
01589 }
01590 }
01591 case TRM_APPLICATION:
01592 {
01593 nameNode nn = n->name;
01594
01595 if (nn != (nameNode) 0)
01596 {
01597 if (nn->isOpId)
01598 {
01599
01600
01601 llfatalbug
01602 (message ("fixTermNode: expect non-empty nameNode: "
01603 "TRM_APPLICATION: %q",
01604 nameNode_unparse (nn)));
01605 }
01606 else
01607 {
01608 sRef sr;
01609
01610 sr = processTermNode (nn->content.opform, n->args, f, cl);
01611 return (sr);
01612 }
01613 }
01614
01615 return sRef_undefined;
01616 }
01617 case TRM_UNCHANGEDALL:
01618 case TRM_UNCHANGEDOTHERS:
01619 case TRM_SIZEOF:
01620 case TRM_QUANTIFIER:
01621 return sRef_undefined;
01622 }
01623 }
01624
01625 return sRef_undefined;
01626 }
01627
01628 static
01629 sRefSet fixModifies (fcnNode f, uentryList cl)
01630 {
01631 static bool shownWarning = FALSE;
01632 modifyNode m = f->modify;
01633 sRefSet sl = sRefSet_new ();
01634
01635 if (m != (modifyNode) 0)
01636 {
01637 if (m->hasStoreRefList)
01638 {
01639 storeRefNodeList srefs = m->list;
01640
01641 storeRefNodeList_elements (srefs, i)
01642 {
01643 if (storeRefNode_isObj (i) || storeRefNode_isType (i))
01644 {
01645 if (!shownWarning)
01646 {
01647 fileloc loc = fileloc_fromTok (f->name);
01648
01649 llmsg (message
01650 ("%q: Warning: object and type modifications "
01651 "not understood by LCLint",
01652 fileloc_unparse (loc)));
01653 fileloc_free (loc);
01654 shownWarning = TRUE;
01655 }
01656 }
01657 else if (storeRefNode_isSpecial (i))
01658 {
01659 sl = sRefSet_insert (sl, i->content.ref);
01660 }
01661 else if (storeRefNode_isTerm (i))
01662 {
01663 sRef s = fixTermNode (i->content.term, f, cl);
01664
01665 if (sRef_isKnown (s))
01666 {
01667 sl = sRefSet_insert (sl, s);
01668 }
01669 }
01670 else
01671 {
01672 BADEXIT;
01673 }
01674 } end_storeRefNodeList_elements;
01675
01676 }
01677 }
01678
01679 return sl;
01680 }
01681
01682 static cstring
01683 paramNode_name (paramNode x)
01684 {
01685 return (typeExpr_name (x->paramdecl));
01686 }
01687
01688 static uentry
01689 paramNode_toUentry (paramNode p)
01690 {
01691 if (p != (paramNode) 0)
01692 {
01693 if (p->kind == PELIPSIS)
01694 {
01695 return uentry_makeElipsisMarker ();
01696 }
01697 else
01698 {
01699 qtype ct = convertLclTypeSpecNode (p->type);
01700 ctype cr = convertTypeExpr (qtype_getType (ct), p->paramdecl);
01701 cstring pname = (p->paramdecl == (typeExpr)0) ? cstring_undefined
01702 : paramNode_name (p);
01703 uentry ue = uentry_makeVariableParam (pname, cr);
01704
01705 uentry_reflectQualifiers (ue, qtype_getQuals (ct));
01706 qtype_free (ct);
01707 return (ue);
01708 }
01709 }
01710 else
01711 {
01712 llcontbuglit ("paramNode_toUentry: NULL");
01713 return uentry_undefined;
01714 }
01715 BADEXIT;
01716 }
01717
01718 static uentryList
01719 paramNodeList_toUentryList (paramNodeList p)
01720 {
01721 uentryList cl = uentryList_new ();
01722
01723 if (paramNodeList_isNull (p)) return (cl);
01724
01725 paramNodeList_elements (p, current)
01726 {
01727 cl = uentryList_add (cl, paramNode_toUentry (current));
01728 } end_paramNodeList_elements;
01729
01730 return cl;
01731 }
01732
01733