@@ -6,6 +6,7 @@ import codingstandards.cpp.CKeywords
66import codingstandards.cpp.Linkage
77import codingstandards.cpp.Macro
88import codingstandards.cpp.StandardLibraryNames
9+ import codingstandards.cpp.StdNamespace
910
1011module ReservedNames {
1112 module C11 {
@@ -297,4 +298,230 @@ module ReservedNames {
297298 )
298299 }
299300 }
301+
302+ module Cpp14 {
303+ private import codingstandards.cpp.Lex
304+
305+ module TargetedCppLibrary = CppStandardLibrary:: Cpp14;
306+
307+ module TargetedCLibrary = CStandardLibrary:: C99;
308+
309+ predicate isMacroUsingReservedIdentifier ( PreprocessorDirective pd , string reason ) {
310+ exists ( string name , string identifierDescription |
311+ pd .( Macro ) .getName ( ) = name and identifierDescription = "#define"
312+ or
313+ pd .( PreprocessorUndef ) .getName ( ) = name and
314+ identifierDescription = "#undef"
315+ |
316+ // [macro.names] precludes the use of any name declared in any standard library header
317+ exists ( string header , string standard |
318+ TargetedCLibrary:: hasName ( header , name ) and
319+ standard = TargetedCLibrary:: getName ( )
320+ or
321+ TargetedCppLibrary:: hasName ( header , name ) and
322+ standard = TargetedCppLibrary:: getName ( )
323+ |
324+ // Includes at least one standard library header
325+ pd .getFile ( ) .getAnIncludedFile * ( ) .getBaseName ( ) =
326+ [ TargetedCLibrary:: getAHeader ( ) , TargetedCppLibrary:: getAHeader ( ) ] and
327+ reason =
328+ "'" + identifierDescription + " " + name + "' uses a reserved name from the " + standard
329+ + " standard library header <" + header + ">."
330+ )
331+ or
332+ // [macro.names] precludes the use of keywords, special identifiers or reserved attribute tokens
333+ exists ( string kind |
334+ name = Lex:: Cpp14:: keyword ( ) and kind = " keyword"
335+ or
336+ name = Lex:: Cpp14:: specialIdentfier ( ) and kind = "special identifier"
337+ or
338+ name = Lex:: Cpp14:: reservedAttributeToken ( ) and kind = "reserved attribute token"
339+ |
340+ reason =
341+ "'" + identifierDescription + " " + name + "' uses a name lexically identical to a " +
342+ kind + "."
343+ )
344+ or
345+ // [global.names] Reserves unconditionally all names containing __ or prefixed with _[A-Z].
346+ // In addition _ prefixed names are reserved to the implementation in the global namespace.
347+ // As macros are not limited in effect to a given namespace, we also consider all names
348+ // starting with _ as reserved when considering macros, as well as those with __ in the name.
349+ name .regexpMatch ( "(_.*|.*__.*)" ) and
350+ reason =
351+ "'" + identifierDescription + " " + name + "' uses a name reserved for the " +
352+ TargetedCppLibrary:: getName ( ) + " implementation."
353+ )
354+ }
355+
356+ class GlobalFunction extends TopLevelFunction {
357+ GlobalFunction ( ) { getNamespace ( ) instanceof GlobalNamespace }
358+ }
359+
360+ private Macro getGeneratedFrom ( Element e ) {
361+ isCppIdentifier ( e , _, _, _) and
362+ exists ( MacroInvocation mi |
363+ mi = result .getAnInvocation ( ) and
364+ mi .getAGeneratedElement ( ) = e and
365+ not exists ( MacroInvocation child |
366+ child .getParentInvocation ( ) = mi and
367+ child .getAGeneratedElement ( ) = e
368+ )
369+ )
370+ }
371+
372+ newtype IdentifierScope =
373+ StdNamespaceScope ( ) or
374+ GlobalNamespaceScope ( ) or
375+ OtherNamespaceScope ( )
376+
377+ /**
378+ * An declaration whose name can be reserved.
379+ */
380+ private predicate isCppIdentifier (
381+ Declaration m , string name , string identifierDescription , IdentifierScope scope
382+ ) {
383+ m .( GlobalFunction ) .getName ( ) = name and
384+ identifierDescription = "Function" and
385+ scope = GlobalNamespaceScope ( )
386+ or
387+ m .( GlobalVariable ) .getName ( ) = name and
388+ identifierDescription = "Variable" and
389+ scope = GlobalNamespaceScope ( )
390+ or
391+ m .( UserType ) .getName ( ) = name and
392+ m .( UserType ) .getNamespace ( ) instanceof GlobalNamespace and
393+ identifierDescription = "Type" and
394+ scope = GlobalNamespaceScope ( )
395+ or
396+ hasExternalLinkage ( m ) and
397+ m .( Declaration ) .getName ( ) = name and
398+ identifierDescription = "Declaration with external linkage" and
399+ exists ( Namespace n | n = m .( Declaration ) .getNamespace ( ) |
400+ if n instanceof StdNS
401+ then scope = StdNamespaceScope ( )
402+ else
403+ if n instanceof GlobalNamespace
404+ then scope = GlobalNamespaceScope ( )
405+ else scope = OtherNamespaceScope ( )
406+ )
407+ }
408+
409+ predicate isAReservedIdentifier ( Declaration m , string message ) {
410+ exists ( string name , string identifierDescription , IdentifierScope scope , string reason |
411+ isCppIdentifier ( m , name , identifierDescription , scope ) and
412+ // Exclude cases generated from library macros, because the user does not control them
413+ not getGeneratedFrom ( m ) instanceof LibraryMacro and
414+ message = identifierDescription + " '" + name + "' " + reason + "."
415+ |
416+ // [global.names] reserves unconditionally all names containing __ or prefixed with _[A-Z].
417+ // In addition _ prefixed names are reserved to the implementation in the global namespace.
418+ name .regexpMatch ( "(_[A-Z].*|.*__.*)" ) and
419+ reason =
420+ " uses a name reserved for the " + TargetedCppLibrary:: getName ( ) + " implementation."
421+ or
422+ // [global.names] reserves all _ prefixed names to the implementation in the global namespace.
423+ name .regexpMatch ( "_([^A-Z_].*)?" ) and
424+ scope = GlobalNamespaceScope ( ) and
425+ reason =
426+ " uses a name reserved for the " + TargetedCppLibrary:: getName ( ) + " implementation."
427+ or
428+ // [extern.names]/1:
429+ // Each name declared as an object with external linkage in a header is reserved to the implementation to
430+ // designate that library object with external linkage,182 both in namespace std and in the global namespace.
431+ exists ( string header |
432+ header =
433+ max ( string candidate_header |
434+ TargetedCppLibrary:: hasObjectName ( candidate_header , _, name , _, "external" )
435+ )
436+ or
437+ header = "errno" and
438+ name = "cerrno"
439+ |
440+ not scope = OtherNamespaceScope ( ) and
441+ reason =
442+ "declares a reserved object name from the " + TargetedCppLibrary:: getName ( ) +
443+ " standard library header <" + header + ">"
444+ )
445+ or
446+ // [extern.names]/2:
447+ // Each global function signature declared with external linkage in a header is reserved to the implementation
448+ // to designate that function signature with external linkage.
449+ exists ( string header |
450+ header =
451+ max ( string candidate_header |
452+ // Global functions are in the global namespace ("") and have no declaring type
453+ TargetedCppLibrary:: hasFunctionName ( candidate_header , "" , "" , name , _, _, "external" )
454+ )
455+ or
456+ header = "csetjmp" and
457+ name = "setjmp"
458+ or
459+ header = "cstdarg" and
460+ name = "va_end"
461+ |
462+ // Only report against elements with external linkage
463+ hasExternalLinkage ( m ) and
464+ reason =
465+ "declares a name which is reserved for a function from the " +
466+ TargetedCppLibrary:: getName ( ) + " standard library header <" + header + ">"
467+ )
468+ or
469+ // [extern.names]/3:
470+ // Each name from the Standard C library declared with external linkage is reserved to the implementation
471+ // for use as a name with extern "C" linkage, both in namespace std and in the global namespace.
472+ exists ( string header |
473+ header =
474+ max ( string candidate_header |
475+ TargetedCLibrary:: hasObjectName ( candidate_header , _, name , _, "external" )
476+ )
477+ |
478+ // Only global and std
479+ not scope = OtherNamespaceScope ( ) and
480+ reason =
481+ "declares a name which is reserved for the " + TargetedCLibrary:: getName ( ) +
482+ " standard library header <" + header + ">"
483+ )
484+ or
485+ exists ( string header |
486+ // [extern.names]/4:
487+ // Each function signature from the Standard C library declared with external linkage is reserved to the
488+ // implementation for use as a function signature with both extern "C" and extern "C++" linkage, 184 or as
489+ // a name of namespace scope in the global namespace.
490+ header =
491+ max ( string candidate_header |
492+ TargetedCLibrary:: hasFunctionName ( candidate_header , _, _, name , _, _, "external" )
493+ ) and
494+ reason =
495+ "declares a name which is reserved for a function from the " +
496+ TargetedCLibrary:: getName ( ) + " standard library header <" + header + ">"
497+ or
498+ header = [ "cuchar" , "cwchar" , "cwctype" ] and
499+ TargetedCppLibrary:: hasFunctionName ( header , _, "" , name , _, _, "external" ) and
500+ reason =
501+ "declares a name which is reserved for a function from the " +
502+ TargetedCppLibrary:: getName ( ) + " standard library header <" + header + ">"
503+ |
504+ // Only reserved as a name in the global scope
505+ scope = GlobalNamespaceScope ( )
506+ or
507+ // Not a function, but has external linkage
508+ hasExternalLinkage ( m ) and
509+ not m instanceof Function
510+ )
511+ or
512+ exists ( string header |
513+ // [extern.types]:
514+ // For each type T from the Standard C library,185 the types ::T and std::T are reserved to the implementation
515+ // and, when defined, ::T shall be identical to std::T.
516+ header =
517+ max ( string candidate_header | TargetedCLibrary:: hasTypeName ( candidate_header , _, name ) ) and
518+ // Only restricted in std and global namespace
519+ not scope = OtherNamespaceScope ( ) and
520+ reason =
521+ "declares a name which is reserved for a type from the " + TargetedCLibrary:: getName ( ) +
522+ " standard library header <" + header + ">"
523+ )
524+ )
525+ }
526+ }
300527}
0 commit comments