]> andersk Git - splint.git/blame - src/nameChecks.c
*** empty log message ***
[splint.git] / src / nameChecks.c
CommitLineData
616915dd 1/*
2** LCLint - annotation-assisted static program checker
28bf4b0b 3** Copyright (C) 1994-2001 University of Virginia,
616915dd 4** Massachusetts Institute of Technology
5**
6** This program is free software; you can redistribute it and/or modify it
7** under the terms of the GNU General Public License as published by the
8** Free Software Foundation; either version 2 of the License, or (at your
9** option) any later version.
10**
11** This program is distributed in the hope that it will be useful, but
12** WITHOUT ANY WARRANTY; without even the implied warranty of
13** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14** General Public License for more details.
15**
16** The GNU General Public License is available from http://www.gnu.org/ or
17** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18** MA 02111-1307, USA.
19**
20** For information on lclint: lclint-request@cs.virginia.edu
21** To report a bug: lclint-bug@cs.virginia.edu
22** For more information: http://lclint.cs.virginia.edu
23*/
24/*
25** nameChecks.c
26*/
27
28# include "lclintMacros.nf"
29# include "basic.h"
30# include "nameChecks.h"
31
32static bool checkCzechName (uentry p_ue, flagcode p_czechflag, bool p_report)
33 /*@modifies p_ue, g_msgstream@*/ ;
34
35static bool checkSlovakName (uentry p_ue, flagcode p_slovakflag, bool p_report)
36 /*@modifies p_ue, g_msgstream@*/ ;
37
38static cstring czechPrefix (cstring name)
39{
40 return (cstring_beforeChar (name, '_'));
41}
42
43static cstring slovakPrefix (cstring name)
44{
45 int i = 0;
46
47 cstring_chars (name, c)
48 {
49 if (isupper ((unsigned char) c))
50 {
51 return (cstring_prefix (name, i));
52 }
53 i++;
54 } end_cstring_chars;
55
56 return cstring_undefined;
57}
58
59static flagcode excludeCodes [] =
60 {
61 FLG_MACROVARPREFIXEXCLUDE,
62 FLG_TAGPREFIXEXCLUDE,
63 FLG_ENUMPREFIXEXCLUDE,
64 FLG_FILESTATICPREFIXEXCLUDE,
65 FLG_GLOBPREFIXEXCLUDE,
66 FLG_TYPEPREFIXEXCLUDE,
67 FLG_EXTERNALPREFIXEXCLUDE,
68 FLG_UNCHECKEDMACROPREFIXEXCLUDE,
69 FLG_LOCALPREFIXEXCLUDE,
70 INVALID_FLAG
71 } ;
72
73/*@iter excludeFlagCodes (yield flagcode code);@*/
74# define excludeFlagCodes(m_c) \
75 { int m_i = 0; while (flagcode_isValid (excludeCodes[m_i])) \
76 { flagcode m_c = excludeCodes[m_i]; m_i++;
77
78# define end_excludeFlagCodes }}
79
80static bool matchPrefixChar (int nc, int pc)
81{
82 if (nc == pc)
83 {
84 return TRUE;
85 }
86 else
87 {
88 switch (pc)
89 {
90 case PFX_UPPERCASE:
91 return isupper (nc);
92 case PFX_LOWERCASE:
93 return islower (nc);
94 case PFX_ANY:
95 return TRUE;
96 case PFX_DIGIT:
97 return isdigit (nc);
98 case PFX_NOTUPPER:
99 return !isupper (nc);
100 case PFX_NOTLOWER:
101 return !islower (nc);
102 case PFX_ANYLETTER:
103 return isalpha (nc);
104 case PFX_ANYLETTERDIGIT:
105 return (isdigit (nc) || isalpha (nc));
106 default: return FALSE;
107 }
108 }
109
110 BADEXIT;
111}
112
113static bool matchPrefix (cstring name, cstring prefix)
114{
115 if (cstring_isUndefined (name)
116 || cstring_isUndefined (prefix))
117 {
118 return TRUE;
119 }
120 else
121 {
122 int namelen = cstring_length (name);
123 int last = (int) '\0';
124 int n = 1;
125
126 cstring_chars (prefix, pc)
127 {
128 int nc;
129
130 if (pc == '*')
131 {
132 n++;
133
616915dd 134 while (n <= namelen)
135 {
136 nc = (int) cstring_getChar (name, n);
137
138 if (!matchPrefixChar (nc, last))
139 {
140 return FALSE;
141 }
28bf4b0b 142
616915dd 143 n++;
144 }
145
146 return TRUE;
147 }
148 else
149 {
150 if (n > namelen)
151 {
28bf4b0b 152 if (namelen > 1
153 && (cstring_length (prefix) >= n + 1)
616915dd 154 && cstring_getChar (prefix, n + 1) == '*')
155 {
156 return TRUE;
157 }
158 else
159 {
160 return FALSE;
161 }
162 }
163
164 nc = (int) cstring_getChar (name, n);
165
166 if (!matchPrefixChar (nc, (int) pc))
167 {
168 return FALSE;
169 }
170 }
171
172 last = (int) pc;
173 n++;
174 } end_cstring_chars;
175
176 return TRUE;
177 }
178}
179
180static flagcode
181namespaceExcluded (flagcode code) /*@*/
182{
183 switch (code)
184 {
185 case FLG_MACROVARPREFIXEXCLUDE:
186 return (FLG_MACROVARPREFIX);
187 case FLG_TAGPREFIXEXCLUDE:
188 return (FLG_TAGPREFIX);
189 case FLG_ENUMPREFIXEXCLUDE:
190 return (FLG_ENUMPREFIX);
191 case FLG_FILESTATICPREFIXEXCLUDE:
192 return (FLG_FILESTATICPREFIX);
193 case FLG_GLOBPREFIXEXCLUDE:
194 return (FLG_GLOBPREFIX);
195 case FLG_TYPEPREFIXEXCLUDE:
196 return (FLG_TYPEPREFIX);
197 case FLG_EXTERNALPREFIXEXCLUDE:
198 return (FLG_EXTERNALPREFIX);
199 case FLG_UNCHECKEDMACROPREFIXEXCLUDE:
200 return (FLG_UNCHECKEDMACROPREFIX);
201 case FLG_LOCALPREFIXEXCLUDE:
202 return (FLG_LOCALPREFIX);
203 case FLG_ITERPREFIXEXCLUDE:
204 return (FLG_ITERPREFIX);
205 case FLG_CONSTPREFIXEXCLUDE:
206 return (FLG_CONSTPREFIX);
207 BADDEFAULT;
208 }
209}
210
211static /*@observer@*/ cstring
212namespaceName (flagcode flag) /*@*/
213{
214 switch (flag)
215 {
216 case FLG_MACROVARPREFIX:
217 return cstring_makeLiteralTemp ("macro variable");
218 case FLG_TAGPREFIX:
219 return cstring_makeLiteralTemp ("tag");
220 case FLG_ENUMPREFIX:
221 return cstring_makeLiteralTemp ("enum member");
222 case FLG_TYPEPREFIX:
223 return cstring_makeLiteralTemp ("user-defined type");
224 case FLG_FILESTATICPREFIX:
225 return cstring_makeLiteralTemp ("file static");
226 case FLG_GLOBPREFIX:
227 return cstring_makeLiteralTemp ("global variable");
228 case FLG_EXTERNALPREFIX:
229 return cstring_makeLiteralTemp ("external");
230 case FLG_LOCALPREFIX:
231 return cstring_makeLiteralTemp ("local variable");
232 case FLG_CONSTPREFIX:
233 return cstring_makeLiteralTemp ("constant");
234 case FLG_ITERPREFIX:
235 return cstring_makeLiteralTemp ("iter");
236 case FLG_UNCHECKEDMACROPREFIX:
237 return cstring_makeLiteralTemp ("unchecked macro");
238 BADDEFAULT;
239 }
240}
241
28bf4b0b 242void
616915dd 243checkPrefix (uentry ue)
244{
245 cstring name = cstring_undefined;
246 flagcode flag;
247
248 if (uentry_isExpandedMacro (ue))
249 {
250 flag = FLG_UNCHECKEDMACROPREFIX;
251 }
252 else if (uentry_isAnyTag (ue))
253 {
254 flag = FLG_TAGPREFIX;
255 }
256 else if (uentry_isEnumConstant (ue))
257 {
258 flag = FLG_ENUMPREFIX;
259 }
260 else if (uentry_isDatatype (ue))
261 {
262 flag = FLG_TYPEPREFIX;
263 }
264 else if (uentry_isFileStatic (ue))
265 {
266 flag = FLG_FILESTATICPREFIX;
267 }
28bf4b0b 268 else if (uentry_isGlobalVariable (ue))
616915dd 269 {
270 flag = FLG_GLOBPREFIX;
271 }
272 else if (uentry_isVariable (ue))
273 {
274 if (uentry_isRefParam (ue))
275 {
276 return; /* already checked param */
277 }
278
279 if (context_inMacro ())
280 {
281 if (uentry_isAnyParam (ue))
282 {
283 if (uentry_isYield (ue))
284 {
285 flag = FLG_MACROVARPREFIX;
286 }
287 else
288 {
289 flag = FLG_LOCALPREFIX;
290 }
291 }
292 else
293 {
294 flag = FLG_MACROVARPREFIX;
295 }
296 }
297 else
298 {
299 flag = FLG_LOCALPREFIX;
300 }
301 }
302 else if (uentry_isConstant (ue))
303 {
304 flag = FLG_CONSTPREFIX;
305 }
306 else if (uentry_isIter (ue))
307 {
308 flag = FLG_ITERPREFIX;
309 }
310 else if (uentry_isExported (ue))
311 {
312 flag = FLG_EXTERNALPREFIX;
313 }
314 else
315 {
316 llcontbug (message ("What is it: %q", uentry_unparseFull (ue)));
317 return;
318 }
319
320 if (flag == FLG_TYPEPREFIX || flag == FLG_GLOBPREFIX
321 || flag == FLG_ENUMPREFIX || flag == FLG_CONSTPREFIX)
322 {
323 if (flag == FLG_ENUMPREFIX)
324 {
325 if (!context_getFlag (flag))
326 {
327 flag = FLG_CONSTPREFIX;
328 }
329 }
330
331 if (!context_getFlag (flag))
332 {
333 flag = FLG_EXTERNALPREFIX;
334 }
335 }
336
337 if (context_getFlag (flag))
338 {
28bf4b0b 339 name = uentry_observeRealName (ue);
616915dd 340
341 if (!matchPrefix (name, context_getString (flag)))
342 {
343 if (optgenerror
344 (flag,
345 message ("%s %s name is not consistent with %s "
346 "namespace prefix \"%s\"",
347 uentry_ekindName (ue),
348 name,
349 namespaceName (flag),
350 context_getString (flag)),
351 uentry_whereLast (ue)))
352 {
353 uentry_setHasNameError (ue);
354 }
355 }
356 }
357
358 excludeFlagCodes (code)
359 {
360 bool check = FALSE;
361
362 if (context_getFlag (code))
363 {
364 /*@-loopswitchbreak@*/
365 switch (code)
366 {
367 case FLG_MACROVARPREFIXEXCLUDE:
368 check = (flag != FLG_MACROVARPREFIX);
369 break;
370 case FLG_TAGPREFIXEXCLUDE:
371 check = (flag != FLG_TAGPREFIX);
372 break;
373 case FLG_ENUMPREFIXEXCLUDE:
374 check = (flag != FLG_ENUMPREFIX);
375 break;
376 case FLG_FILESTATICPREFIXEXCLUDE:
377 check = (flag != FLG_FILESTATICPREFIX);
378 break;
379 case FLG_GLOBPREFIXEXCLUDE:
380 check = (flag != FLG_GLOBPREFIX);
381 break;
382 case FLG_TYPEPREFIXEXCLUDE:
383 check = (flag != FLG_TYPEPREFIX);
384 break;
385 case FLG_EXTERNALPREFIXEXCLUDE:
386 check = (flag != FLG_EXTERNALPREFIX
387 && flag != FLG_GLOBPREFIX
388 && flag != FLG_TYPEPREFIX
389 && flag != FLG_UNCHECKEDMACROPREFIX);
390 break;
391 case FLG_UNCHECKEDMACROPREFIXEXCLUDE:
392 check = (flag != FLG_UNCHECKEDMACROPREFIX);
393 break;
394 case FLG_LOCALPREFIXEXCLUDE:
395 check = (flag != FLG_LOCALPREFIX);
396 break;
397 case FLG_CONSTPREFIXEXCLUDE:
398 check = (flag != FLG_CONSTPREFIX);
399 break;
400 case FLG_ITERPREFIXEXCLUDE:
401 check = (flag != FLG_ITERPREFIX);
402 break;
403 BADDEFAULT;
404 }
405 /*@=loopswitchbreak@*/
406
407 if (check)
408 {
409 flagcode rcode = namespaceExcluded (code);
410 cstring pstring = context_getString (rcode);
411
412 if (cstring_isDefined (pstring))
413 {
414 if (cstring_isUndefined (name))
415 {
28bf4b0b 416 name = uentry_observeRealName (ue);
616915dd 417 }
418
419 if (matchPrefix (name, context_getString (rcode)))
420 {
421 if (optgenerror
422 (code,
423 message
424 ("%s %s name is not a %s (it is a %s), "
425 "but matches the %s "
426 "namespace prefix \"%s\"",
427 uentry_ekindName (ue),
428 name,
429 namespaceName (rcode),
430 namespaceName (flag),
431 namespaceName (rcode),
432 context_getString (rcode)),
433 uentry_whereLast (ue)))
434 {
435 uentry_setHasNameError (ue);
436 }
437 }
438 }
439 }
440 }
441 } end_excludeFlagCodes ;
616915dd 442}
443
444static void
445checkNationalName (uentry ue)
446{
447 flagcode czechflag;
448 flagcode slovakflag;
449 flagcode czechoslovakflag;
450 bool gcf, gsf, gcsf;
451
452
453 if (uentry_isFunction (ue)
454 || uentry_isIter (ue)
455 || uentry_isEndIter (ue))
456 {
457 czechflag = FLG_CZECHFUNCTIONS;
458 slovakflag = FLG_SLOVAKFUNCTIONS;
459 czechoslovakflag = FLG_CZECHOSLOVAKFUNCTIONS;
460 }
461 else if (uentry_isExpandedMacro (ue))
462 {
463 czechflag = FLG_CZECHMACROS;
464 slovakflag = FLG_SLOVAKMACROS;
465 czechoslovakflag = FLG_CZECHOSLOVAKMACROS;
466 }
467 else if (uentry_isVariable (ue))
468 {
28bf4b0b 469 if (uentry_isGlobalVariable (ue) && context_getFlag (FLG_GLOBPREFIX))
616915dd 470 {
471 /* prefix checks supercede national naming checks */
472 return;
473 }
474
475 czechflag = FLG_CZECHVARS;
476 slovakflag = FLG_SLOVAKVARS;
477 czechoslovakflag = FLG_CZECHOSLOVAKVARS;
478 }
479 else if (uentry_isConstant (ue))
480 {
28bf4b0b 481 if (uentry_isGlobalVariable (ue) && context_getFlag (FLG_CONSTPREFIX))
616915dd 482 {
483 /* prefix checks supercede national naming checks */
484 return;
485 }
486
487 czechflag = FLG_CZECHCONSTANTS;
488 slovakflag = FLG_SLOVAKCONSTANTS;
489 czechoslovakflag = FLG_CZECHOSLOVAKCONSTANTS;
490 }
491 else
492 {
493 if (uentry_isAnyTag (ue) || uentry_isEnumConstant (ue))
494 {
495 return; /* no errors for tags */
496 }
497
498 llassert (uentry_isDatatype (ue));
499
500 czechflag = FLG_CZECHTYPES;
501 slovakflag = FLG_SLOVAKTYPES;
502 czechoslovakflag = FLG_CZECHOSLOVAKTYPES;
503 }
504
505 gcf = context_getFlag (czechflag);
506 gsf = context_getFlag (slovakflag);
507 gcsf = context_getFlag (czechoslovakflag);
508
509 if (gcf || (uentry_isFunction (ue)
510 && context_getFlag (FLG_ACCESSCZECH)))
511 {
512 (void) checkCzechName (ue, czechflag, gcf);
513 }
514
515 if (gsf || (uentry_isFunction (ue)
516 && context_getFlag (FLG_ACCESSSLOVAK)))
517 {
518 (void) checkSlovakName (ue, slovakflag, gsf);
519 }
520
521 if (gcsf)
522 {
523 if (uentry_isDatatype (ue))
524 {
525 /* May not have either _'s or uppercase letter */
526 cstring name = uentry_rawName (ue);
527 int charno = 1;
528
529 cstring_chars (name, c)
530 {
531 if (isupper ((unsigned char) c))
532 {
533 if (optgenerror
534 (FLG_CZECHOSLOVAKTYPES,
535 message
536 ("%s %q name violates Czechoslovak naming convention. "
537 "Czechoslovak datatype names should not use uppercase "
538 "letters.",
539 uentry_ekindName (ue),
540 uentry_getName (ue)),
541 uentry_whereLast (ue)))
542 {
543 uentry_setHasNameError (ue);
544 }
545 break;
546 }
547
548 if (c == '_' && charno != 2 && charno != 3)
549 {
550 if (optgenerror
551 (FLG_CZECHOSLOVAKTYPES,
552 message ("%s %q name violates Czechoslovak naming "
553 "convention. Czechoslovak datatype names "
554 "should not use the _ charater.",
555 uentry_ekindName (ue),
556 uentry_getName (ue)),
557 uentry_whereLast (ue)))
558 {
559 uentry_setHasNameError (ue);
560 }
561 break;
562 }
563
564 charno++;
565 } end_cstring_chars;
566 }
567 else
568 {
569 bool okay = checkCzechName (ue, czechflag, FALSE);
570
571 /* still need to call, to set access */
572 okay |= checkSlovakName (ue, slovakflag, FALSE);
573
574 if (!okay)
575 {
576 if (optgenerror
577 (czechoslovakflag,
578 message ("%s %q name is not consistent with Czechoslovak "
579 "naming convention.",
580 uentry_ekindName (ue),
581 uentry_getName (ue)),
582 uentry_whereLast (ue)))
583 {
584 uentry_setHasNameError (ue);
585 }
586 }
587 }
588 }
589}
590
591static bool checkCzechName (uentry ue, flagcode czechflag, bool report)
592{
593 if (uentry_isDatatype (ue))
594 {
595 /*
596 ** Czech datatypes may not have _'s, except if there are 1 or 2 characters
597 ** before the only _.
598 */
599
600 cstring name = uentry_rawName (ue);
601 int charno = 1;
602
603 cstring_chars (name, c)
604 {
605 if (c == '_' && charno != 2 && charno != 3)
606 {
607 if (report)
608 {
609 if (optgenerror
610 (FLG_CZECHTYPES,
611 message
612 ("%s %q name violates Czech naming convention. "
613 "Czech datatype names should not use the _ charater.",
614 uentry_ekindName (ue),
615 uentry_getName (ue)),
616 uentry_whereLast (ue)))
617 {
618 uentry_setHasNameError (ue);
619 }
620 }
621
622 return FALSE;
623 }
624
625 charno++;
626 } end_cstring_chars;
627 }
628 else
629 {
630 typeIdSet acc = context_fileAccessTypes ();
631 cstring pfx = czechPrefix (uentry_rawName (ue));
632
633 if (cstring_isEmpty (pfx))
634 {
635 if (uentry_isVariable (ue) || uentry_isConstant (ue))
636 {
637 ctype ct = uentry_getType (ue);
638
639 if (ctype_isAbstract (ct)
640 && context_hasAccess (ctype_typeId (ct)))
641 {
642 if (report)
643 {
644 if (optgenerror
645 (czechflag,
646 message ("%s %q name is not consistent with Czech "
647 "naming convention. The name should "
648 "begin with %s_",
649 uentry_ekindName (ue),
650 uentry_getName (ue),
651 ctype_unparse (ct)),
652 uentry_whereLast (ue)))
653 {
654 uentry_setHasNameError (ue);
655 }
656 }
657
658 cstring_free (pfx);
659 return FALSE;
660 }
661 }
662 else if (uentry_isFunction (ue) || uentry_isIter (ue))
663 {
664 if (typeIdSet_isEmpty (acc))
665 {
666 ; /* okay - should not be czech name */
667 }
668 else
669 {
670 if (report)
671 {
672 if (optgenerror
673 (czechflag,
674 message ("%s %q name is not consistent with Czech "
675 "naming convention. Accessible types: %q",
676 uentry_ekindName (ue),
677 uentry_getName (ue),
678 typeIdSet_unparse (acc)),
679 uentry_whereLast (ue)))
680 {
681 uentry_setHasNameError (ue);
682 }
683 }
684
685 cstring_free (pfx);
686 return FALSE;
687 }
688 }
689 else
690 {
691 ;
692 }
693 }
694 else
695 {
696 if (usymtab_existsTypeEither (pfx))
697 {
698 ctype ct = usymtab_lookupAbstractType (pfx);
699 typeId tid;
700
701 if (ctype_isUA (ct))
702 {
703 tid = ctype_typeId (ct);
704
705 if (ctype_isUser (ct) || context_hasAccess (tid))
706 {
707 ;
708 }
709 else
710 {
711 if (context_getFlag (FLG_ACCESSCZECH)
712 || context_getFlag (FLG_ACCESSCZECHOSLOVAK))
713 {
714 if (!uentry_isVar (ue))
715 {
716 uentry_addAccessType (ue, tid);
717 }
718 }
719 else
720 {
721 if (report)
722 {
723 if (llgenhinterror
724 (czechflag,
725 message
726 ("%s %q name violates Czech naming "
727 "convention. Czech prefix %s names "
728 "an abstract type that is "
729 "not accessible.",
730 uentry_ekindName (ue),
731 uentry_getName (ue),
732 pfx),
733 cstring_makeLiteral
734 ("Use +accessczech to allow access to "
735 "type <t> in functions "
736 "named <t>_<name>."),
737 uentry_whereLast (ue)))
738 {
739 uentry_setHasNameError (ue);
740 }
741 }
742
743 cstring_free (pfx);
744 return FALSE;
745 }
746 }
747 }
748 else if (ctype_isManifestBool (ct))
749 {
750 if (context_canAccessBool ())
751 {
752 ;
753 }
754 else
755 {
756 if (context_getFlag (FLG_ACCESSCZECH)
757 || context_getFlag (FLG_ACCESSCZECHOSLOVAK))
758 {
759 if (!uentry_isVar (ue))
760 {
761 tid = usymtab_getTypeId (context_getBoolName ());
762 uentry_addAccessType (ue, tid);
763 }
764 }
765 else
766 {
767 if (report)
768 {
769 if (llgenhinterror
770 (czechflag,
771 message
772 ("%s %q name violates Czech naming "
773 "convention. Type bool is not accessible.",
774 uentry_ekindName (ue),
775 uentry_getName (ue)),
776 cstring_makeLiteral
777 ("Use +accessczech to allow access to "
778 "type <t> in functions named <t>_<name>."),
779 uentry_whereLast (ue)))
780 {
781 uentry_setHasNameError (ue);
782 }
783 }
784
785 cstring_free (pfx);
786 return FALSE;
787 }
788 }
789 }
790 else
791 {
792 ;
793 }
794 }
795 else
796 {
797 if (cstring_equalLit (pfx, "int")
798 || cstring_equalLit (pfx, "char")
799 || cstring_equalLit (pfx, "short")
800 || cstring_equalLit (pfx, "long")
801 || cstring_equalLit (pfx, "unsigned")
802 || cstring_equalLit (pfx, "signed")
803 || cstring_equalLit (pfx, "float")
804 || cstring_equalLit (pfx, "double"))
805 {
806 ; /* built-in types */
807 }
808 else
809 {
810 /* no accessible types, could match module name */
811
812 if (cstring_equal (pfx, context_moduleName ()))
813 {
814 ;
815 }
816 else
817 {
818 if (report)
819 {
820 if (optgenerror
821 (czechflag,
822 message
823 ("%s %q name violates Czech naming convention. "
824 "Czech prefix %s is not the name of a type.",
825 uentry_ekindName (ue),
826 uentry_getName (ue),
827 pfx),
828 uentry_whereLast (ue)))
829 {
830 uentry_setHasNameError (ue);
831 }
832 }
833
834 cstring_free (pfx);
835 return FALSE;
836 }
837 }
838 }
839 }
840 cstring_free (pfx);
841 }
842
843 return TRUE;
844}
845
846static bool checkSlovakName (uentry ue, flagcode slovakflag, bool report)
847{
848 if (uentry_isDatatype (ue))
849 {
850 /*
851 ** Slovak datatypes may not have uppercase letters.
852 */
853
854 if (context_getFlag (FLG_SLOVAK))
855 {
856 cstring name = uentry_rawName (ue);
857
858 cstring_chars (name, c)
859 {
860 if (isupper ((unsigned char) c))
861 {
862 if (report)
863 {
864 if (optgenerror
865 (FLG_SLOVAKTYPES,
866 message
867 ("%s %q name violates Slovak naming convention. "
868 "Slovak datatype names should not use uppercase "
869 "letters.",
870 uentry_ekindName (ue),
871 uentry_getName (ue)),
872 uentry_whereLast (ue)))
873 {
874 uentry_setHasNameError (ue);
875 }
876 }
877 return FALSE;
878 }
879 } end_cstring_chars;
880 }
881 }
882 else
883 {
884 typeIdSet acc = context_fileAccessTypes ();
885 cstring pfx = slovakPrefix (uentry_rawName (ue));
886
887 if (cstring_isEmpty (pfx))
888 {
889 if (typeIdSet_isEmpty (acc))
890 {
891 ; /* okay - should not be slovak name */
892 }
893 else
894 {
895 if (uentry_isFunction (ue))
896 {
897 if (report)
898 {
899 if (optgenerror
900 (slovakflag,
901 message ("%s %q name is not consistent with Slovak "
902 "naming convention. Accessible types: %q",
903 uentry_ekindName (ue),
904 uentry_getName (ue),
905 typeIdSet_unparse (acc)),
906 uentry_whereLast (ue)))
907 {
908 uentry_setHasNameError (ue);
909 }
910 }
911
912 cstring_free (pfx);
913 return FALSE;
914 }
915 else
916 {
917 ctype ct = uentry_getType (ue);
918
919 if (ctype_isUA (ct))
920 {
921 if (report)
922 {
923 if (optgenerror
924 (slovakflag,
925 message ("%s %q name is not consistent with "
926 "Slovak naming convention. The "
927 "name should begin with %s followed "
928 "by an uppercase letter.",
929 uentry_ekindName (ue),
930 uentry_getName (ue),
931 ctype_unparse (ct)),
932 uentry_whereLast (ue)))
933 {
934 uentry_setHasNameError (ue);
935 }
936 }
937
938 cstring_free (pfx);
939 return FALSE;
940 }
941 }
942 }
943 }
944 else
945 {
946 if (usymtab_existsTypeEither (pfx))
947 {
948 ctype ct = usymtab_lookupAbstractType (pfx);
949 typeId tid;
950
951 if (ctype_isUA (ct))
952 {
953 tid = ctype_typeId (ct);
954
955 if (ctype_isUser (ct) || context_hasAccess (tid))
956 {
957 ;
958 }
959 else
960 {
961 if (context_getFlag (FLG_ACCESSSLOVAK)
962 || context_getFlag (FLG_ACCESSCZECHOSLOVAK))
963 {
964 if (!uentry_isVar (ue))
965 {
966 uentry_addAccessType (ue, tid);
967 }
968 }
969 else
970 {
971 if (report)
972 {
973 if (llgenhinterror
974 (slovakflag,
975 message
976 ("%s %q name violates Slovak naming "
977 "convention. Slovak prefix %s names "
978 "an abstract type that is not accessible.",
979 uentry_ekindName (ue),
980 uentry_getName (ue),
981 pfx),
982 cstring_makeLiteral
983 ("Use +accessslovak to allow access to "
984 "type <t> in functions named <t>_<name>."),
985 uentry_whereLast (ue)))
986 {
987 uentry_setHasNameError (ue);
988 }
989 }
990
991 cstring_free (pfx);
992 return FALSE;
993 }
994 }
995 }
996 else if (ctype_isManifestBool (ct))
997 {
998 if (context_canAccessBool ())
999 {
1000 ;
1001 }
1002 else
1003 {
1004 if (context_getFlag (FLG_ACCESSSLOVAK)
1005 || context_getFlag (FLG_ACCESSCZECHOSLOVAK))
1006 {
1007 if (!uentry_isVar (ue))
1008 {
1009 tid = usymtab_getTypeId (context_getBoolName ());
1010 uentry_addAccessType (ue, tid);
1011 }
1012 }
1013 else
1014 {
1015 if (report)
1016 {
1017 if (llgenhinterror
1018 (slovakflag,
1019 message
1020 ("%s %q name violates Slovak naming convention. "
1021 "Type bool is not accessible.",
1022 uentry_ekindName (ue),
1023 uentry_getName (ue)),
1024 cstring_makeLiteral
1025 ("Use +accessslovak to allow access to "
1026 "type <t> in functions named <t>_<name>."),
1027 uentry_whereLast (ue)))
1028 {
1029 uentry_setHasNameError (ue);
1030 }
1031 }
1032
1033 cstring_free (pfx);
1034 return FALSE;
1035 }
1036 }
1037 }
1038 else
1039 {
1040 ;
1041 }
1042 }
1043 else
1044 {
1045 if (cstring_equalLit (pfx, "int")
1046 || cstring_equalLit (pfx, "char")
1047 || cstring_equalLit (pfx, "short")
1048 || cstring_equalLit (pfx, "long")
1049 || cstring_equalLit (pfx, "unsigned")
1050 || cstring_equalLit (pfx, "signed")
1051 || cstring_equalLit (pfx, "float")
1052 || cstring_equalLit (pfx, "double"))
1053 {
1054 ; /* built-in types */
1055 }
1056 else
1057 {
1058 /* no accessible types, could match module name */
1059
1060 if (cstring_equal (pfx, context_moduleName ()))
1061 {
1062 ;
1063 }
1064 else
1065 {
1066 if (report)
1067 {
1068 if (optgenerror
1069 (slovakflag,
1070 message
1071 ("%s %q name violates Slovak naming convention. "
1072 "Slovak prefix %s is not the name of a type.",
1073 uentry_ekindName (ue),
1074 uentry_getName (ue),
1075 pfx),
1076 uentry_whereLast (ue)))
1077 {
1078 uentry_setHasNameError (ue);
1079 }
1080 }
1081
1082 cstring_free (pfx);
1083 return FALSE;
1084 }
1085 }
1086 }
1087 }
1088
1089 cstring_free (pfx);
1090 }
1091
1092 return TRUE;
1093}
1094
1095void
28bf4b0b 1096checkExternalName (uentry ue)
616915dd 1097{
1098 if (!uentry_isStatic (ue) && uentry_hasName (ue))
1099 {
1100 checkNationalName (ue);
1101 }
1102 else
1103 {
1104 ;
1105 }
1106}
1107
1108void
1109checkLocalName (/*@unused@*/ uentry ue)
1110{
28bf4b0b 1111 /*
1112 ** No local checks (yet)
1113 */
1114
1115 return;
1116}
1117
1118void
1119checkFileScopeName (/*@unused@*/ uentry ue)
1120{
1121 /*
1122 ** No file scope checks (yet)
1123 */
1124
1125 /*@i423 add a file scope naming convention policy? */
1126
1127 return;
616915dd 1128}
1129
1130/*
1131** Checks a name used by user source is not reserved by ANSI
1132** (or for future library functions).
1133**
1134** The restrictions are described in X3.159-1989: 4.13
1135*/
1136
1137/*@constant int NRESERVEDNAMES; @*/
1138# define NRESERVEDNAMES 201
1139
1140/*@constant int NCPPNAMES@*/
1141# define NCPPNAMES 39
1142
28bf4b0b 1143void
1144checkCppName (uentry ue)
616915dd 1145{
28bf4b0b 1146 cstring name = uentry_observeRealName (ue);
1147
616915dd 1148 static ob_mstring cppNames[NCPPNAMES] =
1149 {
1150 "and", "and_eq", "asm",
1151 "bitand", "bitor", "bool", /* gasp: "bool", is special for lclint */
1152 "catch", "class", "compl", "const_class",
1153 "delete", "dynamic_cast", "false", "friend",
1154 "inline", "mutable", "namespace", "new",
1155 "not", "not_eq",
1156 "operator", "or", "or_eq", "overload",
1157 "private", "protected", "public",
1158 "reinterpret_cast", "static_cast",
1159 "template", "this", "throw", "true", "try",
1160 "typeid", "using", "virtual", "xor", "xor_eq"
1161 } ;
1162
1163 if (cstring_isDefined (cstring_bsearch (name, &cppNames[0],
1164 NCPPNAMES)))
1165 {
28bf4b0b 1166 if (optgenerror
1167 (FLG_CPPNAMES,
1168 message ("Name %s is a keyword or reserved word in C++",
1169 name),
1170 uentry_whereLast (ue)))
1171 {
1172 uentry_setHasNameError (ue);
1173 }
616915dd 1174 }
616915dd 1175}
1176
28bf4b0b 1177void
1178checkAnsiName (uentry ue)
616915dd 1179{
1180 bool hasError = FALSE;
28bf4b0b 1181 cstring name = uentry_observeRealName (ue);
616915dd 1182 int length = cstring_length (name);
1183 char fchar = (length >= 1) ? cstring_firstChar (name) : '\0';
1184 char schar = (length >= 2) ? cstring_secondChar (name) : '\0';
1185 char tchar = (length >= 3) ? cstring_getChar (name, 3) : '\0';
1186 char rchar = (length >= 4) ? cstring_getChar (name, 4) : '\0';
1187
1188 /*
1189 ** reservedNames
1190 ** taken from Linden, "Expert C Programming", p. 126-8.
1191 ** invariant: must be sorted (case-insensitive, lexicographically)
1192 ** must end with NULL
1193 */
1194
1195 static ob_mstring reservedNames[NRESERVEDNAMES] =
1196 {
1197# include "reservedNames.nf"
1198 } ;
1199
616915dd 1200# if 0
28bf4b0b 1201 /*
1202 ** This code is for checking reservedNames.nf
1203 */
1204
616915dd 1205 {
1206 int i = 0;
1207 char *lastname = NULL;
1208 char *name;
1209
1210 while ((name = reservedNames[i]) != NULL)
1211 {
1212 llassertprint (lastname == NULL
1213 || strcmp (name, lastname) > 0,
1214 ("%s / %s", lastname, name));
1215 lastname = name;
1216 i++;
1217 }
1218
1219 nreservedNames = i - 1;
1220 }
1221# endif
28bf4b0b 1222
1223 if (fileloc_isSystemFile (uentry_whereLast (ue)) || fileloc_isBuiltin (uentry_whereLast (ue)))
1224 {
1225 return; /* no errors for system files */
1226 }
616915dd 1227
1228 if (cstring_isDefined (cstring_bsearch (name, &reservedNames[0],
1229 NRESERVEDNAMES)))
1230 {
28bf4b0b 1231 hasError |= optgenerror
1232 (FLG_ANSIRESERVED,
1233 message ("Name %s is reserved for the standard library",
1234 name),
1235 uentry_whereLast (ue));
616915dd 1236 }
1237
28bf4b0b 1238 if (uentry_isFileStatic (ue) || uentry_isVisibleExternally (ue) || uentry_isAnyTag (ue)
1239 || context_getFlag (FLG_ANSIRESERVEDLOCAL))
616915dd 1240 {
28bf4b0b 1241 if (fchar == '_')
1242 {
1243 hasError |= optgenerror
1244 (FLG_ANSIRESERVED,
1245 message
1246 ("Name %s is in the implementation name space (any identifier "
1247 "beginning with underscore)",
1248 name),
1249 uentry_whereLast (ue));
1250 }
1251 }
1252 else
1253 {
1254 /*
1255 ** ISO 7.1.3:
1256 ** - All identifiers that begin with an underscore and either an uppercase
1257 ** letter or another underscore are always reserved for any use.
1258 */
1259
1260 if (fchar == '_'
1261 && (schar == '_' || isupper ((int) schar)))
1262 {
1263 hasError |= optgenerror
1264 (FLG_ANSIRESERVED,
1265 message
1266 ("Name %s is in the implementation name space (any identifier "
1267 "beginning with underscore and either an uppercase letter or "
1268 "another underscore is always reserved for any use)",
1269 name),
1270 uentry_whereLast (ue));
1271 }
616915dd 1272 }
1273
1274 /*
1275 ** 4.13.1 Errors <errno.h>
1276 **
1277 ** Macros that begin with E and a digit or E and an uppercase letter ...
1278 */
28bf4b0b 1279
1280 if (fchar == 'E' && (isdigit ((int) schar)
1281 || isupper ((int) schar)))
616915dd 1282 {
28bf4b0b 1283 hasError |= optgenerror
616915dd 1284 (FLG_ANSIRESERVED,
1285 message
1286 ("Name %s is reserved for future ANSI library extensions. "
1287 "Macros beginning with E and a digit or uppercase letter "
1288 "may be added to <errno.h>. (See ANSI, Section 4.13.1)",
1289 name),
28bf4b0b 1290 uentry_whereLast (ue));
616915dd 1291 }
616915dd 1292
616915dd 1293 /*
1294 ** 4.13.3 Localization <locale.h>
1295 **
1296 ** Macros that begin with LC_ and an uppercase letter ...
1297 */
28bf4b0b 1298
1299 if (length >= 4
1300 && ((fchar == 'L')
1301 && (schar == 'C')
1302 && (tchar == '_'))
1303 && (isupper ((int) rchar)))
616915dd 1304 {
28bf4b0b 1305 hasError |= optgenerror
616915dd 1306 (FLG_ANSIRESERVED,
1307 message
1308 ("Name %s is reserved for future ANSI library extensions. "
1309 "Macros beginning with \"LC_\" and an uppercase letter may "
1310 "be added to <locale.h>. (See ANSI, Section 4.13.3)",
1311 name),
28bf4b0b 1312 uentry_whereLast (ue));
616915dd 1313 }
616915dd 1314
616915dd 1315 /*
1316 ** 4.13.5 Signal Handling <signal.h>
1317 **
1318 ** Macros that begin with either SIG or SIG_ and an uppercase letter or...
1319 */
28bf4b0b 1320
1321 if (fchar == 'S' && schar == 'I' && tchar == 'G'
616915dd 1322 && ((rchar == '_' && ((length >= 5
1323 && isupper ((int) cstring_getChar (name, 5)))))
1324 || (isupper ((int) rchar))))
1325 {
28bf4b0b 1326 hasError |= optgenerror
616915dd 1327 (FLG_ANSIRESERVED,
1328 message
1329 ("Name %s is reserved for future ANSI library extensions. "
1330 "Macros that begin with SIG and an uppercase letter or SIG_ "
1331 "and an uppercase letter may be added to "
28bf4b0b 1332 "<signal.h>. (See ISO99 7.14 or ANSI 4.13.5)",
616915dd 1333 name),
28bf4b0b 1334 uentry_whereLast (ue));
616915dd 1335 }
616915dd 1336
28bf4b0b 1337 DPRINTF (("Here..."));
616915dd 1338
28bf4b0b 1339 if ((uentry_isVisibleExternally (ue) && !uentry_isAnyTag (ue))
1340 || context_getFlag (FLG_ANSIRESERVEDLOCAL))
616915dd 1341 {
28bf4b0b 1342 flagcode flg;
616915dd 1343
28bf4b0b 1344 DPRINTF (("Okay...: %s", uentry_unparse (ue)));
1345
1346 if (uentry_isVisibleExternally (ue) && !uentry_isAnyTag (ue))
1347 {
1348 flg = FLG_ANSIRESERVED;
1349 }
1350 else
1351 {
1352 flg = FLG_ANSIRESERVEDLOCAL;
1353 }
1354
1355 /*
1356 ** These restrictions only apply to identifiers with global linkage.
1357 */
1358
1359 /*
1360 ** 4.13.2 Character Handling <ctype.h>
1361 **
1362 ** Function names that begin with either "is" or "to" and a lowercase letter ...
1363 */
1364
1365 if (((fchar == 'i' && schar == 's')
1366 || (fchar == 't' && schar == 'o'))
1367 && (islower ((int) tchar)))
1368 {
1369 hasError |= optgenerror
1370 (flg,
1371 message
1372 ("Name %s is reserved for future ANSI library extensions. "
1373 "Functions beginning with \"is\" or \"to\" and a lowercase "
1374 "letter may be added to <ctype.h>. (See ANSI, Section 4.13.2)",
1375 name),
1376 uentry_whereLast (ue));
1377
1378 DPRINTF (("Externally visible: %s / %s",
1379 uentry_unparseFull (ue),
1380 bool_unparse (uentry_isVisibleExternally (ue))));
1381 }
1382
1383
1384 /*
1385 ** 4.13.4 Mathematics <math.h>
1386 **
1387 ** The names of all existing functions declared in the <math.h> header,
1388 ** suffixed with f or l...
1389 */
1390
1391 DPRINTF (("Check name: %s", name));
1392
1393 if ((cstring_lastChar (name) == 'f' || cstring_lastChar (name) == 'l')
1394 &&
1395 (((length == 4)
1396 && ((cstring_equalPrefix (name, "cos") ||
1397 cstring_equalPrefix (name, "sin") ||
1398 cstring_equalPrefix (name, "tan") ||
1399 cstring_equalPrefix (name, "exp") ||
1400 cstring_equalPrefix (name, "log") ||
1401 cstring_equalPrefix (name, "pow"))))
1402 || ((length == 5)
1403 && ((cstring_equalPrefix (name, "acos") ||
1404 cstring_equalPrefix (name, "asin") ||
1405 cstring_equalPrefix (name, "atan") ||
1406 cstring_equalPrefix (name, "cosh") ||
1407 cstring_equalPrefix (name, "sinh") ||
1408 cstring_equalPrefix (name, "sqrt") ||
1409 cstring_equalPrefix (name, "ceil") ||
1410 cstring_equalPrefix (name, "fabs") ||
1411 cstring_equalPrefix (name, "fmod") ||
1412 cstring_equalPrefix (name, "tanh") ||
1413 cstring_equalPrefix (name, "modf"))))
1414 || ((length == 6)
1415 && ((cstring_equalPrefix (name, "atan2") ||
1416 cstring_equalPrefix (name, "floor") ||
1417 cstring_equalPrefix (name, "frexp") ||
1418 cstring_equalPrefix (name, "ldexp") ||
1419 cstring_equalPrefix (name, "log10"))))))
1420 {
1421 hasError |= optgenerror
1422 (flg,
1423 message
1424 ("Name %s is reserved for future ANSI library extensions. "
1425 "The names of all existing functions in <math.h> suffixed "
1426 "with 'f' or 'l' may be added to <math.h>. (See ANSI, Section 4.13.4)",
1427 name),
1428 uentry_whereLast (ue));
1429 }
1430
1431 /*
1432 ** 4.13.6 Input/Output <stdio.h>
1433 **
1434 ** (nothing to check)
1435 */
1436
1437 /*
1438 ** 4.13.7 General Utilities <stdlib.h>
1439 **
1440 ** Functions names that begin with str and a lowercase letter may be added to <stdlib.h>.
1441 */
1442
1443 if (fchar == 's' && schar == 't' && tchar == 'r'
1444 && (islower ((int) rchar)))
1445 {
1446 hasError |= optgenerror
1447 (flg,
1448 message
1449 ("Name %s is reserved for future ANSI library extensions. "
1450 "Functions that begin with \"str\" and a lowercase letter "
1451 "may be added to <stdlib.h> or <string.h>. (See ANSI, Section 4.13.7)",
1452 name),
1453 uentry_whereLast (ue));
1454 }
1455
1456 /*
1457 ** 4.13.8 String Handling <string.h>
1458 **
1459 ** Function names that begin with str, mem, or wcs and a lowercase letter ...
1460 **
1461 ** (Note: already checked "str" above.)
1462 */
1463
1464 if (((fchar == 'm' && schar == 'e' && tchar == 'm')
1465 || (fchar == 'w' && schar == 'c' && tchar == 's'))
1466 && (islower ((int) rchar)))
1467 {
1468 hasError |= optgenerror
1469 (flg,
1470 message
1471 ("Name %s is reserved for future ANSI library extensions. "
1472 "Functions that begin with \"mem\" or \"wcs\" and a "
1473 "lowercase letter letter may be added to <string.h>. (See ANSI, Section 4.13.8)",
1474 name),
1475 uentry_whereLast (ue));
1476 }
616915dd 1477 }
1478 else
1479 {
28bf4b0b 1480 DPRINTF (("Not checked: [%s] %s", bool_unparse (uentry_isVisibleExternally (ue)),
1481 uentry_unparseFull (ue)));
616915dd 1482 }
1483
28bf4b0b 1484 if (hasError)
1485 {
1486 uentry_setHasNameError (ue);
1487 }
616915dd 1488}
1489
1490void checkParamNames (uentry ue)
1491{
1492 cstring fpfx = context_getString (FLG_DECLPARAMPREFIX);
1493 bool noformal = context_getFlag (FLG_DECLPARAMNAME);
1494
1495 llassert (uentry_isFunction (ue));
1496
1497 if (cstring_isDefined (fpfx) || noformal)
1498 {
1499 uentryList params = uentry_getParams (ue);
1500
1501 uentryList_elements (params, p)
1502 {
1503 if (uentry_hasName (p))
1504 {
1505 if (noformal && !cstring_isDefined (fpfx))
1506 {
1507 if (optgenerror
1508 (FLG_DECLPARAMNAME,
1509 message ("Declaration parameter has name: %q",
1510 uentry_getName (p)),
1511 uentry_whereLast (p)))
1512 {
1513 uentry_setHasNameError (p);
1514 }
1515 }
1516 else
1517 {
28bf4b0b 1518 cstring pname = uentry_observeRealName (p);
616915dd 1519
1520 if (!cstring_equalPrefix (pname, cstring_toCharsSafe (fpfx)))
1521 {
1522 if (context_getFlag (FLG_NAMECHECKS))
1523 {
1524 if (optgenerror
1525 (FLG_DECLPARAMPREFIX,
1526 message ("Declaration parameter name %s does not begin "
1527 "with protoparamprefix (%s)",
1528 pname, fpfx),
1529 uentry_whereLast (p)))
1530 {
1531 uentry_setHasNameError (p);
1532 }
1533 }
1534 }
616915dd 1535 }
1536 }
1537 } end_uentryList_elements ;
1538 }
1539}
1540
1541
1542
1543
This page took 0.248349 seconds and 5 git commands to generate.