55import cpp
66import codingstandards.cpp.Scope
77
8+ /**
9+ * [basic]/6 uses a specific definition of "variable" that excludes non-static data members.
10+ */
11+ private predicate isSpecificationVariable ( Variable v ) {
12+ v .( MemberVariable ) .isStatic ( )
13+ or
14+ not v instanceof MemberVariable
15+ }
16+
817/** Holds if `elem` has internal linkage. */
918predicate hasInternalLinkage ( Element elem ) {
19+ // An unnamed namespace or a namespace declared directly or indirectly within an unnamed namespace has internal linkage
20+ directlyOrIndirectlyUnnnamedNamespace ( elem )
21+ or
1022 exists ( Declaration decl | decl = elem |
1123 // A name having namespace scope has internal linkage if it is the name of
1224 hasNamespaceScope ( decl ) and
1325 (
1426 // a variable, function or function template
1527 (
16- decl instanceof Variable
28+ isSpecificationVariable ( decl )
1729 or
1830 decl instanceof Function // TemplateFunction is a subclass of Function so this captures both.
1931 ) and
2032 // that is explicitly declared static; or,
2133 decl .isStatic ( )
2234 or
2335 // a non-volatile variable
24- decl instanceof Variable and
36+ isSpecificationVariable ( decl ) and
2537 not decl .( Variable ) .isVolatile ( ) and
2638 // that is explicitly declared const or constexpr and
2739 ( decl .( Variable ) .isConst ( ) or decl .( Variable ) .isConstexpr ( ) ) and
@@ -32,131 +44,93 @@ predicate hasInternalLinkage(Element elem) {
3244 exists ( Union u | hasNamespaceScope ( u ) and u .isAnonymous ( ) |
3345 decl = u .getACanonicalMemberVariable ( )
3446 )
35- or
36- // A name having namespace scope that has not been given internal linkage above has the same linkage as the enclosing namespace if it is the name of
37- hasInternalLinkage ( decl .getNamespace ( ) ) and
38- (
39- // a variable;
40- decl instanceof Variable
41- or
42- // a function
43- decl instanceof Function
44- or
45- // a named class, or an unnamed class defined in a typedef declartion in which the class has the typedef name for linkage purposes
46- exists ( Class klass | decl = klass |
47- not klass .isAnonymous ( )
48- or
49- klass .isAnonymous ( ) and exists ( TypedefType typedef | typedef .getADeclaration ( ) = klass )
50- )
51- or
52- // a named enumeration, or an unnamed enumeration defined in a typedef declaration in which the enumeration has the typedef name for linkage purposes
53- exists ( Enum enum | enum = decl |
54- not enum .isAnonymous ( )
55- or
56- enum .isAnonymous ( ) and exists ( TypedefType typedef | typedef .getADeclaration ( ) = enum )
57- )
58- or
59- // an enumerator beloning to an enumeration with linkage
60- exists ( Enum enum | enum .getADeclaration ( ) = decl | hasInternalLinkage ( enum ) )
61- or
62- // a template
63- decl instanceof TemplateClass
64- or
65- decl instanceof TemplateFunction
66- )
6747 )
6848 or
69- decl instanceof GlobalVariable and
70- (
71- decl .( GlobalVariable ) .isStatic ( ) or
72- decl .( GlobalVariable ) .isConst ( )
73- ) and
74- not decl .( GlobalVariable ) .hasSpecifier ( "external" )
75- )
76- or
77- // An unnamed namespace or a namespace declared directly or indirectly within an unnamed namespace has internal linkage
78- exists ( Namespace ns | ns = elem |
79- ns .isAnonymous ( )
49+ directlyOrIndirectlyUnnnamedNamespace ( decl .getNamespace ( ) ) and
50+ inheritsLinkageOfNamespace ( decl .getNamespace ( ) , decl )
8051 or
81- not ns .isAnonymous ( ) and
82- exists ( Namespace parent | parent .isAnonymous ( ) and parent .getAChildNamespace + ( ) = ns )
52+ exists ( Class klass |
53+ hasInternalLinkage ( klass ) and
54+ inheritsLinkageOfClass ( klass , decl )
55+ )
8356 )
84- or
85- elem instanceof TopLevelFunction and
86- elem .( Function ) .isStatic ( )
8757}
8858
8959/** Holds if `elem` has external linkage. */
9060predicate hasExternalLinkage ( Element elem ) {
61+ elem instanceof Namespace and
62+ not directlyOrIndirectlyUnnnamedNamespace ( elem )
63+ or
9164 not hasInternalLinkage ( elem ) and
92- (
93- exists ( Declaration decl | decl = elem |
94- hasNamespaceScope ( decl ) and
95- // A name having namespace scope that has not been given internal linkage above has the same linkage as the enclosing namespace if it is the name of
96- not hasInternalLinkage ( decl .getNamespace ( ) ) and
97- (
98- // a variable;
99- decl instanceof Variable
100- or
101- // a function
102- decl instanceof Function
103- or
104- // a named class, or an unnamed class defined in a typedef declaration in which the class has the typedef name for linkage purposes
105- exists ( Class klass | decl = klass |
106- not klass .isAnonymous ( )
107- or
108- klass .isAnonymous ( ) and exists ( TypedefType typedef | typedef .getADeclaration ( ) = klass )
109- )
110- or
111- // a named enumeration, or an unnamed enumeration defined in a typedef declaration in which the enumeration has the typedef name for linkage purposes
112- exists ( Enum enum | enum = decl |
113- not enum .isAnonymous ( )
114- or
115- enum .isAnonymous ( ) and exists ( TypedefType typedef | typedef .getADeclaration ( ) = enum )
116- )
117- or
118- // an enumerator beloning to an enumeration with linkage
119- exists ( Enum enum | enum .getADeclaration ( ) = decl | hasInternalLinkage ( enum ) )
120- or
121- // a template
122- decl instanceof TemplateClass
123- or
124- decl instanceof TemplateFunction
125- )
126- or
127- // In addition,
128- hasClassScope ( decl ) and
129- (
130- // a member function,
131- decl instanceof MemberFunction
132- or
133- // static data member
134- decl instanceof MemberVariable and decl .( MemberVariable ) .isStatic ( )
135- or
136- // a named class, or an unnamed class defined in a typedef declartion in which the class has the typedef name for linkage purposes
137- exists ( Class klass | decl = klass |
138- not klass .isAnonymous ( )
139- or
140- klass .isAnonymous ( ) and exists ( TypedefType typedef | typedef .getADeclaration ( ) = klass )
141- )
142- or
143- // a named enumeration, or an unnamed enumeration defined in a typedef declaration in which the enumeration has the typedef name for linkage purposes
144- exists ( Enum enum | enum = decl |
145- not enum .isAnonymous ( )
146- or
147- enum .isAnonymous ( ) and exists ( TypedefType typedef | typedef .getADeclaration ( ) = enum )
148- )
149- ) and
150- // has external linkage if the name of the class has external linkage
151- hasExternalLinkage ( decl .getDeclaringType ( ) )
152- or
153- decl instanceof GlobalVariable and
154- not decl .( GlobalVariable ) .isStatic ( ) and
155- not decl .( GlobalVariable ) .isConst ( )
65+ exists ( Declaration decl | decl = elem |
66+ // A name having namespace scope that has not been given internal linkage above has the same linkage as the enclosing namespace if it is the name of
67+ not directlyOrIndirectlyUnnnamedNamespace ( decl .getNamespace ( ) ) and
68+ inheritsLinkageOfNamespace ( decl .getNamespace ( ) , decl )
69+ or
70+ exists ( Class klass |
71+ hasExternalLinkage ( klass ) and
72+ inheritsLinkageOfClass ( klass , decl )
15673 )
74+ )
75+ }
76+
77+ private predicate directlyOrIndirectlyUnnnamedNamespace ( Namespace ns ) {
78+ exists ( Namespace anonymous |
79+ anonymous .isAnonymous ( ) and
80+ ns = anonymous .getAChildNamespace * ( )
81+ )
82+ }
83+
84+ private predicate hasLinkageOfTypedef ( TypedefType typedef , Element decl ) {
85+ // an unnamed class defined in a typedef declartion in which the class has the typedef name for linkage purposes
86+ decl .( Class ) .isAnonymous ( ) and typedef .getADeclaration ( ) = decl
87+ or
88+ // an unnamed enumeration defined in a typedef declaration in which the enumeration has the typedef name for linkage purposes
89+ decl .( Enum ) .isAnonymous ( ) and typedef .getADeclaration ( ) = decl
90+ }
91+
92+ private predicate inheritsLinkageOfNamespace ( Namespace ns , Declaration decl ) {
93+ hasNamespaceScope ( decl ) and
94+ ns = decl .getNamespace ( ) and
95+ (
96+ // A name having namespace scope that has not been given internal linkage above has the same linkage as the enclosing namespace if it is the name of
97+ // a variable;
98+ isSpecificationVariable ( decl )
99+ or
100+ // a function
101+ decl instanceof Function
102+ or
103+ decl instanceof Class and not decl .( Class ) .isAnonymous ( ) // a named class
104+ or
105+ decl instanceof Enum and not decl .( Enum ) .isAnonymous ( ) // a named enumeration
106+ or
107+ // a template
108+ decl instanceof TemplateClass
109+ or
110+ decl instanceof TemplateFunction
111+ or
112+ decl instanceof TemplateVariable
113+ )
114+ or
115+ hasNamespaceScope ( decl ) and
116+ exists ( TypedefType typedef | hasLinkageOfTypedef ( typedef , decl ) and ns = typedef .getNamespace ( ) )
117+ }
118+
119+ private predicate inheritsLinkageOfClass ( Class klass , Element decl ) {
120+ hasClassScope ( decl ) and
121+ (
122+ // a member function,
123+ decl .( MemberFunction ) .getDeclaringType ( ) = klass
124+ or
125+ // static data member
126+ decl .( MemberVariable ) .isStatic ( ) and decl .( MemberVariable ) .getDeclaringType ( ) = klass
157127 or
158- elem instanceof Namespace
128+ decl . ( Class ) . getDeclaringType ( ) = klass and not decl . ( Class ) . isAnonymous ( )
159129 or
160- elem instanceof TopLevelFunction
130+ decl .( Enum ) .getDeclaringType ( ) = klass and not decl .( Enum ) .isAnonymous ( )
131+ or
132+ exists ( TypedefType typedef |
133+ hasLinkageOfTypedef ( typedef , decl ) and klass = typedef .getDeclaringType ( )
134+ )
161135 )
162136}
0 commit comments