+ DPRINTF (("Reflect after clause: %s / %s",
+ stateClause_unparse (cl),
+ sRefSet_unparse (srs)));
+
+ sRefSet_elements (srs, sel)
+ {
+ sRef s;
+
+ DPRINTF (("elements: %s", sRef_unparse (sel)));
+ DPRINTF (("elements: %s", sRef_unparseFull (sel)));
+
+ if (sRef_isResult (sRef_getRootBase (sel)))
+ {
+ DPRINTF (("Fix base: %s / %s",
+ sRef_unparse (sel), sRef_unparse (exprNode_getSref (ret))));
+ s = sRef_fixBase (sel, exprNode_getSref (ret));
+ DPRINTF (("==> %s", sRef_unparseFull (s)));
+ }
+ else
+ {
+ s = sRef_fixBaseParam (sel, args);
+ }
+
+ DPRINTF (("elements: %s", sRef_unparse (s)));
+ DPRINTF (("elements: %s", sRef_unparseFull (s)));
+
+ DPRINTF (("Reflecting state clause on: %s / %s",
+ sRef_unparseFull (sel), sRef_unparseFull (s)));
+
+ /* evans 2001-08-24 - added aliasSetCompleteParam */
+ sRef_aliasSetCompleteParam (modf, s, eparam, exprNode_loc (f));
+
+ DPRINTF (("After reflecting state clause on: %s / %s",
+ sRef_unparseFull (sel), sRef_unparseFull (s)));
+ } end_sRefSet_elements;
+ }
+ }
+ } end_stateClauseList_elements ;
+ }
+
+ DPRINTF (("Here: %s / %s",
+ uentry_unparseFull (le),
+ bool_unparse (uentry_hasMetaStateEnsures (le))));
+
+ if (uentry_hasMetaStateEnsures (le))
+ {
+ fileloc loc = exprNode_loc (f);
+
+ metaStateConstraintList mscl = uentry_getMetaStateEnsures (le);
+
+ metaStateConstraintList_elements (mscl, msc)
+ {
+ metaStateSpecifier msspec = metaStateConstraint_getSpecifier (msc);
+ metaStateInfo msinfo = metaStateSpecifier_getMetaStateInfo (msspec);
+ metaStateExpression msexpr = metaStateConstraint_getExpression (msc);
+ cstring key = metaStateInfo_getName (msinfo);
+ sRef mlsr = metaStateSpecifier_getSref (msspec);
+ sRef s;
+ sRef lastref = sRef_undefined;
+ stateValue sval = stateValue_undefined;
+
+ DPRINTF (("Meta state constraint for %s: %s", uentry_unparse (le),
+ metaStateConstraint_unparse (msc)));
+ DPRINTF (("Matches left: %s", sRef_unparseDebug (mlsr)));
+
+ if (sRef_isResult (sRef_getRootBase (mlsr)))
+ {
+ s = exprNode_getSref (ret);
+ }
+ else
+ {
+ s = sRef_fixBaseParam (mlsr, args);
+ }
+
+ DPRINTF (("Setting state: %s", sRef_unparseFull (s)));
+
+ while (metaStateExpression_isDefined (msexpr))
+ {
+ metaStateSpecifier ms = metaStateExpression_getSpecifier (msexpr);
+ metaStateInfo msi = metaStateSpecifier_getMetaStateInfo (ms);
+ sRef msr, fs;
+
+ DPRINTF (("Check expression: %s", metaStateExpression_unparse (msexpr)));
+
+ if (metaStateExpression_isMerge (msexpr))
+ {
+ msexpr = metaStateExpression_getRest (msexpr);
+ }
+ else
+ {
+ msexpr = metaStateExpression_undefined;
+ }
+
+ if (metaStateInfo_isDefined (msi))
+ {
+ /* Must match lhs state */
+ llassert (metaStateInfo_equal (msinfo, msi));
+ }
+
+ if (metaStateSpecifier_isElipsis (ms))
+ {
+ /*
+ ** For elipsis, we need to merge all the relevant elipsis parameters
+ **
+ */
+
+ uentryList params = uentry_getParams (le);
+ int paramno = uentryList_size (params) - 1;
+
+ if (!uentry_isElipsisMarker (uentryList_getN (params, paramno)))
+ {
+ voptgenerror
+ (FLG_TYPE,
+ message ("Ensures clauses uses ... for function without ... in parameter list: %q",
+ uentry_getName (le)),
+ uentry_whereLast (le));
+ /*@innerbreak@*/ break;
+ }
+
+ while (paramno < exprNodeList_size (args))
+ {
+ exprNode arg = exprNodeList_getN (args, paramno);
+ fs = exprNode_getSref (arg);
+ DPRINTF (("Merge arg: %s", exprNode_unparse (arg)));
+
+ /* cut and pasted... gack*/
+ if (stateValue_isDefined (sval))
+ {
+ /* Use combination table to merge old state value with new one: */
+ stateValue tval = sRef_getMetaStateValue (fs, key);
+
+ if (stateValue_isDefined (tval))
+ {
+ stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
+ cstring msg = cstring_undefined;
+ int nval = stateCombinationTable_lookup (sctable,
+ stateValue_getValue (sval),
+ stateValue_getValue (tval),
+ &msg);
+ DPRINTF (("Combining: %s + %s -> %d",
+ stateValue_unparseValue (sval, msinfo),
+ stateValue_unparseValue (tval, msinfo),
+ nval));
+
+ if (nval == stateValue_error)
+ {
+ if (optgenerror
+ (FLG_STATEMERGE,
+ message
+ ("Attributes merged in ensures clause in states that "
+ "cannot be combined (%q is %q, %q is %q)%q",
+ sRef_unparse (lastref),
+ stateValue_unparseValue (sval, msinfo),
+ sRef_unparse (fs),
+ stateValue_unparseValue (tval, msinfo),
+ cstring_isDefined (msg) ?
+ message (": %s", msg) : cstring_undefined),
+ exprNode_loc (f)))
+ {
+ sRef_showMetaStateInfo (fs, key);
+ }
+ }
+
+ stateValue_updateValueLoc (sval, nval, fileloc_undefined);
+ loc = exprNode_loc (arg);
+ }
+ else
+ {
+ DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
+ }
+ }
+ else
+ {
+ sval = sRef_getMetaStateValue (fs, key);
+ }
+
+ lastref = fs;
+
+ if (stateValue_isError (sval))
+ {
+ /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
+ }
+
+
+ paramno++;
+ }
+ }
+ else
+ {
+ msr = metaStateSpecifier_getSref (ms);
+
+
+ llassert (sRef_isParam (sRef_getRootBase (msr)));
+ fs = sRef_fixBaseParam (msr, args);
+
+ if (stateValue_isDefined (sval))
+ {
+ /* Use combination table to merge old state value with new one: */
+ stateValue tval = sRef_getMetaStateValue (fs, key);
+
+ if (stateValue_isDefined (tval))
+ {
+ stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
+ cstring msg = cstring_undefined;
+ int nval = stateCombinationTable_lookup (sctable,
+ stateValue_getValue (sval),
+ stateValue_getValue (tval),
+ &msg);
+ DPRINTF (("Combining: %s + %s -> %d",
+ stateValue_unparseValue (sval, msinfo),
+ stateValue_unparseValue (tval, msinfo),
+ nval));
+
+ if (nval == stateValue_error)
+ {
+ if (optgenerror
+ (FLG_STATEMERGE,
+ message
+ ("Attributes merged in ensures clause in states that "
+ "cannot be combined (%q is %q, %q is %q)%q",
+ sRef_unparse (lastref),
+ stateValue_unparseValue (sval, msinfo),
+ sRef_unparse (fs),
+ stateValue_unparseValue (tval, msinfo),
+ cstring_isDefined (msg)
+ ? message (": %s", msg) : cstring_undefined),
+ exprNode_loc (f)))
+ {
+ sRef_showMetaStateInfo (fs, key);
+ }
+ }
+
+ stateValue_updateValueLoc (sval, nval, fileloc_undefined);
+ }
+ else
+ {
+ DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
+ }
+ }
+ else
+ {
+ sval = sRef_getMetaStateValue (fs, key);
+ }
+
+ lastref = fs;
+
+ if (stateValue_isError (sval))
+ {
+ /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
+ }
+ }
+ }
+
+ DPRINTF (("Setting: %s:%s <- %s", sRef_unparse (s), key, stateValue_unparse (sval)));
+
+ if (stateValue_isDefined (sval))
+ {
+ sRef_setMetaStateValueComplete (s, key, stateValue_getValue (sval), loc);
+ }
+ else
+ {
+ DPRINTF (("Undefined state: %s", cstring_toCharsSafe (sRef_unparse (s))));
+ }
+ } end_metaStateConstraintList_elements ;
+
+ metaStateConstraintList_free (mscl);
+ }
+ }
+}
+
+static void
+checkRequiresClause (uentry le, exprNode f, exprNodeList args)
+{
+ DPRINTF (("Check requires clause: %s(%s) / %s / %s",
+ exprNode_unparse (f), exprNodeList_unparse (args),
+ uentry_unparseFull (le),
+ stateClauseList_unparse (uentry_getStateClauseList (le))));
+
+ if (uentry_isValid (le) && uentry_isFunction (le))
+ {
+ stateClauseList sclauses = uentry_getStateClauseList (le);
+
+ if (stateClauseList_isDefined (sclauses))
+ {
+ DPRINTF (("Check requires: %s / %s / %s",
+ uentry_unparse (le),
+ exprNode_unparse (f), exprNodeList_unparse (args)));
+
+ stateClauseList_elements (sclauses, cl)
+ {
+ DPRINTF (("Check clause: %s / %s",
+ stateClause_unparse (cl),
+ bool_unparse (stateClause_hasRequires (cl))));
+
+ if (stateClause_hasRequires (cl))
+ {
+ sRefSet osrs = sRefSet_undefined;
+ sRefSet srs;
+
+ if (stateClause_isGlobal (cl))
+ {
+ srs = sRefSet_single (usymtab_lookupGlobalMarker ());
+ osrs = srs;
+ }
+ else
+ {
+ srs = stateClause_getRefs (cl);
+ }
+
+ DPRINTF (("Refs: %s", sRefSet_unparse (srs)));
+
+ if (stateClause_setsMetaState (cl))
+ {
+ qual q = stateClause_getMetaQual (cl);
+ annotationInfo ainfo = qual_getAnnotationInfo (q);
+ metaStateInfo minfo = annotationInfo_getState (ainfo);
+ cstring key = metaStateInfo_getName (minfo);
+ int mvalue = annotationInfo_getValue (ainfo);
+
+ DPRINTF (("Requires meta state! %s = %d", key, mvalue));
+
+ sRefSet_elements (srs, sel)
+ {
+ sRef s = sRef_fixBaseParam (sel, args);
+
+ if (sRef_isResult (sRef_getRootBase (sel)))
+ {
+ BADBRANCH;
+ }
+ else
+ {
+ DPRINTF (("Checking state clause on: %s / %s / %s = %d",
+ sRef_unparseFull (sel), sRef_unparseFull (s),
+ key, mvalue));
+
+ if (!sRef_checkMetaStateValue (s, key, mvalue))
+ {
+ DPRINTF (("HERE: %s", sRef_unparse (s)));
+ if (optgenerror
+ (FLG_STATETRANSFER,
+ message
+ ("Requires clause of called function %q not satisfied%q (state is %q): %q",
+ uentry_getName (le),
+ sRef_isGlobalMarker (s)
+ ? message ("")
+ : message (" by %q", sRef_unparse (s)),
+ stateValue_unparseValue (sRef_getMetaStateValue (s, key),
+ minfo),
+ stateClause_unparse (cl)),
+ exprNode_loc (f)))
+ {
+ sRef_showAliasInfo (s);
+ }
+ else
+ {
+ DPRINTF (("Error supressed!"));
+ DPRINTF (("Loc: %s", fileloc_unparse (exprNode_loc (f))));
+ DPRINTF (("Context supress: %s",
+ bool_unparse (context_suppressFlagMsg (FLG_STATETRANSFER, exprNode_loc (f)))));
+ }
+ }
+ }
+ } end_sRefSet_elements;
+ }
+ else
+ {
+ sRefModVal modf = stateClause_getRequiresBodyFunction (cl);
+ int eparam = stateClause_getStateParameter (cl);
+
+ DPRINTF (("Reflect after clause: %s / %s",
+ stateClause_unparse (cl),
+ sRefSet_unparse (srs)));
+
+ llassert (modf != NULL);
+
+ sRefSet_elements (srs, sel)
+ {
+ sRef s;
+
+ DPRINTF (("elements: %s", sRef_unparse (sel)));
+ DPRINTF (("elements: %s", sRef_unparseFull (sel)));
+
+ s = sRef_fixBaseParam (sel, args);
+
+ DPRINTF (("elements: %s", sRef_unparse (s)));
+ DPRINTF (("elements: %s", sRef_unparseFull (s)));
+
+ if (sRef_isResult (sRef_getRootBase (sel)))
+ {
+ ; /* what do we do about results? */
+ }
+ else
+ {
+ DPRINTF (("Reflecting state clause on: %s / %s",
+ sRef_unparse (sel), sRef_unparse (s)));
+
+ modf (s, eparam, exprNode_loc (f));
+ }
+ } end_sRefSet_elements;
+ }
+
+ sRefSet_free (osrs);
+ }
+ } end_stateClauseList_elements ;
+ }
+ }
+}
+
+static /*@only@*/ exprNode
+functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f,
+ ctype t, /*@keep@*/ exprNodeList args)
+{
+ /* requires f is a non-error exprNode, with type function */
+ cstring fname = exprNode_unparse (f);
+ uentry le = exprNode_getUentry (f);
+ exprNode ret = exprNode_createPartialCopy (f);
+ int special;
+
+ setCodePoint ();
+
+ DPRINTF (("Call: %s %s",exprNode_unparse (f), exprNodeList_unparse (args)));
+
+ ret->typ = ctype_getReturnType (t);
+ ret->kind = XPR_CALL;
+
+ ret->edata = exprData_makeCall (f, args);
+
+ /*
+ ** Order of these steps is very important!
+ **
+ ** Must check for argument dependencies before messing up uses and sets.
+ */
+
+ if (context_getFlag (FLG_EVALORDER))
+ {
+ exprNodeList_elements (args, current)
+ {
+ if (exprNode_isDefined (current))
+ {
+ exprNode_addUse (current, current->sref);
+ }
+ } end_exprNodeList_elements;
+
+ if (context_maybeSet (FLG_EVALORDER) || context_maybeSet (FLG_EVALORDERUNCON))
+ {
+ checkSequencing (f, args);
+ }
+
+ exprNodeList_elements (args, current)
+ {
+ if (exprNode_isDefined (current) && sRef_isMeaningful (current->sref))
+ {
+ exprNode_addUse (ret, sRef_makeDerived (current->sref));
+ }
+ } end_exprNodeList_elements ;
+ }
+
+ special = checkArgs (le, f, t, args, ret);
+ checkGlobMods (f, le, args, ret, special);
+ checkRequiresClause (le, f, args);
+ setCodePoint ();
+
+ if (uentry_isValid (le)
+ && (uentry_isFunction (le)
+ || (uentry_isVariable (le)
+ && ctype_isFunction (uentry_getType (le)))))
+ {
+ exitkind exk = uentry_getExitCode (le);
+
+ /* f->typ is already set to the return type */
+
+ DPRINTF (("Function: %s", uentry_unparseFull (le)));
+ ret->sref = uentry_returnedRef (le, args, exprNode_loc (f));
+ DPRINTF (("Returned: %s / %s",
+ uentry_unparseFull (le),
+ sRef_unparseFull (ret->sref)));
+