Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 58.5% 38 / 0 / 65
Functions: -% 0 / 1 / 1
Branches: 65.9% 29 / 0 / 44

OMCompiler/Compiler/FrontEnd/NFSCodeCheck.mo
Line Branch Exec Source
1 /*
2 * This file is part of OpenModelica.
3 *
4 * Copyright (c) 1998-2026, Open Source Modelica Consortium (OSMC),
5 * c/o Linköpings universitet, Department of Computer and Information Science,
6 * SE-58183 Linköping, Sweden.
7 *
8 * All rights reserved.
9 *
10 * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF AGPL VERSION 3 LICENSE OR
11 * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8.
12 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES
13 * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GNU AGPL
14 * VERSION 3, ACCORDING TO RECIPIENTS CHOICE.
15 *
16 * The OpenModelica software and the OSMC (Open Source Modelica Consortium)
17 * Public License (OSMC-PL) are obtained from OSMC, either from the above
18 * address, from the URLs:
19 * http://www.openmodelica.org or
20 * https://github.com/OpenModelica/ or
21 * http://www.ida.liu.se/projects/OpenModelica,
22 * and in the OpenModelica distribution.
23 *
24 * GNU AGPL version 3 is obtained from:
25 * https://www.gnu.org/licenses/licenses.html#GPL
26 *
27 * This program is distributed WITHOUT ANY WARRANTY; without
28 * even the implied warranty of MERCHANTABILITY or FITNESS
29 * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH
30 * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL.
31 *
32 * See the full OSMC Public License conditions for more details.
33 *
34 */
35
36 encapsulated package NFSCodeCheck
37 " file: NFSCodeCheck.mo
38 package: NFSCodeCheck
39 description: SCode checking
40
41
42 This module checks the SCode representation for conformance "
43
44 public import Absyn;
45 public import AbsynUtil;
46 public import NFInstTypes;
47 public import SCode;
48 public import NFSCodeEnv;
49
50 protected import Debug;
51 protected import Dump;
52 protected import Error;
53 protected import Flags;
54 protected import NFInstDump;
55 protected import SCodeDump;
56 import SCodeUtil;
57
58 import NFSCodeEnv.EnvTree;
59
60 public function checkRecursiveShortDefinition
61 input Absyn.TypeSpec inTypeSpec;
62 input String inTypeName;
63 input NFSCodeEnv.Env inTypeEnv;
64 input SourceInfo inInfo;
65 algorithm
66 () := matchcontinue inTypeEnv
67 local
68 Absyn.Path ts_path, ty_path;
69 String ty;
70
71 case {} then ();
72
73 case _ :: _
74 algorithm
75 104189 ts_path := AbsynUtil.typeSpecPath(inTypeSpec);
76 104189 ty_path := NFSCodeEnv.getEnvPath(inTypeEnv);
77
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 104188 times.
104189 false := isSelfReference(inTypeName, ty_path, ts_path);
78 then
79 ();
80
81 else
82 algorithm
83 1 ty := Dump.unparseTypeSpec(inTypeSpec);
84 1 Error.addSourceMessage(Error.RECURSIVE_SHORT_CLASS_DEFINITION,
85 {inTypeName, ty}, inInfo);
86 1 then
87 fail();
88
89 end matchcontinue;
90 end checkRecursiveShortDefinition;
91
92 protected function isSelfReference
93 input String inTypeName;
94 input Absyn.Path inTypePath;
95 input Absyn.Path inReferencedName;
96 output Boolean selfRef;
97 algorithm
98 selfRef := match(inTypePath, inReferencedName)
99 local
100 Absyn.Path p1, p2;
101
102 case (p1, Absyn.FULLYQUALIFIED(p2))
103 20 then AbsynUtil.pathEqual(AbsynUtil.joinPaths(p1, Absyn.IDENT(inTypeName)), p2);
104
105 case (_, p2)
106
4/4
✓ Branch 2 taken 6391 times.
✓ Branch 3 taken 99820 times.
✓ Branch 7 taken 6390 times.
✓ Branch 8 taken 1 time.
106211 then stringEqual(AbsynUtil.pathLastIdent(inTypePath), AbsynUtil.pathFirstIdent(p2));
107
108 end match;
109 end isSelfReference;
110
111 public function checkClassExtendsReplaceability
112 input NFSCodeEnv.Item inBaseClass;
113 input SourceInfo inOriginInfo;
114 algorithm
115 () := match inBaseClass
116 local
117 case NFSCodeEnv.CLASS(cls = SCode.CLASS(prefixes = SCode.PREFIXES(
118 replaceablePrefix = SCode.REPLACEABLE())))
119 then ();
120 end match;
121 end checkClassExtendsReplaceability;
122
123 public function checkRedeclareModifier
124 input NFSCodeEnv.Redeclaration inModifier;
125 input Absyn.Path inBaseClass;
126 input NFSCodeEnv.Env inEnv;
127 algorithm
128 () := match inModifier
129 local
130 SCode.Element e;
131
132 case NFSCodeEnv.RAW_MODIFIER(e as SCode.CLASS(classDef =
133 SCode.DERIVED()))
134 algorithm
135 2042 checkRedeclareModifier2(e, inBaseClass, inEnv);
136 then
137 ();
138
139 else ();
140 end match;
141 end checkRedeclareModifier;
142
143 public function checkRedeclareModifier2
144 input SCode.Element inModifier;
145 input Absyn.Path inBaseClass;
146 input NFSCodeEnv.Env inEnv;
147 algorithm
148 () := matchcontinue inModifier
149 local
150 Absyn.TypeSpec ty;
151 SourceInfo info;
152 String name, ty_str;
153 Absyn.Path ty_path;
154
155 case SCode.CLASS(name = name,
156 classDef = SCode.DERIVED(typeSpec = ty))
157 algorithm
158 2042 ty_path := AbsynUtil.typeSpecPath(ty);
159
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2042 times.
2042 false := isSelfReference(name, inBaseClass, ty_path);
160 then
161 ();
162
163 case SCode.CLASS(name = name,
164 classDef = SCode.DERIVED(typeSpec = ty), info = info)
165 algorithm
166 ✗ ty_str := Dump.unparseTypeSpec(ty);
167 ✗ Error.addSourceMessage(Error.RECURSIVE_SHORT_CLASS_DEFINITION,
168 {name, ty_str}, info);
169 ✗ then
170 fail();
171
172 end matchcontinue;
173 end checkRedeclareModifier2;
174
175 public function checkModifierIfRedeclare
176 input NFSCodeEnv.Item inItem;
177 input SCode.Mod inModifier;
178 input SourceInfo inInfo;
179 algorithm
180 () := match inModifier
181 local
182 SCode.Element el;
183
184 case SCode.REDECL(element = el)
185 algorithm
186 199 checkRedeclaredElementPrefix(inItem, el, inInfo);
187 then
188 ();
189
190 else ();
191 end match;
192 end checkModifierIfRedeclare;
193
194 public function checkRedeclaredElementPrefix
195 "Checks that an element that is being redeclared is declared as replaceable
196 and non-final, otherwise an error is printed."
197 input NFSCodeEnv.Item inItem;
198 input SCode.Element inReplacement;
199 input SourceInfo inInfo;
200 algorithm
201 () := match(inItem, inReplacement)
202 local
203 SCode.Replaceable repl;
204 SCode.Final fin;
205 SCode.Ident name;
206 SourceInfo info;
207 SCode.Variability var;
208 SCode.Restriction res;
209 String ty;
210 Absyn.TypeSpec ty1, ty2;
211 Boolean ok;
212
213 case (NFSCodeEnv.VAR(var =
214 SCode.COMPONENT(name = name, prefixes = SCode.PREFIXES(
215 finalPrefix = fin, replaceablePrefix = repl),
216 attributes = SCode.ATTR(variability = var), typeSpec = ty1, info = info)),
217 SCode.COMPONENT(prefixes = SCode.PREFIXES(), typeSpec = ty2))
218 algorithm
219 ty := "component";
220 47 ok := checkCompRedeclarationReplaceable(name, repl, ty1, ty2, inInfo, info);
221
3/4
✓ Branch 1 taken 45 times.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
✓ Branch 4 taken 45 times.
46 ok := checkRedeclarationFinal(name, ty, fin, inInfo, info) and ok;
222
4/4
✓ Branch 1 taken 45 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 44 times.
✓ Branch 4 taken 1 time.
46 ok := checkRedeclarationVariability(name, ty, var, inInfo, info) and ok;
223 //checkRedeclarationVisibility(name, ty, vis1, vis2, inInfo, info);
224 2 true := ok;
225 then
226 ();
227
228 case (NFSCodeEnv.CLASS(cls =
229 SCode.CLASS(name = name, prefixes = SCode.PREFIXES(
230 finalPrefix = fin, replaceablePrefix = repl),
231 restriction = res, info = info)),
232 SCode.CLASS(prefixes = SCode.PREFIXES()))
233 algorithm
234 152 ty := SCodeDump.restrictionStringPP(res);
235 152 ok := checkClassRedeclarationReplaceable(name, repl, inInfo, info);
236
2/4
✓ Branch 1 taken 152 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 152 times.
152 ok := checkRedeclarationFinal(name, ty, fin, inInfo, info) and ok;
237 //checkRedeclarationVisibility(name, ty, vis1, vis2, inInfo, info);
238 ✗ true := ok;
239 then
240 ();
241
242 case (NFSCodeEnv.VAR(var = SCode.COMPONENT(name = name, info = info)),
243 SCode.CLASS(restriction = res))
244 algorithm
245 ✗ ty := SCodeDump.restrictionStringPP(res);
246 ✗ ty := "a " + ty;
247 ✗ Error.addMultiSourceMessage(Error.INVALID_REDECLARE_AS,
248 {"component", name, ty}, {inInfo, info});
249 ✗ then
250 fail();
251
252 case (NFSCodeEnv.CLASS(cls = SCode.CLASS(restriction = res, info = info)),
253 SCode.COMPONENT(name = name))
254 algorithm
255 ✗ ty := SCodeDump.restrictionStringPP(res);
256 ✗ Error.addMultiSourceMessage(Error.INVALID_REDECLARE_AS,
257 {ty, name, "a component"}, {inInfo, info});
258 ✗ then
259 fail();
260
261 else ();
262 end match;
263 end checkRedeclaredElementPrefix;
264
265 protected function checkClassRedeclarationReplaceable
266 input SCode.Ident inName;
267 input SCode.Replaceable inReplaceable;
268 input SourceInfo inOriginInfo;
269 input SourceInfo inInfo;
270 output Boolean isValid;
271 algorithm
272 isValid := match inReplaceable
273 case SCode.NOT_REPLACEABLE() guard not Flags.getConfigBool(Flags.IGNORE_REPLACEABLE)
274 algorithm
275 ✗ Error.addMultiSourceMessage(Error.REDECLARE_NON_REPLACEABLE,
276 {inName}, {inOriginInfo, inInfo});
277 then
278 false;
279
280 else true;
281
282 end match;
283 end checkClassRedeclarationReplaceable;
284
285 protected function checkCompRedeclarationReplaceable
286 input SCode.Ident inName;
287 input SCode.Replaceable inReplaceable;
288 input Absyn.TypeSpec inType1;
289 input Absyn.TypeSpec inType2;
290 input SourceInfo inOriginInfo;
291 input SourceInfo inInfo;
292 output Boolean isValid;
293 algorithm
294 isValid := match inReplaceable
295 case SCode.NOT_REPLACEABLE()
296 guard AbsynUtil.pathEqual(AbsynUtil.typeSpecPath(inType1),
297 AbsynUtil.typeSpecPath(inType2))
298 then
299 true;
300
301 case SCode.NOT_REPLACEABLE() guard not Flags.getConfigBool(Flags.IGNORE_REPLACEABLE)
302 algorithm
303 1 Error.addMultiSourceMessage(Error.REDECLARE_NON_REPLACEABLE,
304 {inName}, {inOriginInfo, inInfo});
305 1 then
306 fail();
307
308 else true;
309
310 end match;
311 end checkCompRedeclarationReplaceable;
312
313 protected function checkRedeclarationFinal
314 input SCode.Ident inName;
315 input String inType;
316 input SCode.Final inFinal;
317 input SourceInfo inOriginInfo;
318 input SourceInfo inInfo;
319 output Boolean isValid;
320 algorithm
321 isValid := match inFinal
322 case SCode.NOT_FINAL() then true;
323
324 case SCode.FINAL()
325 algorithm
326 1 Error.addMultiSourceMessage(Error.INVALID_REDECLARE,
327 {"final", inType, inName}, {inOriginInfo, inInfo});
328 then
329 false;
330
331 end match;
332 end checkRedeclarationFinal;
333
334 protected function checkRedeclarationVariability
335 input SCode.Ident inName;
336 input String inType;
337 input SCode.Variability inVariability;
338 input SourceInfo inOriginInfo;
339 input SourceInfo inInfo;
340 output Boolean isValid;
341 algorithm
342 isValid := match inVariability
343 case SCode.CONST()
344 algorithm
345 1 Error.addMultiSourceMessage(Error.INVALID_REDECLARE,
346 {"constant", inType, inName}, {inOriginInfo, inInfo});
347 then
348 false;
349
350 else true;
351 end match;
352 end checkRedeclarationVariability;
353
354 protected function checkRedeclarationVisibility
355 input SCode.Ident inName;
356 input String inType;
357 input SCode.Visibility inOriginalVisibility;
358 input SCode.Visibility inNewVisibility;
359 input SourceInfo inOriginInfo;
360 input SourceInfo inNewInfo;
361 output Boolean isValid;
362 algorithm
363 isValid := match (inOriginalVisibility, inNewVisibility)
364 case (SCode.PUBLIC(), SCode.PROTECTED())
365 algorithm
366 ✗ Error.addMultiSourceMessage(Error.INVALID_REDECLARE_AS,
367 {"public element", inName, "protected"}, {inNewInfo, inOriginInfo});
368 then
369 false;
370
371 case (SCode.PROTECTED(), SCode.PUBLIC())
372 algorithm
373 ✗ Error.addMultiSourceMessage(Error.INVALID_REDECLARE_AS,
374 {"protected element", inName, "public"}, {inNewInfo, inOriginInfo});
375 then
376 false;
377
378 else true;
379 end match;
380 end checkRedeclarationVisibility;
381
382 public function checkDuplicateRedeclarations
383 "Checks if a redeclaration already exists in a list of redeclarations."
384 input NFSCodeEnv.Redeclaration inRedeclare;
385 input list<NFSCodeEnv.Redeclaration> inRedeclarations;
386 protected
387 String el_name;
388 SourceInfo el_info;
389 algorithm
390 69527 (el_name, el_info) := NFSCodeEnv.getRedeclarationNameInfo(inRedeclare);
391
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 69526 times.
69527 false := checkDuplicateRedeclarations2(el_name, el_info, inRedeclarations);
392 end checkDuplicateRedeclarations;
393
394 protected function checkDuplicateRedeclarations2
395 "Helper function to checkDuplicateRedeclarations."
396 input String inRedeclareName;
397 input SourceInfo inRedeclareInfo;
398 input list<NFSCodeEnv.Redeclaration> inRedeclarations;
399 output Boolean outIsDuplicate;
400 algorithm
401 outIsDuplicate := matchcontinue inRedeclarations
402 local
403 NFSCodeEnv.Redeclaration redecl;
404 list<NFSCodeEnv.Redeclaration> rest_redecls;
405 String el_name;
406 SourceInfo el_info;
407
408 case {} then false;
409
410 case redecl :: _
411 algorithm
412 753087 (el_name, el_info) := NFSCodeEnv.getRedeclarationNameInfo(redecl);
413
4/4
✓ Branch 0 taken 53772 times.
✓ Branch 1 taken 699315 times.
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 53771 times.
753087 true := stringEqual(inRedeclareName, el_name);
414 1 Error.addSourceMessage(Error.ERROR_FROM_HERE, {}, el_info);
415 1 Error.addSourceMessage(Error.DUPLICATE_REDECLARATION,
416 {inRedeclareName}, inRedeclareInfo);
417 then
418 true;
419
420 case _ :: rest_redecls
421 753086 then checkDuplicateRedeclarations2(inRedeclareName,
422 inRedeclareInfo, rest_redecls);
423
424 end matchcontinue;
425 end checkDuplicateRedeclarations2;
426
427 public function checkRecursiveComponentDeclaration
428 "Checks if a component is declared with a type that is one of the enclosing
429 classes, e.g:
430 class A
431 class B
432 A a;
433 end B;
434 end A;
435 "
436 input String inComponentName;
437 input SourceInfo inComponentInfo;
438 input NFSCodeEnv.Env inTypeEnv;
439 input NFSCodeEnv.Item inTypeItem;
440 input NFSCodeEnv.Env inComponentEnv;
441 algorithm
442 () := matchcontinue(inTypeEnv, inComponentEnv)
443 local
444 String cls_name, ty_name;
445 EnvTree.Tree tree;
446 SCode.Element el;
447
448 // No environment means one of the basic types.
449 case ({}, _) then ();
450
451 // Check that the environment of the components type is not an enclosing
452 // scope of the component itself.
453 case (_, _)
454 algorithm
455
2/2
✓ Branch 1 taken 292 times.
✓ Branch 2 taken 56910 times.
57202 false := NFSCodeEnv.envPrefixOf(inTypeEnv, inComponentEnv);
456 then
457 ();
458
459 // Make an exception for components in functions
460 case (_, NFSCodeEnv.FRAME(name = SOME(cls_name)) ::
461 NFSCodeEnv.FRAME(clsAndVars = tree) :: _)
462 algorithm
463
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 292 times.
292 NFSCodeEnv.CLASS(cls = el) := EnvTree.get(tree, cls_name);
464
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 291 times.
292 true := SCodeUtil.isFunction(el);
465 then
466 ();
467
468 // Make an exception for components in uniontypes
469 case (_, NFSCodeEnv.FRAME(name = SOME(cls_name)) ::
470 NFSCodeEnv.FRAME(clsAndVars = tree) :: _)
471 algorithm
472
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 NFSCodeEnv.CLASS(cls = el) := EnvTree.get(tree, cls_name);
473
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
1 true := SCodeUtil.isUniontype(el);
474 then
475 ();
476
477 else
478 algorithm
479 1 ty_name := NFSCodeEnv.getItemName(inTypeItem);
480
481 1 Error.addSourceMessage(Error.RECURSIVE_DEFINITION,
482 {inComponentName, ty_name}, inComponentInfo);
483 1 then
484 fail();
485
486 end matchcontinue;
487 end checkRecursiveComponentDeclaration;
488
489 public function checkIdentNotEqTypeName
490 "Checks that a simple identifier is not the same as a type name."
491 input String inIdent;
492 input Absyn.TypeSpec inTypeName;
493 input SourceInfo inInfo;
494 output Boolean outIsNotEq;
495 algorithm
496 outIsNotEq := matchcontinue(inIdent, inTypeName)
497 local
498 String id, ty;
499
500 case (id, Absyn.TPATH(path = Absyn.IDENT(ty)))
501 algorithm
502 ✗ true := stringEq(id, ty);
503 ✗ Error.addSourceMessage(Error.LOOKUP_TYPE_FOUND_COMP, {id}, inInfo);
504 then
505 false;
506
507 else true;
508 end matchcontinue;
509 end checkIdentNotEqTypeName;
510
511 public function checkComponentsEqual
512 input NFInstTypes.Component inComponent1;
513 input NFInstTypes.Component inComponent2;
514 algorithm
515 () := match inComponent2
516 case _
517 algorithm
518 ✗ print("Found duplicate component\n");
519 then
520 ();
521
522 end match;
523 end checkComponentsEqual;
524
525 public function checkInstanceRestriction
526 input NFSCodeEnv.Item inItem;
527 input NFInstTypes.Prefix inPrefix;
528 input SourceInfo inInfo;
529 algorithm
530 () := matchcontinue inItem
531 local
532 SCode.Restriction res;
533 String pre_str, res_str;
534
535 case NFSCodeEnv.CLASS(cls = SCode.CLASS(restriction = res))
536 algorithm
537 ✗ true := SCodeUtil.isInstantiableClassRestriction(res);
538 then
539 ();
540
541 case NFSCodeEnv.CLASS(cls = SCode.CLASS(restriction = res))
542 algorithm
543 ✗ res_str := SCodeDump.restrictionStringPP(res);
544 ✗ pre_str := NFInstDump.prefixStr(inPrefix);
545 ✗ Error.addSourceMessage(Error.INVALID_CLASS_RESTRICTION,
546 {res_str, pre_str}, inInfo);
547 ✗ then
548 fail();
549
550 else
551 algorithm
552 ✗ true := Flags.isSet(Flags.FAILTRACE);
553 ✗ Debug.traceln("- NFSCodeCheck.checkInstanceRestriction failed on unknown item.");
554 ✗ then
555 fail();
556
557 end matchcontinue;
558 end checkInstanceRestriction;
559
560 public function checkPartialInstance
561 "Checks if the given item is partial, and prints out an error message in that
562 case."
563 input NFSCodeEnv.Item inItem;
564 input SourceInfo inInfo;
565 algorithm
566 () := match inItem
567 local
568 String name;
569
570 case NFSCodeEnv.CLASS(cls = SCode.CLASS(name = name, partialPrefix =
571 SCode.PARTIAL()))
572 algorithm
573 ✗ Error.addSourceMessage(Error.INST_PARTIAL_CLASS, {name}, inInfo);
574 ✗ then
575 fail();
576
577 else ();
578 end match;
579 end checkPartialInstance;
580
581 annotation(__OpenModelica_Interface="frontend");
582 end NFSCodeCheck;
583