2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 University of Virginia,
4 ** Massachusetts Institute of Technology
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.
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.
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.
20 ** For information on splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
28 # include "splintMacros.nf"
30 # include "nameChecks.h"
32 static bool checkCzechName (uentry p_ue
, flagcode p_czechflag
, bool p_report
)
33 /*@modifies p_ue, g_warningstream@*/ ;
35 static bool checkSlovakName (uentry p_ue
, flagcode p_slovakflag
, bool p_report
)
36 /*@modifies p_ue, g_warningstream@*/ ;
38 static cstring
czechPrefix (cstring name
)
40 return (cstring_beforeChar (name
, '_'));
43 static cstring
slovakPrefix (cstring name
)
47 cstring_chars (name
, c
)
49 if (isupper ((unsigned char) c
))
51 return (cstring_prefix (name
, i
));
56 return cstring_undefined
;
59 static flagcode excludeCodes
[] =
61 FLG_MACROVARPREFIXEXCLUDE
,
63 FLG_ENUMPREFIXEXCLUDE
,
64 FLG_FILESTATICPREFIXEXCLUDE
,
65 FLG_GLOBPREFIXEXCLUDE
,
66 FLG_TYPEPREFIXEXCLUDE
,
67 FLG_EXTERNALPREFIXEXCLUDE
,
68 FLG_UNCHECKEDMACROPREFIXEXCLUDE
,
69 FLG_LOCALPREFIXEXCLUDE
,
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++;
78 # define end_excludeFlagCodes }}
80 static bool matchPrefixChar (int nc
, int pc
)
101 return !islower (nc
);
104 case PFX_ANYLETTERDIGIT
:
105 return (isdigit (nc
) || isalpha (nc
));
106 default: return FALSE
;
113 static bool matchPrefix (cstring name
, cstring prefix
)
115 if (cstring_isUndefined (name
)
116 || cstring_isUndefined (prefix
))
122 size_t namelen
= cstring_length (name
);
123 int last
= (int) '\0';
126 cstring_chars (prefix
, pc
)
136 nc
= (int) cstring_getChar (name
, n
);
138 if (!matchPrefixChar (nc
, last
))
153 && (cstring_length (prefix
) >= n
+ 1)
154 && cstring_getChar (prefix
, n
+ 1) == '*')
164 nc
= (int) cstring_getChar (name
, n
);
166 if (!matchPrefixChar (nc
, (int) pc
))
181 namespaceExcluded (flagcode code
) /*@*/
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
);
211 static /*@observer@*/ cstring
212 namespaceName (flagcode flag
) /*@*/
216 case FLG_MACROVARPREFIX
:
217 return cstring_makeLiteralTemp ("macro variable");
219 return cstring_makeLiteralTemp ("tag");
221 return cstring_makeLiteralTemp ("enum member");
223 return cstring_makeLiteralTemp ("user-defined type");
224 case FLG_FILESTATICPREFIX
:
225 return cstring_makeLiteralTemp ("file static");
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");
235 return cstring_makeLiteralTemp ("iter");
236 case FLG_UNCHECKEDMACROPREFIX
:
237 return cstring_makeLiteralTemp ("unchecked macro");
243 checkPrefix (uentry ue
)
245 cstring name
= cstring_undefined
;
248 if (uentry_isExpandedMacro (ue
))
250 flag
= FLG_UNCHECKEDMACROPREFIX
;
252 else if (uentry_isAnyTag (ue
))
254 flag
= FLG_TAGPREFIX
;
256 else if (uentry_isEnumConstant (ue
))
258 flag
= FLG_ENUMPREFIX
;
260 else if (uentry_isDatatype (ue
))
262 flag
= FLG_TYPEPREFIX
;
264 else if (uentry_isFileStatic (ue
))
266 flag
= FLG_FILESTATICPREFIX
;
268 else if (uentry_isGlobalVariable (ue
))
270 flag
= FLG_GLOBPREFIX
;
272 else if (uentry_isVariable (ue
))
274 if (uentry_isRefParam (ue
))
276 return; /* already checked param */
279 if (context_inMacro ())
281 if (uentry_isAnyParam (ue
))
283 if (uentry_isYield (ue
))
285 flag
= FLG_MACROVARPREFIX
;
289 flag
= FLG_LOCALPREFIX
;
294 flag
= FLG_MACROVARPREFIX
;
299 flag
= FLG_LOCALPREFIX
;
302 else if (uentry_isConstant (ue
))
304 flag
= FLG_CONSTPREFIX
;
306 else if (uentry_isIter (ue
))
308 flag
= FLG_ITERPREFIX
;
310 else if (uentry_isExported (ue
))
312 flag
= FLG_EXTERNALPREFIX
;
316 llcontbug (message ("What is it: %q", uentry_unparseFull (ue
)));
320 if (flag
== FLG_TYPEPREFIX
|| flag
== FLG_GLOBPREFIX
321 || flag
== FLG_ENUMPREFIX
|| flag
== FLG_CONSTPREFIX
)
323 if (flag
== FLG_ENUMPREFIX
)
325 if (!context_getFlag (flag
))
327 flag
= FLG_CONSTPREFIX
;
331 if (!context_getFlag (flag
))
333 flag
= FLG_EXTERNALPREFIX
;
337 if (context_getFlag (flag
))
339 name
= uentry_observeRealName (ue
);
341 if (!matchPrefix (name
, context_getString (flag
)))
343 llassert (flag
!= FLG_NAMECHECKS
);
346 (flag
, FLG_NAMECHECKS
,
347 message ("%s %s name is not consistent with %s "
348 "namespace prefix \"%s\"",
349 uentry_ekindName (ue
),
351 namespaceName (flag
),
352 context_getString (flag
)),
353 uentry_whereLast (ue
)))
355 uentry_setHasNameError (ue
);
360 excludeFlagCodes (code
)
364 if (context_getFlag (code
))
366 /*@-loopswitchbreak@*/
369 case FLG_MACROVARPREFIXEXCLUDE
:
370 check
= (flag
!= FLG_MACROVARPREFIX
);
372 case FLG_TAGPREFIXEXCLUDE
:
373 check
= (flag
!= FLG_TAGPREFIX
);
375 case FLG_ENUMPREFIXEXCLUDE
:
376 check
= (flag
!= FLG_ENUMPREFIX
);
378 case FLG_FILESTATICPREFIXEXCLUDE
:
379 check
= (flag
!= FLG_FILESTATICPREFIX
);
381 case FLG_GLOBPREFIXEXCLUDE
:
382 check
= (flag
!= FLG_GLOBPREFIX
);
384 case FLG_TYPEPREFIXEXCLUDE
:
385 check
= (flag
!= FLG_TYPEPREFIX
);
387 case FLG_EXTERNALPREFIXEXCLUDE
:
388 check
= (flag
!= FLG_EXTERNALPREFIX
389 && flag
!= FLG_GLOBPREFIX
390 && flag
!= FLG_TYPEPREFIX
391 && flag
!= FLG_UNCHECKEDMACROPREFIX
);
393 case FLG_UNCHECKEDMACROPREFIXEXCLUDE
:
394 check
= (flag
!= FLG_UNCHECKEDMACROPREFIX
);
396 case FLG_LOCALPREFIXEXCLUDE
:
397 check
= (flag
!= FLG_LOCALPREFIX
);
399 case FLG_CONSTPREFIXEXCLUDE
:
400 check
= (flag
!= FLG_CONSTPREFIX
);
402 case FLG_ITERPREFIXEXCLUDE
:
403 check
= (flag
!= FLG_ITERPREFIX
);
407 /*@=loopswitchbreak@*/
411 flagcode rcode
= namespaceExcluded (code
);
412 cstring pstring
= context_getString (rcode
);
414 if (cstring_isDefined (pstring
))
416 if (cstring_isUndefined (name
))
418 name
= uentry_observeRealName (ue
);
421 if (matchPrefix (name
, context_getString (rcode
)))
424 (code
, FLG_NAMECHECKS
,
426 ("%s %s name is not a %s (it is a %s), "
427 "but matches the %s "
428 "namespace prefix \"%s\"",
429 uentry_ekindName (ue
),
431 namespaceName (rcode
),
432 namespaceName (flag
),
433 namespaceName (rcode
),
434 context_getString (rcode
)),
435 uentry_whereLast (ue
)))
437 uentry_setHasNameError (ue
);
443 } end_excludeFlagCodes
;
447 checkNationalName (uentry ue
)
451 flagcode czechoslovakflag
;
455 if (uentry_isFunction (ue
)
456 || uentry_isIter (ue
)
457 || uentry_isEndIter (ue
))
459 czechflag
= FLG_CZECHFUNCTIONS
;
460 slovakflag
= FLG_SLOVAKFUNCTIONS
;
461 czechoslovakflag
= FLG_CZECHOSLOVAKFUNCTIONS
;
463 else if (uentry_isExpandedMacro (ue
))
465 czechflag
= FLG_CZECHMACROS
;
466 slovakflag
= FLG_SLOVAKMACROS
;
467 czechoslovakflag
= FLG_CZECHOSLOVAKMACROS
;
469 else if (uentry_isVariable (ue
))
471 if (uentry_isGlobalVariable (ue
) && context_getFlag (FLG_GLOBPREFIX
))
473 /* prefix checks supercede national naming checks */
477 czechflag
= FLG_CZECHVARS
;
478 slovakflag
= FLG_SLOVAKVARS
;
479 czechoslovakflag
= FLG_CZECHOSLOVAKVARS
;
481 else if (uentry_isConstant (ue
))
483 if (uentry_isGlobalVariable (ue
) && context_getFlag (FLG_CONSTPREFIX
))
485 /* prefix checks supercede national naming checks */
489 czechflag
= FLG_CZECHCONSTANTS
;
490 slovakflag
= FLG_SLOVAKCONSTANTS
;
491 czechoslovakflag
= FLG_CZECHOSLOVAKCONSTANTS
;
495 if (uentry_isAnyTag (ue
) || uentry_isEnumConstant (ue
))
497 return; /* no errors for tags */
500 llassert (uentry_isDatatype (ue
));
502 czechflag
= FLG_CZECHTYPES
;
503 slovakflag
= FLG_SLOVAKTYPES
;
504 czechoslovakflag
= FLG_CZECHOSLOVAKTYPES
;
507 gcf
= context_getFlag (czechflag
);
508 gsf
= context_getFlag (slovakflag
);
509 gcsf
= context_getFlag (czechoslovakflag
);
511 if (gcf
|| (uentry_isFunction (ue
)
512 && context_getFlag (FLG_ACCESSCZECH
)))
514 (void) checkCzechName (ue
, czechflag
, gcf
);
517 if (gsf
|| (uentry_isFunction (ue
)
518 && context_getFlag (FLG_ACCESSSLOVAK
)))
520 (void) checkSlovakName (ue
, slovakflag
, gsf
);
525 if (uentry_isDatatype (ue
))
527 /* May not have either _'s or uppercase letter */
528 cstring name
= uentry_rawName (ue
);
531 cstring_chars (name
, c
)
533 if (isupper ((unsigned char) c
))
536 (FLG_CZECHOSLOVAKTYPES
, FLG_NAMECHECKS
,
538 ("%s %q name violates Czechoslovak naming convention. "
539 "Czechoslovak datatype names should not use uppercase "
541 uentry_ekindName (ue
),
542 uentry_getName (ue
)),
543 uentry_whereLast (ue
)))
545 uentry_setHasNameError (ue
);
550 if (c
== '_' && charno
!= 2 && charno
!= 3)
553 (FLG_CZECHOSLOVAKTYPES
, FLG_NAMECHECKS
,
554 message ("%s %q name violates Czechoslovak naming "
555 "convention. Czechoslovak datatype names "
556 "should not use the _ charater.",
557 uentry_ekindName (ue
),
558 uentry_getName (ue
)),
559 uentry_whereLast (ue
)))
561 uentry_setHasNameError (ue
);
571 bool okay
= checkCzechName (ue
, czechflag
, FALSE
);
573 /* still need to call, to set access */
574 okay
|= checkSlovakName (ue
, slovakflag
, FALSE
);
579 (czechoslovakflag
, FLG_NAMECHECKS
,
580 message ("%s %q name is not consistent with Czechoslovak "
581 "naming convention.",
582 uentry_ekindName (ue
),
583 uentry_getName (ue
)),
584 uentry_whereLast (ue
)))
586 uentry_setHasNameError (ue
);
593 static bool checkCzechName (uentry ue
, flagcode czechflag
, bool report
)
595 if (uentry_isDatatype (ue
))
598 ** Czech datatypes may not have _'s, except if there are 1 or 2 characters
599 ** before the only _.
602 cstring name
= uentry_rawName (ue
);
605 cstring_chars (name
, c
)
607 if (c
== '_' && charno
!= 2 && charno
!= 3)
612 (FLG_CZECHTYPES
, FLG_NAMECHECKS
,
614 ("%s %q name violates Czech naming convention. "
615 "Czech datatype names should not use the _ charater.",
616 uentry_ekindName (ue
),
617 uentry_getName (ue
)),
618 uentry_whereLast (ue
)))
620 uentry_setHasNameError (ue
);
632 typeIdSet acc
= context_fileAccessTypes ();
633 cstring pfx
= czechPrefix (uentry_rawName (ue
));
635 if (cstring_isEmpty (pfx
))
637 if (uentry_isVariable (ue
) || uentry_isConstant (ue
))
639 ctype ct
= uentry_getType (ue
);
641 if (ctype_isAbstract (ct
)
642 && context_hasAccess (ctype_typeId (ct
)))
647 (czechflag
, FLG_NAMECHECKS
,
648 message ("%s %q name is not consistent with Czech "
649 "naming convention. The name should "
651 uentry_ekindName (ue
),
654 uentry_whereLast (ue
)))
656 uentry_setHasNameError (ue
);
664 else if (uentry_isFunction (ue
) || uentry_isIter (ue
))
666 if (typeIdSet_isEmpty (acc
))
668 ; /* okay - should not be czech name */
675 (czechflag
, FLG_NAMECHECKS
,
676 message ("%s %q name is not consistent with Czech "
677 "naming convention. Accessible types: %q",
678 uentry_ekindName (ue
),
680 typeIdSet_unparse (acc
)),
681 uentry_whereLast (ue
)))
683 uentry_setHasNameError (ue
);
698 if (usymtab_existsTypeEither (pfx
))
700 ctype ct
= usymtab_lookupAbstractType (pfx
);
705 tid
= ctype_typeId (ct
);
707 if (ctype_isUser (ct
) || context_hasAccess (tid
))
713 if (context_getFlag (FLG_ACCESSCZECH
)
714 || context_getFlag (FLG_ACCESSCZECHOSLOVAK
))
716 if (!uentry_isVar (ue
))
718 uentry_addAccessType (ue
, tid
);
728 ("%s %q name violates Czech naming "
729 "convention. Czech prefix %s names "
730 "an abstract type that is "
732 uentry_ekindName (ue
),
736 ("Use +accessczech to allow access to "
737 "type <t> in functions "
738 "named <t>_<name>."),
739 uentry_whereLast (ue
)))
741 uentry_setHasNameError (ue
);
750 else if (ctype_isManifestBool (ct
))
752 if (context_canAccessBool ())
758 if (context_getFlag (FLG_ACCESSCZECH
)
759 || context_getFlag (FLG_ACCESSCZECHOSLOVAK
))
761 if (!uentry_isVar (ue
))
763 tid
= usymtab_getTypeId (context_getBoolName ());
764 uentry_addAccessType (ue
, tid
);
774 ("%s %q name violates Czech naming "
775 "convention. Type bool is not accessible.",
776 uentry_ekindName (ue
),
777 uentry_getName (ue
)),
779 ("Use +accessczech to allow access to "
780 "type <t> in functions named <t>_<name>."),
781 uentry_whereLast (ue
)))
783 uentry_setHasNameError (ue
);
799 if (cstring_equalLit (pfx
, "int")
800 || cstring_equalLit (pfx
, "char")
801 || cstring_equalLit (pfx
, "short")
802 || cstring_equalLit (pfx
, "long")
803 || cstring_equalLit (pfx
, "unsigned")
804 || cstring_equalLit (pfx
, "signed")
805 || cstring_equalLit (pfx
, "float")
806 || cstring_equalLit (pfx
, "double"))
808 ; /* built-in types */
812 /* no accessible types, could match module name */
814 if (cstring_equal (pfx
, context_moduleName ()))
823 (czechflag
, FLG_NAMECHECKS
,
825 ("%s %q name violates Czech naming convention. "
826 "Czech prefix %s is not the name of a type.",
827 uentry_ekindName (ue
),
830 uentry_whereLast (ue
)))
832 uentry_setHasNameError (ue
);
848 static bool checkSlovakName (uentry ue
, flagcode slovakflag
, bool report
)
850 if (uentry_isDatatype (ue
))
853 ** Slovak datatypes may not have uppercase letters.
856 if (context_getFlag (FLG_SLOVAK
))
858 cstring name
= uentry_rawName (ue
);
860 cstring_chars (name
, c
)
862 if (isupper ((unsigned char) c
))
867 (FLG_SLOVAKTYPES
, FLG_NAMECHECKS
,
869 ("%s %q name violates Slovak naming convention. "
870 "Slovak datatype names should not use uppercase "
872 uentry_ekindName (ue
),
873 uentry_getName (ue
)),
874 uentry_whereLast (ue
)))
876 uentry_setHasNameError (ue
);
886 typeIdSet acc
= context_fileAccessTypes ();
887 cstring pfx
= slovakPrefix (uentry_rawName (ue
));
889 if (cstring_isEmpty (pfx
))
891 if (typeIdSet_isEmpty (acc
))
893 ; /* okay - should not be slovak name */
897 if (uentry_isFunction (ue
))
902 (slovakflag
, FLG_NAMECHECKS
,
903 message ("%s %q name is not consistent with Slovak "
904 "naming convention. Accessible types: %q",
905 uentry_ekindName (ue
),
907 typeIdSet_unparse (acc
)),
908 uentry_whereLast (ue
)))
910 uentry_setHasNameError (ue
);
919 ctype ct
= uentry_getType (ue
);
926 (slovakflag
, FLG_NAMECHECKS
,
927 message ("%s %q name is not consistent with "
928 "Slovak naming convention. The "
929 "name should begin with %s followed "
930 "by an uppercase letter.",
931 uentry_ekindName (ue
),
934 uentry_whereLast (ue
)))
936 uentry_setHasNameError (ue
);
948 if (usymtab_existsTypeEither (pfx
))
950 ctype ct
= usymtab_lookupAbstractType (pfx
);
955 tid
= ctype_typeId (ct
);
957 if (ctype_isUser (ct
) || context_hasAccess (tid
))
963 if (context_getFlag (FLG_ACCESSSLOVAK
)
964 || context_getFlag (FLG_ACCESSCZECHOSLOVAK
))
966 if (!uentry_isVar (ue
))
968 uentry_addAccessType (ue
, tid
);
978 ("%s %q name violates Slovak naming "
979 "convention. Slovak prefix %s names "
980 "an abstract type that is not accessible.",
981 uentry_ekindName (ue
),
985 ("Use +accessslovak to allow access to "
986 "type <t> in functions named <t>_<name>."),
987 uentry_whereLast (ue
)))
989 uentry_setHasNameError (ue
);
998 else if (ctype_isManifestBool (ct
))
1000 if (context_canAccessBool ())
1006 if (context_getFlag (FLG_ACCESSSLOVAK
)
1007 || context_getFlag (FLG_ACCESSCZECHOSLOVAK
))
1009 if (!uentry_isVar (ue
))
1011 tid
= usymtab_getTypeId (context_getBoolName ());
1012 uentry_addAccessType (ue
, tid
);
1022 ("%s %q name violates Slovak naming convention. "
1023 "Type bool is not accessible.",
1024 uentry_ekindName (ue
),
1025 uentry_getName (ue
)),
1027 ("Use +accessslovak to allow access to "
1028 "type <t> in functions named <t>_<name>."),
1029 uentry_whereLast (ue
)))
1031 uentry_setHasNameError (ue
);
1047 if (cstring_equalLit (pfx
, "int")
1048 || cstring_equalLit (pfx
, "char")
1049 || cstring_equalLit (pfx
, "short")
1050 || cstring_equalLit (pfx
, "long")
1051 || cstring_equalLit (pfx
, "unsigned")
1052 || cstring_equalLit (pfx
, "signed")
1053 || cstring_equalLit (pfx
, "float")
1054 || cstring_equalLit (pfx
, "double"))
1056 ; /* built-in types */
1060 /* no accessible types, could match module name */
1062 if (cstring_equal (pfx
, context_moduleName ()))
1071 (slovakflag
, FLG_NAMECHECKS
,
1073 ("%s %q name violates Slovak naming convention. "
1074 "Slovak prefix %s is not the name of a type.",
1075 uentry_ekindName (ue
),
1076 uentry_getName (ue
),
1078 uentry_whereLast (ue
)))
1080 uentry_setHasNameError (ue
);
1098 checkExternalName (uentry ue
)
1100 if (!uentry_isStatic (ue
) && uentry_hasName (ue
))
1102 checkNationalName (ue
);
1111 checkLocalName (/*@unused@*/ uentry ue
)
1114 ** No local checks (yet)
1121 checkFileScopeName (/*@unused@*/ uentry ue
)
1124 ** No file scope checks (yet)
1127 /* add a file scope naming convention policy? */
1133 ** Checks a name used by user source is not reserved by ANSI
1134 ** (or for future library functions).
1136 ** The restrictions are described in X3.159-1989: 4.13
1139 /*@constant int NRESERVEDNAMES; @*/
1140 # define NRESERVEDNAMES 201
1142 /*@constant int NCPPNAMES@*/
1143 # define NCPPNAMES 39
1146 checkCppName (uentry ue
)
1148 cstring name
= uentry_observeRealName (ue
);
1150 static /*@observer@*/ const char* cppNames
[NCPPNAMES
] =
1152 "and", "and_eq", "asm",
1153 "bitand", "bitor", "bool", /* gasp: "bool", is special for splint */
1154 "catch", "class", "compl", "const_class",
1155 "delete", "dynamic_cast", "false", "friend",
1156 "inline", "mutable", "namespace", "new",
1158 "operator", "or", "or_eq", "overload",
1159 "private", "protected", "public",
1160 "reinterpret_cast", "static_cast",
1161 "template", "this", "throw", "true", "try",
1162 "typeid", "using", "virtual", "xor", "xor_eq"
1165 if (cstring_bsearch (name
, &cppNames
[0], NCPPNAMES
))
1168 (FLG_CPPNAMES
, FLG_NAMECHECKS
,
1169 message ("Name %s is a keyword or reserved word in C++",
1171 uentry_whereLast (ue
)))
1173 uentry_setHasNameError (ue
);
1179 checkStdName (uentry ue
)
1181 bool hasError
= FALSE
;
1182 cstring name
= uentry_observeRealName (ue
);
1183 size_t length
= cstring_length (name
);
1184 char fchar
= (length
>= 1) ? cstring_firstChar (name
) : '\0';
1185 char schar
= (length
>= 2) ? cstring_secondChar (name
) : '\0';
1186 char tchar
= (length
>= 3) ? cstring_getChar (name
, 3) : '\0';
1187 char rchar
= (length
>= 4) ? cstring_getChar (name
, 4) : '\0';
1191 ** taken from Linden, "Expert C Programming", p. 126-8.
1192 ** invariant: must be sorted (case-insensitive, lexicographically)
1193 ** must end with NULL
1196 static /*@observer@*/ const char* reservedNames
[NRESERVEDNAMES
] =
1198 # include "reservedNames.c"
1203 ** This code is for checking reservedNames.c
1208 char *lastname
= NULL
;
1211 while ((name
= reservedNames
[i
]) != NULL
)
1213 llassertprint (lastname
== NULL
1214 || strcmp (name
, lastname
) > 0,
1215 ("%s / %s", lastname
, name
));
1220 nreservedNames
= i
- 1;
1224 if (fileloc_isSystemFile (uentry_whereLast (ue
)) || fileloc_isBuiltin (uentry_whereLast (ue
)))
1226 return; /* no errors for system files */
1229 if (cstring_bsearch (name
, &reservedNames
[0], NRESERVEDNAMES
))
1231 hasError
|= optgenerror2
1232 (FLG_ISORESERVED
, FLG_NAMECHECKS
,
1233 message ("Name %s is reserved for the standard library",
1235 uentry_whereLast (ue
));
1238 if (uentry_isFileStatic (ue
) || uentry_isVisibleExternally (ue
) || uentry_isAnyTag (ue
)
1239 || context_getFlag (FLG_ISORESERVEDLOCAL
))
1243 hasError
|= optgenerror2
1244 (FLG_ISORESERVED
, FLG_NAMECHECKS
,
1246 ("Name %s is in the implementation name space (any identifier "
1247 "beginning with underscore)",
1249 uentry_whereLast (ue
));
1256 ** - All identifiers that begin with an underscore and either an uppercase
1257 ** letter or another underscore are always reserved for any use.
1261 && (schar
== '_' || isupper ((int) schar
)))
1263 hasError
|= optgenerror2
1264 (FLG_ISORESERVED
, FLG_NAMECHECKS
,
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)",
1270 uentry_whereLast (ue
));
1275 ** 4.13.1 Errors <errno.h>
1277 ** Macros that begin with E and a digit or E and an uppercase letter ...
1280 if (fchar
== 'E' && (isdigit ((int) schar
)
1281 || isupper ((int) schar
)))
1283 hasError
|= optgenerror2
1284 (FLG_ISORESERVED
, FLG_NAMECHECKS
,
1286 ("Name %s is reserved for future library extensions. "
1287 "Macros beginning with E and a digit or uppercase letter "
1288 "may be added to <errno.h>. (ISO99:7.26.3)",
1290 uentry_whereLast (ue
));
1294 ** 4.13.3 Localization <locale.h>
1296 ** Macros that begin with LC_ and an uppercase letter ...
1303 && (isupper ((int) rchar
)))
1305 hasError
|= optgenerror2
1306 (FLG_ISORESERVED
, FLG_NAMECHECKS
,
1308 ("Name %s is reserved for future library extensions. "
1309 "Macros beginning with \"LC_\" and an uppercase letter may "
1310 "be added to <locale.h>. (ISO99:7.26.5)",
1312 uentry_whereLast (ue
));
1316 ** 4.13.5 Signal Handling <signal.h>
1318 ** Macros that begin with either SIG or SIG_ and an uppercase letter or...
1321 if (fchar
== 'S' && schar
== 'I' && tchar
== 'G'
1322 && ((rchar
== '_' && ((length
>= 5
1323 && isupper ((int) cstring_getChar (name
, 5)))))
1324 || (isupper ((int) rchar
))))
1326 hasError
|= optgenerror2
1327 (FLG_ISORESERVED
, FLG_NAMECHECKS
,
1329 ("Name %s is reserved for future library extensions. "
1330 "Macros that begin with SIG and an uppercase letter or SIG_ "
1331 "and an uppercase letter may be added to "
1332 "<signal.h>. (ISO99:7.14)",
1334 uentry_whereLast (ue
));
1338 ** evans - 2002-12-16: added this check (even though it is not required by ISO)
1341 if (fchar
== 'S' && schar
== 'A' && tchar
== '_')
1343 hasError
|= optgenerror2
1344 (FLG_ISORESERVED
, FLG_NAMECHECKS
,
1346 ("Name %s may be defined as a macro by Linux library. "
1347 "It is not research by the ISO specification, but may produce conflicts on some systems.",
1349 uentry_whereLast (ue
));
1352 if ((uentry_isVisibleExternally (ue
) && !uentry_isAnyTag (ue
))
1353 || context_getFlag (FLG_ISORESERVEDLOCAL
))
1357 DPRINTF (("Okay...: %s", uentry_unparse (ue
)));
1359 if (uentry_isVisibleExternally (ue
) && !uentry_isAnyTag (ue
))
1361 flg
= FLG_ISORESERVED
;
1365 flg
= FLG_ISORESERVEDLOCAL
;
1368 DPRINTF (("ue: %s", uentry_unparseFull (ue
)));
1371 ** These restrictions only apply to identifiers with global linkage.
1375 ** 4.13.2 Character Handling <ctype.h>
1377 ** Function names that begin with either "is" or "to" and a lowercase letter ...
1380 if (((fchar
== 'i' && schar
== 's')
1381 || (fchar
== 't' && schar
== 'o'))
1382 && (islower ((int) tchar
)))
1384 hasError
|= optgenerror2
1385 (flg
, FLG_NAMECHECKS
,
1387 ("Name %s is reserved for future library extensions. "
1388 "Functions beginning with \"is\" or \"to\" and a lowercase "
1389 "letter may be added to <ctype.h>. (ISO99:7.26.2)",
1391 uentry_whereLast (ue
));
1393 DPRINTF (("Externally visible: %s / %s",
1394 uentry_unparseFull (ue
),
1395 bool_unparse (uentry_isVisibleExternally (ue
))));
1400 ** 4.13.4 Mathematics <math.h>
1402 ** The names of all existing functions declared in the <math.h> header,
1403 ** suffixed with f or l...
1406 DPRINTF (("Check name: %s", name
));
1408 if ((cstring_lastChar (name
) == 'f' || cstring_lastChar (name
) == 'l')
1411 && ((cstring_equalPrefixLit (name
, "cos") ||
1412 cstring_equalPrefixLit (name
, "sin") ||
1413 cstring_equalPrefixLit (name
, "tan") ||
1414 cstring_equalPrefixLit (name
, "exp") ||
1415 cstring_equalPrefixLit (name
, "log") ||
1416 cstring_equalPrefixLit (name
, "pow"))))
1418 && ((cstring_equalPrefixLit (name
, "acos") ||
1419 cstring_equalPrefixLit (name
, "asin") ||
1420 cstring_equalPrefixLit (name
, "atan") ||
1421 cstring_equalPrefixLit (name
, "cosh") ||
1422 cstring_equalPrefixLit (name
, "sinh") ||
1423 cstring_equalPrefixLit (name
, "sqrt") ||
1424 cstring_equalPrefixLit (name
, "ceil") ||
1425 cstring_equalPrefixLit (name
, "fabs") ||
1426 cstring_equalPrefixLit (name
, "fmod") ||
1427 cstring_equalPrefixLit (name
, "tanh") ||
1428 cstring_equalPrefixLit (name
, "modf"))))
1430 && ((cstring_equalPrefixLit (name
, "atan2") ||
1431 cstring_equalPrefixLit (name
, "floor") ||
1432 cstring_equalPrefixLit (name
, "frexp") ||
1433 cstring_equalPrefixLit (name
, "ldexp") ||
1434 cstring_equalPrefixLit (name
, "log10"))))))
1436 hasError
|= optgenerror2
1437 (flg
, FLG_NAMECHECKS
,
1439 ("Name %s is reserved for future library extensions. "
1440 "The names of all existing functions in <math.h> suffixed "
1441 "with 'f' or 'l' may be added to <math.h>. (ISO:7.26.1)",
1443 uentry_whereLast (ue
));
1447 ** 4.13.6 Input/Output <stdio.h>
1449 ** (nothing to check)
1453 ** 4.13.7 General Utilities <stdlib.h>
1455 ** Functions names that begin with str and a lowercase letter may be added to <stdlib.h>.
1458 if (fchar
== 's' && schar
== 't' && tchar
== 'r'
1459 && (islower ((int) rchar
)))
1461 hasError
|= optgenerror2
1462 (flg
, FLG_NAMECHECKS
,
1464 ("Name %s is reserved for future library extensions. "
1465 "Functions that begin with \"str\" and a lowercase letter "
1466 "may be added to <stdlib.h> or <string.h>. (ISO99:7.26.9)",
1468 uentry_whereLast (ue
));
1472 ** 4.13.8 String Handling <string.h>
1474 ** Function names that begin with str, mem, or wcs and a lowercase letter ...
1476 ** (Note: already checked "str" above.)
1479 if (((fchar
== 'm' && schar
== 'e' && tchar
== 'm')
1480 || (fchar
== 'w' && schar
== 'c' && tchar
== 's'))
1481 && (islower ((int) rchar
)))
1483 hasError
|= optgenerror2
1484 (flg
, FLG_NAMECHECKS
,
1486 ("Name %s is reserved for future library extensions. "
1487 "Functions that begin with \"mem\" or \"wcs\" and a "
1488 "lowercase letter may be added to <string.h>. (ISO:7.26.11)",
1490 uentry_whereLast (ue
));
1495 DPRINTF (("Not checked: [%s] %s", bool_unparse (uentry_isVisibleExternally (ue
)),
1496 uentry_unparseFull (ue
)));
1501 uentry_setHasNameError (ue
);
1505 void checkParamNames (uentry ue
)
1507 cstring fpfx
= context_getString (FLG_DECLPARAMPREFIX
);
1508 bool noformal
= context_getFlag (FLG_DECLPARAMNAME
);
1510 llassert (uentry_isFunction (ue
));
1512 if (cstring_isDefined (fpfx
) || noformal
)
1514 uentryList params
= uentry_getParams (ue
);
1516 uentryList_elements (params
, p
)
1518 if (uentry_hasName (p
))
1520 if (noformal
&& !cstring_isDefined (fpfx
))
1523 (FLG_DECLPARAMNAME
, FLG_NAMECHECKS
,
1524 message ("Declaration parameter has name: %q",
1525 uentry_getName (p
)),
1526 uentry_whereLast (p
)))
1528 uentry_setHasNameError (p
);
1533 cstring pname
= uentry_observeRealName (p
);
1535 if (!cstring_equalPrefix (pname
, fpfx
))
1537 if (context_getFlag (FLG_NAMECHECKS
))
1540 (FLG_DECLPARAMPREFIX
, FLG_NAMECHECKS
,
1541 message ("Declaration parameter name %s does not begin "
1542 "with protoparamprefix (%s)",
1544 uentry_whereLast (p
)))
1546 uentry_setHasNameError (p
);
1552 } end_uentryList_elements
;
1556 /* not yet checked: POSIX p. 527 - applications should not declare any symbols that end _MAX */