Skip to content

Commit 9a38b2a

Browse files
committed
Change handling of misplaced external annotations
- Copy external function annotations that are misplaced on the function itself to the external declaration if the external declaration has no annotation, and issue a warning if that happens. Previously the annotation on the function and the external declaration were always merged, which could result in invalid annotations on the external declaration and could also cause the annotation to grow each time e.g. saveTotalModel was used on the function.
1 parent 409ec78 commit 9a38b2a

File tree

7 files changed

+123
-75
lines changed

7 files changed

+123
-75
lines changed

OMCompiler/Compiler/FrontEnd/AbsynToSCode.mo

Lines changed: 47 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ public import AbsynUtil;
4949
public import SCode;
5050

5151
protected
52+
import Config;
5253
import Debug;
5354
import Error;
5455
import Flags;
@@ -449,7 +450,7 @@ algorithm
449450
cos = translateClassdefConstraints(parts);
450451
scodeCmt = translateCommentList(ann, cmtString);
451452
decl = translateClassdefExternaldecls(parts);
452-
decl = translateAlternativeExternalAnnotation(decl,scodeCmt);
453+
decl = translateAlternativeExternalAnnotation(decl, scodeCmt, info);
453454
then
454455
(SCode.PARTS(els,eqs,initeqs,als,initals,cos,classAttrs,decl),scodeCmt);
455456

@@ -487,7 +488,7 @@ algorithm
487488
mod = translateMod(SOME(Absyn.CLASSMOD(cmod,Absyn.NOMOD())), SCode.NOT_FINAL(), SCode.NOT_EACH(), NONE(), AbsynUtil.dummyInfo);
488489
scodeCmt = translateCommentList(ann, cmtString);
489490
decl = translateClassdefExternaldecls(parts);
490-
decl = translateAlternativeExternalAnnotation(decl,scodeCmt);
491+
decl = translateAlternativeExternalAnnotation(decl, scodeCmt, info);
491492
then
492493
(SCode.CLASS_EXTENDS(mod,SCode.PARTS(els,eqs,initeqs,als,initals,cos,{},decl)),scodeCmt);
493494

@@ -507,54 +508,53 @@ algorithm
507508
end translateClassdef;
508509

509510
protected function translateAlternativeExternalAnnotation
510-
"first class annotation instead, since it is very common that an element
511-
annotation is used for this purpose.
512-
For instance, instead of external \"C\" annotation(Library=\"foo.lib\";
513-
it says external \"C\" ; annotation(Library=\"foo.lib\";"
514-
input Option<SCode.ExternalDecl> decl;
515-
input SCode.Comment comment;
516-
output Option<SCode.ExternalDecl> outDecl;
511+
"Checks if the annotation for an external declaration is misplaced, i.e.
512+
external \"C\"; annotation(Library=\"foo.lib\");
513+
instead of
514+
external \"C\" annotation(Library=\"foo.lib\");
515+
"
516+
input Option<SCode.ExternalDecl> decl;
517+
input SCode.Comment comment;
518+
input SourceInfo info;
519+
output Option<SCode.ExternalDecl> outDecl;
520+
protected
521+
SCode.ExternalDecl ext_decl;
522+
SCode.Annotation ann;
523+
524+
function whitelist_mod
525+
input SCode.SubMod submod;
526+
output Boolean keep;
527+
algorithm
528+
keep := match submod.ident
529+
case "Library" then true;
530+
case "Include" then true;
531+
case "LibraryDirectory" then true;
532+
case "SourceDirectory" then true;
533+
case "License" then true;
534+
else false;
535+
end match;
536+
end whitelist_mod;
517537
algorithm
518-
outDecl := match (decl,comment)
519-
local
520-
Option<SCode.Ident> name ;
521-
Option<String> l ;
522-
Option<Absyn.ComponentRef> out ;
523-
list<Absyn.Exp> a;
524-
Option<SCode.Annotation> ann1,ann2,ann;
525-
// none
526-
case (NONE(),_) then NONE();
527-
// Else, merge
528-
case (SOME(SCode.EXTERNALDECL(name,l,out,a,ann1)),SCode.COMMENT(annotation_=ann2))
529-
equation
530-
ann = SCodeUtil.mergeSCodeOptAnn(ann1, ann2);
531-
then SOME(SCode.EXTERNALDECL(name,l,out,a,ann));
532-
end match;
533-
end translateAlternativeExternalAnnotation;
538+
outDecl := match (decl, comment)
539+
// The external declaration is missing an annotation but there is one on the function.
540+
case (SOME(ext_decl as SCode.EXTERNALDECL(annotation_ = NONE())), SCode.COMMENT(annotation_ = SOME(ann)))
541+
algorithm
542+
// Filter out only the modifiers allowed on an external declaration.
543+
ann.modification := SCodeUtil.filterSubMods(ann.modification, whitelist_mod);
534544

535-
protected function mergeSCodeAnnotationsFromParts
536-
input Absyn.ClassPart part;
537-
input Option<SCode.Annotation> inMod;
538-
output Option<SCode.Annotation> outMod;
539-
algorithm
540-
outMod := match (part,inMod)
541-
local
542-
Absyn.Annotation aann;
543-
Option<SCode.Annotation> ann;
544-
list<Absyn.ElementItem> rest;
545-
case (Absyn.EXTERNAL(_,SOME(aann)),_)
546-
equation
547-
ann = translateAnnotation(aann);
548-
ann = SCodeUtil.mergeSCodeOptAnn(ann, inMod);
549-
then ann;
550-
case (Absyn.PUBLIC(_::rest),_)
551-
then mergeSCodeAnnotationsFromParts(Absyn.PUBLIC(rest),inMod);
552-
case (Absyn.PROTECTED(_::rest),_)
553-
then mergeSCodeAnnotationsFromParts(Absyn.PROTECTED(rest),inMod);
554-
555-
else inMod;
545+
// If any matching modifiers were found, issue a warning and copy them to the external declaration.
546+
if not SCodeUtil.isEmptyMod(ann.modification) then
547+
if Config.languageStandardAtLeast(Config.LanguageStandard.'3.3') then
548+
Error.addSourceMessage(Error.MISPLACED_EXTERNAL_ANNOTATION, {}, info);
549+
end if;
550+
ext_decl.annotation_ := SOME(ann);
551+
end if;
552+
then
553+
SOME(ext_decl);
554+
555+
else decl;
556556
end match;
557-
end mergeSCodeAnnotationsFromParts;
557+
end translateAlternativeExternalAnnotation;
558558

559559
protected function translateEnumlist
560560
"Convert an EnumLiteral list to an Ident list.

OMCompiler/Compiler/FrontEnd/ModelicaBuiltin.mo

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1870,8 +1870,8 @@ impure function alarm
18701870
"Schedules an alarm signal for the process."
18711871
input Integer seconds;
18721872
output Integer previousSeconds;
1873-
external "builtin";
1874-
annotation(__OpenModelica_Impure=true,Library = {"omcruntime"},Documentation(info="<html>
1873+
external "builtin" annotation(Library = {"omcruntime"});
1874+
annotation(__OpenModelica_Impure=true,Documentation(info="<html>
18751875
<p>Like <a href=\"http://linux.die.net/man/2/alarm\">alarm(2)</a>.</p>
18761876
<p>Note that OpenModelica also sends SIGALRM to the process group when the alarm is triggered (in order to kill running simulations).</p>
18771877
</html>"));

OMCompiler/Compiler/NFFrontEnd/NFModelicaBuiltin.mo

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2116,8 +2116,8 @@ impure function alarm
21162116
"Schedules an alarm signal for the process."
21172117
input Integer seconds;
21182118
output Integer previousSeconds;
2119-
external "builtin";
2120-
annotation(__OpenModelica_Impure=true,Library = {"omcruntime"},Documentation(info="<html>
2119+
external "builtin" annotation(Library = {"omcruntime"});
2120+
annotation(__OpenModelica_Impure=true,Documentation(info="<html>
21212121
<p>Like <a href=\"http://linux.die.net/man/2/alarm\">alarm(2)</a>.</p>
21222122
<p>Note that OpenModelica also sends SIGALRM to the process group when the alarm is triggered (in order to kill running simulations).</p>
21232123
</html>"));

OMCompiler/Compiler/Util/Error.mo

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1147,6 +1147,8 @@ public constant ErrorTypes.Message REINIT_IN_ALGORITHM = ErrorTypes.MESSAGE(618,
11471147
Gettext.gettext("Operator reinit may not be used in an algorithm section (use translation flag --allowNonStandardModelica=reinitInAlgorithms to ignore)."));
11481148
public constant ErrorTypes.Message HIDE_RESULT_NOT_EVALUATED = ErrorTypes.MESSAGE(619, ErrorTypes.TRANSLATION(), ErrorTypes.WARNING(),
11491149
Gettext.gettext("Ignoring the hideResult annotation on '%s' which could not be evaluated, probably due to missing annotation(Evaluate=true)."));
1150+
public constant ErrorTypes.Message MISPLACED_EXTERNAL_ANNOTATION = ErrorTypes.MESSAGE(620, ErrorTypes.TRANSLATION(), ErrorTypes.WARNING(),
1151+
Gettext.gettext("External function annotation should occur on the external-clause, not on the function."));
11501152

11511153
public constant ErrorTypes.Message MATCH_SHADOWING = ErrorTypes.MESSAGE(5001, ErrorTypes.TRANSLATION(), ErrorTypes.ERROR(),
11521154
Gettext.gettext("Local variable '%s' shadows another variable."));

testsuite/flattening/modelica/ffi/FFITest/package.mo

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package FFITest
33
function real1
44
input Real x;
55
output Real y;
6-
external "C" y = real1_ext(x);
6+
external "C" y = real1_ext(x)
77
annotation(Library="FFITestLib");
88
end real1;
99

@@ -16,7 +16,7 @@ package FFITest
1616
input Real y;
1717
input Real z;
1818
output Real r;
19-
external "C" r = real2_ext(x, y, z);
19+
external "C" r = real2_ext(x, y, z)
2020
annotation(Library="FFITestLib");
2121
end real2;
2222

@@ -28,7 +28,7 @@ package FFITest
2828
input Real x;
2929
input Real y;
3030
output Real r;
31-
external "C" real3_ext(x, y, r);
31+
external "C" real3_ext(x, y, r)
3232
annotation(Library="FFITestLib");
3333
end real3;
3434

@@ -39,7 +39,7 @@ package FFITest
3939
function integer1
4040
input Integer x;
4141
output Integer y;
42-
external "C" y = integer1_ext(x);
42+
external "C" y = integer1_ext(x)
4343
annotation(Library="FFITestLib");
4444
end integer1;
4545

@@ -52,7 +52,7 @@ package FFITest
5252
input Integer y;
5353
input Integer z;
5454
output Integer r;
55-
external "C" r = integer2_ext(x, y, z);
55+
external "C" r = integer2_ext(x, y, z)
5656
annotation(Library="FFITestLib");
5757
end integer2;
5858

@@ -63,7 +63,7 @@ package FFITest
6363
function boolean1
6464
input Boolean x;
6565
output Boolean y;
66-
external "C" y = boolean1_ext(x);
66+
external "C" y = boolean1_ext(x)
6767
annotation(Library="FFITestLib");
6868
end boolean1;
6969

@@ -77,7 +77,7 @@ package FFITest
7777
input Boolean y;
7878
input Boolean z;
7979
output Boolean r;
80-
external "C" r = boolean2_ext(x, y, z);
80+
external "C" r = boolean2_ext(x, y, z)
8181
annotation(Library="FFITestLib");
8282
end boolean2;
8383

@@ -91,7 +91,7 @@ package FFITest
9191
function enum1
9292
input E1 x;
9393
output E1 y;
94-
external "C" y = enum1_ext(x);
94+
external "C" y = enum1_ext(x)
9595
annotation(Library="FFITestLib");
9696
end enum1;
9797

@@ -104,7 +104,7 @@ package FFITest
104104
input E1 x;
105105
input E1 y;
106106
output E1 r;
107-
external "C" r = enum2_ext(x, y);
107+
external "C" r = enum2_ext(x, y)
108108
annotation(Library="FFITestLib");
109109
end enum2;
110110

@@ -119,7 +119,7 @@ package FFITest
119119
function string1
120120
input String x;
121121
output Integer y;
122-
external "C" y = string1_ext(x);
122+
external "C" y = string1_ext(x)
123123
annotation(Library="FFITestLib");
124124
end string1;
125125

@@ -131,7 +131,7 @@ package FFITest
131131
output String s;
132132
protected
133133
Boolean eof;
134-
external "C" s = ModelicaInternal_readLine("String2.mos", 1, eof);
134+
external "C" s = ModelicaInternal_readLine("String2.mos", 1, eof)
135135
annotation(Library="ModelicaExternalC");
136136
end string2;
137137

@@ -144,7 +144,7 @@ package FFITest
144144
function realArray1
145145
input Real x[:];
146146
output Real y[size(x, 1)];
147-
external "C" realArray1_ext(x, size(x, 1), y);
147+
external "C" realArray1_ext(x, size(x, 1), y)
148148
annotation(Library="FFITestLib");
149149
end realArray1;
150150

@@ -155,7 +155,7 @@ package FFITest
155155
function stringArray1
156156
input String s[:];
157157
output Integer lens[size(s, 1)];
158-
external "C" stringArray1_ext(s, size(s, 1), lens);
158+
external "C" stringArray1_ext(s, size(s, 1), lens)
159159
annotation(Library="FFITestLib");
160160
end stringArray1;
161161

@@ -172,7 +172,7 @@ package FFITest
172172
function record1
173173
input R1 r1;
174174
output Real x;
175-
external "C" x = record1_ext(r1);
175+
external "C" x = record1_ext(r1)
176176
annotation(Library="FFITestLib");
177177
end record1;
178178

@@ -192,7 +192,7 @@ package FFITest
192192
input Real y;
193193
input Real z;
194194
output R2 r2;
195-
external "C" record2_ext(r2, x, y, z);
195+
external "C" record2_ext(r2, x, y, z)
196196
annotation(Library="FFITestLib");
197197
end record2;
198198

@@ -211,7 +211,7 @@ package FFITest
211211
input Real r;
212212
input Integer i2;
213213
output R3 r3;
214-
external "C" record3_ext(r3, i1, r, i2);
214+
external "C" record3_ext(r3, i1, r, i2)
215215
annotation(Library="FFITestLib");
216216
end record3;
217217

@@ -228,7 +228,7 @@ package FFITest
228228
function record4
229229
input Real arr[5];
230230
output R4 r4;
231-
external "C" record4_ext(arr, r4);
231+
external "C" record4_ext(arr, r4)
232232
annotation(Library="FFITestLib");
233233
end record4;
234234

@@ -239,7 +239,7 @@ package FFITest
239239
function record5
240240
input Real x;
241241
output R1 r1;
242-
external "C" r1 = record5_ext(x);
242+
external "C" r1 = record5_ext(x)
243243
annotation(Library="FFITestLib");
244244
end record5;
245245

@@ -251,7 +251,7 @@ package FFITest
251251
package ErrorChecking
252252
function missingFunction1
253253
output Real x;
254-
external "C" x = missingFunction1_ext();
254+
external "C" x = missingFunction1_ext()
255255
annotation(Library="FFITestLib");
256256
end missingFunction1;
257257

@@ -261,7 +261,7 @@ package FFITest
261261

262262
function arrayResult1
263263
output Real[3] x;
264-
external "C" x = arrayResult1_ext();
264+
external "C" x = arrayResult1_ext()
265265
annotation(Library="FFITestLib");
266266
end arrayResult1;
267267

@@ -294,7 +294,7 @@ package FFITest
294294
function countLines
295295
input String filename;
296296
output Integer lines;
297-
external "C" lines = ModelicaInternal_countLines(filename);
297+
external "C" lines = ModelicaInternal_countLines(filename)
298298
annotation(Library="ModelicaExternalC");
299299
end countLines;
300300

@@ -309,7 +309,7 @@ package FFITest
309309
output Real number;
310310
protected
311311
Integer nextIndex;
312-
external "C" ModelicaStrings_scanReal(string, startIndex, unsigned, nextIndex, number);
312+
external "C" ModelicaStrings_scanReal(string, startIndex, unsigned, nextIndex, number)
313313
annotation(Library="ModelicaExternalC");
314314
end scanReal;
315315

@@ -324,7 +324,7 @@ package FFITest
324324
output Integer number;
325325
protected
326326
Integer nextIndex;
327-
external "C" ModelicaStrings_scanInteger(string, startIndex, unsigned, nextIndex, number);
327+
external "C" ModelicaStrings_scanInteger(string, startIndex, unsigned, nextIndex, number)
328328
annotation(Library="ModelicaExternalC");
329329
end scanInteger;
330330

@@ -338,7 +338,7 @@ package FFITest
338338
output String outString;
339339
protected
340340
Integer nextIndex;
341-
external "C" ModelicaStrings_scanString(string, startIndex, nextIndex, outString);
341+
external "C" ModelicaStrings_scanString(string, startIndex, nextIndex, outString)
342342
annotation(Library="ModelicaExternalC");
343343
end scanString;
344344

testsuite/openmodelica/interactive-API/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ ReverseLookup3.mos \
129129
RunScript.mos \
130130
saveShort.mos \
131131
saveTotalModel.mos \
132+
saveTotalModel2.mos \
132133
setComponentComment.mos \
133134
setComponentModifierValue.mos \
134135
setElementAnnotation.mos \

0 commit comments

Comments
 (0)