Skip to content

Commit d6435e2

Browse files
committed
- Added check for unused input variables in external functions
- Also added a disabled implementation for regular functions, which has some quirks left to solve (and lots of problems to fix in the compiler sources) git-svn-id: https://openmodelica.org/svn/OpenModelica/trunk@9506 f25d12d1-65f4-0310-ae8a-bbce733d8d8e
1 parent ef519b7 commit d6435e2

File tree

9 files changed

+218
-87
lines changed

9 files changed

+218
-87
lines changed

Compiler/FrontEnd/DAEUtil.mo

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5605,4 +5605,11 @@ algorithm
56055605
outAttributes := DAE.ATTR(fp, sp, var, dir, io);
56065606
end translateSCodeAttrToDAEAttr;
56075607

5608+
public function varName
5609+
input DAE.Element var;
5610+
output String name;
5611+
algorithm
5612+
DAE.VAR(componentRef=DAE.CREF_IDENT(ident=name)) := var;
5613+
end varName;
5614+
56085615
end DAEUtil;

Compiler/FrontEnd/Expression.mo

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3773,7 +3773,7 @@ algorithm
37733773
list<DAE.Exp> expl_1,expl;
37743774
Absyn.Path fn,path;
37753775
Boolean t,scalar,built;
3776-
Type tp;
3776+
Type tp,et;
37773777
Integer i;
37783778
String id,str;
37793779
list<String> fieldNames;
@@ -3786,6 +3786,9 @@ algorithm
37863786
DAE.ReductionInfo reductionInfo;
37873787
DAE.ReductionIterators riters;
37883788
DAE.CallAttributes attr;
3789+
list<DAE.Element> localDecls;
3790+
DAE.MatchType matchType;
3791+
list<DAE.MatchCase> cases;
37893792

37903793
case (e as DAE.ICONST(_),rel,ext_arg) then ((e,ext_arg));
37913794
case (e as DAE.RCONST(_),rel,ext_arg) then ((e,ext_arg));
@@ -3945,7 +3948,14 @@ algorithm
39453948
case ((e as DAE.META_OPTION(oe1)),rel,ext_arg)
39463949
equation
39473950
((oe1,ext_arg)) = traverseExpOptTopDown(oe1, rel, ext_arg);
3948-
then ((e,ext_arg));
3951+
then ((DAE.META_OPTION(oe1),ext_arg));
3952+
3953+
case ((e as DAE.MATCHEXPRESSION(matchType,expl,localDecls,cases,et)),rel,ext_arg)
3954+
equation
3955+
((expl,ext_arg)) = traverseExpListTopDown(expl,rel,ext_arg);
3956+
// TODO: Traverse cases
3957+
then
3958+
((DAE.MATCHEXPRESSION(matchType,expl,localDecls,cases,et),ext_arg));
39493959

39503960
case ((e as DAE.METARECORDCALL(fn,expl,fieldNames,i)),rel,ext_arg)
39513961
equation
@@ -4057,11 +4067,13 @@ public function traverseExpListTopDown
40574067
algorithm
40584068
outTpl := match(expl,rel,ext_arg)
40594069
local DAE.Exp e,e1; list<DAE.Exp> expl1;
4060-
case({},_,ext_arg) then (({},ext_arg));
4061-
case(e::expl,rel,ext_arg) equation
4062-
((e1,ext_arg)) = traverseExpTopDown(e, rel, ext_arg);
4063-
((expl1,ext_arg)) = traverseExpListTopDown(expl,rel,ext_arg);
4064-
then ((e1::expl1,ext_arg));
4070+
case({},_,ext_arg)
4071+
then (({},ext_arg));
4072+
case(e::expl,rel,ext_arg)
4073+
equation
4074+
((e1,ext_arg)) = traverseExpTopDown(e, rel, ext_arg);
4075+
((expl1,ext_arg)) = traverseExpListTopDown(expl,rel,ext_arg);
4076+
then ((e1::expl1,ext_arg));
40654077
end match;
40664078
end traverseExpListTopDown;
40674079

@@ -4158,7 +4170,7 @@ algorithm
41584170
then
41594171
((e, true));
41604172

4161-
case(inExp) then inExp;
4173+
case (inExp) then inExp;
41624174

41634175
end matchcontinue;
41644176
end traversingComponentRefPresent;
@@ -4220,13 +4232,13 @@ algorithm
42204232
ComponentRef cr,cr1;
42214233
DAE.Exp e;
42224234

4223-
case((e as DAE.CREF(componentRef = cr1), (cr,false)))
4235+
case ((e as DAE.CREF(componentRef = cr1), (cr,false)))
42244236
equation
42254237
b = ComponentReference.crefEqualNoStringCompare(cr,cr1);
42264238
then
42274239
((e,not b,(cr,b)));
42284240

4229-
case(((e,(cr,b)))) then ((e,not b,(cr,b)));
4241+
case (((e,(cr,b)))) then ((e,not b,(cr,b)));
42304242

42314243
end matchcontinue;
42324244
end traversingexpHasCref;

Compiler/FrontEnd/Inst.mo

Lines changed: 148 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10630,7 +10630,7 @@ algorithm
1063010630
case (cache,env,ih,mod,pre,csets,(c as SCode.CLASS(name = n,restriction = SCode.R_RECORD())),inst_dims)
1063110631
equation
1063210632
(cache,c,cenv) = Lookup.lookupRecordConstructorClass(cache,env,Absyn.IDENT(n));
10633-
(cache,env,ih,{DAE.FUNCTION(fpath,_,ty1,false,_,source,_)}) = implicitFunctionInstantiation2(cache,cenv,ih,mod,pre,csets,c,inst_dims);
10633+
(cache,env,ih,{DAE.FUNCTION(fpath,_,ty1,false,_,source,_)}) = implicitFunctionInstantiation2(cache,cenv,ih,mod,pre,csets,c,inst_dims,true);
1063410634
fun = DAE.RECORD_CONSTRUCTOR(fpath,ty1,source);
1063510635
cache = Env.addDaeFunction(cache, {fun});
1063610636
then (cache,env,ih);
@@ -10639,7 +10639,7 @@ algorithm
1063910639
equation
1064010640
failure(SCode.R_RECORD() = r);
1064110641
true = MetaUtil.strictRMLCheck(RTOpts.debugFlag("rml"),c);
10642-
(cache,env,ih,funs) = implicitFunctionInstantiation2(cache,env,ih,mod,pre,csets,c,inst_dims);
10642+
(cache,env,ih,funs) = implicitFunctionInstantiation2(cache,env,ih,mod,pre,csets,c,inst_dims,false);
1064310643
cache = Env.addDaeFunction(cache, funs);
1064410644
then (cache,env,ih);
1064510645

@@ -10666,12 +10666,13 @@ protected function implicitFunctionInstantiation2
1066610666
input Connect.Sets inSets;
1066710667
input SCode.Element inClass;
1066810668
input InstDims inInstDims;
10669+
input Boolean instFunctionTypeOnly "if true, do no additional checking of the function";
1066910670
output Env.Cache outCache;
1067010671
output Env.Env outEnv;
1067110672
output InstanceHierarchy outIH;
1067210673
output list<DAE.Function> funcs;
1067310674
algorithm
10674-
(outCache,outEnv,outIH,funcs):= matchcontinue (inCache,inEnv,inIH,inMod,inPrefix,inSets,inClass,inInstDims)
10675+
(outCache,outEnv,outIH,funcs):= matchcontinue (inCache,inEnv,inIH,inMod,inPrefix,inSets,inClass,inInstDims,instFunctionTypeOnly)
1067510676
local
1067610677
Connect.Sets csets_1,csets;
1067710678
DAE.Type ty,ty1;
@@ -10704,7 +10705,7 @@ algorithm
1070410705
Option<SCode.Comment> cmt;
1070510706

1070610707
/* normal functions */
10707-
case (cache,env,ih,mod,pre,csets,(c as SCode.CLASS(classDef=cd,partialPrefix = partialPrefix, name = n,restriction = SCode.R_FUNCTION(),info = info)),inst_dims)
10708+
case (cache,env,ih,mod,pre,csets,(c as SCode.CLASS(classDef=cd,partialPrefix = partialPrefix, name = n,restriction = SCode.R_FUNCTION(),info = info)),inst_dims,instFunctionTypeOnly)
1070810709
equation
1070910710
(cache,cenv,ih,_,DAE.DAE(daeElts),csets_1,ty,st,_,_) =
1071010711
instClass(cache, env, ih, UnitAbsynBuilder.emptyInstStore(), mod, pre, csets, c, inst_dims, true, INNER_CALL(), ConnectionGraph.EMPTY);
@@ -10726,12 +10727,14 @@ algorithm
1072610727

1072710728
daeElts = optimizeFunction(fpath,daeElts,NONE(),{},{},{});
1072810729
cmt = extractClassDefComment(cache, env, cd);
10730+
/* Not working 100% yet... Also, a lot of code has unused inputs :( */
10731+
Debug.bcall3(false and RTOpts.acceptMetaModelicaGrammar() and not instFunctionTypeOnly,checkFunctionInputUsed,daeElts,NONE(),Absyn.pathString(fpath));
1072910732
then
1073010733
(cache,env_1,ih,{DAE.FUNCTION(fpath,DAE.FUNCTION_DEF(daeElts)::derFuncs,ty1,partialPrefixBool,inlineType,source,cmt)});
1073110734

1073210735
/* External functions should also have their type in env, but no dae. */
1073310736
case (cache,env,ih,mod,pre,csets,(c as SCode.CLASS(partialPrefix=partialPrefix,name = n,restriction = (restr as SCode.R_EXT_FUNCTION()),
10734-
classDef = cd as (parts as SCode.PARTS(elementLst = els)), info=info, encapsulatedPrefix = encapsulatedPrefix)),inst_dims)
10737+
classDef = cd as (parts as SCode.PARTS(elementLst = els)), info=info, encapsulatedPrefix = encapsulatedPrefix)),inst_dims,instFunctionTypeOnly)
1073510738
equation
1073610739
(cache,cenv,ih,_,DAE.DAE(daeElts),csets_1,ty,st,_,_) =
1073710740
instClass(cache,env,ih, UnitAbsynBuilder.emptyInstStore(),mod, pre,
@@ -10752,25 +10755,25 @@ algorithm
1075210755
instClassdef(cache, env_1, ih, UnitAbsyn.noStore, mod, pre, csets_1,
1075310756
ClassInf.FUNCTION(fpath), n,parts, restr, vis, partialPrefix, encapsulatedPrefix, inst_dims, true, INNER_CALL(), ConnectionGraph.EMPTY,NONE(),info) "how to get this? impl" ;
1075410757
(cache,ih,extdecl) = instExtDecl(cache, tempenv,ih, n, parts, true, pre,info) "impl" ;
10755-
checkExternalFunction(daeElts,extdecl,n);
1075610758

1075710759
// set the source of this element
1075810760
source = DAEUtil.createElementSource(info, Env.getEnvPath(env), PrefixUtil.prefixToCrefOpt(pre), NONE(), NONE());
1075910761
partialPrefixBool = SCode.partialBool(partialPrefix);
1076010762
cmt = extractClassDefComment(cache, env, cd);
10763+
checkExternalFunction(daeElts,extdecl,Absyn.pathString(fpath));
1076110764
then
1076210765
(cache,env_1,ih,{DAE.FUNCTION(fpath,DAE.FUNCTION_EXT(daeElts,extdecl)::derFuncs,ty1,partialPrefixBool,DAE.NO_INLINE(),source,cmt)});
1076310766

1076410767
/* Instantiate overloaded functions */
1076510768
case (cache,env,ih,mod,pre,csets,(c as SCode.CLASS(name = n,restriction = (restr as SCode.R_FUNCTION()),
10766-
classDef = SCode.OVERLOAD(pathLst = funcnames))),inst_dims)
10769+
classDef = SCode.OVERLOAD(pathLst = funcnames))),inst_dims,_)
1076710770
equation
1076810771
(cache,env_1,ih,resfns) = instOverloadedFunctions(cache,env,ih, n, funcnames) "Overloaded functions" ;
1076910772
then
1077010773
(cache,env_1,ih,resfns);
1077110774

1077210775
// handle failure
10773-
case (_,env,_,_,_,_,SCode.CLASS(name=n),_)
10776+
case (_,env,_,_,_,_,SCode.CLASS(name=n),_,_)
1077410777
equation
1077510778
true = RTOpts.debugFlag("failtrace");
1077610779
Debug.traceln("- Inst.implicitFunctionInstantiation2 failed " +& n);
@@ -10825,7 +10828,7 @@ algorithm
1082510828
(cache,p) = makeFullyQualified(cache,cenv,p);
1082610829
// add to cache before instantiating, to break recursion for recursive definitions.
1082710830
cache = Env.addCachedInstFuncGuard(cache,p);
10828-
(cache,_,ih,funcs) = implicitFunctionInstantiation2(cache,cenv,ih,DAE.NOMOD(),Prefix.NOPRE(), Connect.emptySet,cdef,{});
10831+
(cache,_,ih,funcs) = implicitFunctionInstantiation2(cache,cenv,ih,DAE.NOMOD(),Prefix.NOPRE(), Connect.emptySet,cdef,{},false);
1082910832

1083010833
funcs = addNameToDerivativeMapping(funcs,path);
1083110834
cache = Env.addDaeFunction(cache, funcs);
@@ -11398,7 +11401,7 @@ algorithm
1139811401
equation
1139911402
stripped_elts = Util.listMap(elts,stripFuncOutputsMod);
1140011403
stripped_class = SCode.CLASS(id,prefixes,e,p,r,SCode.PARTS(elts,{},{},{},{},extDecl,annotationLst,NONE()),info);
11401-
(cache,env_1,ih,funs) = implicitFunctionInstantiation2(cache,env,ih, DAE.NOMOD(), Prefix.NOPRE(), Connect.emptySet, stripped_class, {});
11404+
(cache,env_1,ih,funs) = implicitFunctionInstantiation2(cache,env,ih,DAE.NOMOD(), Prefix.NOPRE(), Connect.emptySet, stripped_class, {},true);
1140211405
/* Only external functions are valid without an algorithm section... */
1140311406
cache = Env.addDaeExtFunction(cache, funs);
1140411407
then
@@ -11579,8 +11582,132 @@ protected
1157911582
Integer i;
1158011583
algorithm
1158111584
Util.listMap02(els,checkExternalFunctionOutputAssigned,decl,name);
11585+
checkFunctionInputUsed(els,SOME(decl),name);
1158211586
end checkExternalFunction;
1158311587

11588+
protected function checkFunctionInputUsed
11589+
input list<DAE.Element> elts;
11590+
input Option<DAE.ExternalDecl> decl;
11591+
input String name;
11592+
protected
11593+
list<DAE.Element> invars,vars,algs;
11594+
algorithm
11595+
(vars,_,_,_,algs,_) := DAEUtil.splitElements(elts);
11596+
invars := Util.listFilter(vars,DAEUtil.isInputVar);
11597+
invars := checkExternalDeclInputUsed(invars,decl);
11598+
invars := Util.listSelect1(invars,vars,checkVarBindingsInputUsed);
11599+
(_,invars) := DAEUtil.traverseDAE2(algs,checkExpInputUsed,invars);
11600+
Util.listMap01(invars,name,warnUnusedFunctionVar);
11601+
end checkFunctionInputUsed;
11602+
11603+
protected function warnUnusedFunctionVar
11604+
input DAE.Element v;
11605+
input String name;
11606+
protected
11607+
DAE.ComponentRef cr;
11608+
DAE.ElementSource source;
11609+
String str;
11610+
algorithm
11611+
DAE.VAR(componentRef=cr,source=source) := v;
11612+
str := ComponentReference.printComponentRefStr(cr);
11613+
Error.addSourceMessage(Error.FUNCTION_UNUSED_INPUT,{str,name},DAEUtil.getElementSourceFileInfo(source));
11614+
end warnUnusedFunctionVar;
11615+
11616+
protected function checkExternalDeclInputUsed
11617+
input list<DAE.Element> names;
11618+
input Option<DAE.ExternalDecl> decl;
11619+
output list<DAE.Element> onames;
11620+
algorithm
11621+
onames := match (names,decl)
11622+
local
11623+
list<DAE.ExtArg> args;
11624+
DAE.ExtArg arg;
11625+
case (names,NONE()) then names;
11626+
case ({},_) then {};
11627+
case (names,SOME(DAE.EXTERNALDECL(returnArg=arg,args=args)))
11628+
equation
11629+
names = Util.listSelect1(names,arg::args,checkExternalDeclArgs);
11630+
then names;
11631+
end match;
11632+
end checkExternalDeclInputUsed;
11633+
11634+
protected function checkExpInputUsed
11635+
input tuple<DAE.Exp,list<DAE.Element>> tpl;
11636+
output tuple<DAE.Exp,list<DAE.Element>> otpl;
11637+
protected
11638+
DAE.Exp exp;
11639+
list<DAE.Element> els;
11640+
algorithm
11641+
(exp,els) := tpl;
11642+
otpl := Expression.traverseExp(exp,checkExpInputUsed2,els);
11643+
end checkExpInputUsed;
11644+
11645+
protected function checkExpInputUsed2
11646+
input tuple<DAE.Exp,list<DAE.Element>> tpl;
11647+
output tuple<DAE.Exp,list<DAE.Element>> otpl;
11648+
algorithm
11649+
otpl := matchcontinue tpl
11650+
local
11651+
DAE.Exp exp;
11652+
list<DAE.Element> els;
11653+
DAE.ComponentRef cr;
11654+
Absyn.Path path;
11655+
case ((exp as DAE.CREF(componentRef=cr),els))
11656+
equation
11657+
els = Util.listSelect1(els,cr,checkExpInputUsed3);
11658+
then ((exp,els));
11659+
case ((exp as DAE.CALL(path=path),els))
11660+
equation
11661+
true = RTOpts.acceptMetaModelicaGrammar();
11662+
cr = ComponentReference.pathToCref(path);
11663+
els = Util.listSelect1(els,cr,checkExpInputUsed3);
11664+
then ((exp,els));
11665+
else tpl;
11666+
end matchcontinue;
11667+
end checkExpInputUsed2;
11668+
11669+
protected function checkExpInputUsed3
11670+
input DAE.Element el;
11671+
input DAE.ComponentRef cr2;
11672+
output Boolean noteq;
11673+
protected
11674+
DAE.ComponentRef cr1;
11675+
algorithm
11676+
DAE.VAR(componentRef=cr1) := el;
11677+
noteq := not ComponentReference.crefEqualNoStringCompare(cr1,cr2);
11678+
end checkExpInputUsed3;
11679+
11680+
protected function checkVarBindingsInputUsed
11681+
input DAE.Element v;
11682+
input list<DAE.Element> els;
11683+
output Boolean notfound;
11684+
algorithm
11685+
notfound := not Util.listContainsWithCompareFunc(v,els,checkVarBindingInputUsed);
11686+
end checkVarBindingsInputUsed;
11687+
11688+
protected function checkVarBindingInputUsed
11689+
input DAE.Element v;
11690+
input DAE.Element el;
11691+
output Boolean found;
11692+
algorithm
11693+
found := match (v,el)
11694+
local
11695+
DAE.Exp exp;
11696+
DAE.ComponentRef cr;
11697+
case (DAE.VAR(componentRef=_),DAE.VAR(direction=DAE.INPUT())) then false;
11698+
case (DAE.VAR(componentRef=cr),DAE.VAR(binding=SOME(exp))) then Expression.expHasCref(exp,cr);
11699+
else false;
11700+
end match;
11701+
end checkVarBindingInputUsed;
11702+
11703+
protected function checkExternalDeclArgs
11704+
input DAE.Element v;
11705+
input list<DAE.ExtArg> args;
11706+
output Boolean notfound;
11707+
algorithm
11708+
notfound := not Util.listContainsWithCompareFunc(v,args,extArgCrefEq);
11709+
end checkExternalDeclArgs;
11710+
1158411711
protected function checkExternalFunctionOutputAssigned
1158511712
"All outputs must either have a default binding or be used in the external function
1158611713
declaration as there is no way to make assignments in external functions."
@@ -11599,10 +11726,9 @@ algorithm
1159911726
DAE.ElementSource source;
1160011727
case (DAE.VAR(direction=DAE.OUTPUT(),componentRef=cr,binding=binding,source=source),DAE.EXTERNALDECL(returnArg=arg,args=args),name)
1160111728
equation
11602-
args = Util.listSelect1(arg::args,cr,extArgCrefEq);
1160311729
// Some weird functions pass the same output twice so we cannot check for exactly 1 occurance
1160411730
// Interfacing with LAPACK routines is fun, fun, fun :)
11605-
b = listLength(args)>0 or Util.isSome(binding);
11731+
b = Util.listContainsWithCompareFunc(v,arg::args,extArgCrefEq) or Util.isSome(binding);
1160611732
str = Debug.bcallret1(not b,ComponentReference.printComponentRefStr,cr,"");
1160711733
Error.assertionOrAddSourceMessage(b,Error.EXTERNAL_NOT_SINGLE_RESULT,{str,name},DAEUtil.getElementSourceFileInfo(source));
1160811734
then ();
@@ -11612,15 +11738,21 @@ end checkExternalFunctionOutputAssigned;
1161211738

1161311739
protected function extArgCrefEq
1161411740
"See if an external argument matches a cref"
11741+
input DAE.Element v;
1161511742
input DAE.ExtArg arg;
11616-
input DAE.ComponentRef cr2;
1161711743
output Boolean b;
1161811744
algorithm
11619-
b := match (arg,cr2)
11745+
b := match (v,arg)
1162011746
local
11621-
DAE.ComponentRef cr1;
11622-
case (DAE.EXTARG(componentRef=cr1),cr2)
11747+
DAE.ComponentRef cr1,cr2;
11748+
DAE.Exp exp;
11749+
case (DAE.VAR(componentRef=cr1),DAE.EXTARG(componentRef=cr2))
11750+
then ComponentReference.crefEqualNoStringCompare(cr1,cr2);
11751+
case (DAE.VAR(direction=DAE.OUTPUT()),_) then false;
11752+
case (DAE.VAR(componentRef=cr1),DAE.EXTARGSIZE(componentRef=cr2))
1162311753
then ComponentReference.crefEqualNoStringCompare(cr1,cr2);
11754+
case (DAE.VAR(componentRef=cr1),DAE.EXTARGEXP(exp=exp))
11755+
then Expression.expHasCref(exp,cr1);
1162411756
else false;
1162511757
end match;
1162611758
end extArgCrefEq;

Compiler/FrontEnd/Parser.mo

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public function parsestringexp "Parse a string as if it was a sequence of statem
6767
input String str;
6868
input String infoFilename := "<interactive>";
6969
output Interactive.Statements outStatements;
70-
external "C" outStatements=Parser_parsestringexp(str) annotation(Library = {"omcruntime","omparse","antlr3"});
70+
external "C" outStatements=Parser_parsestringexp(str,infoFilename) annotation(Library = {"omcruntime","omparse","antlr3"});
7171
end parsestringexp;
7272
end Parser;
7373

0 commit comments

Comments
 (0)