@@ -11,7 +11,110 @@ private import codeql.rust.elements.internal.generated.Element
1111 * be referenced directly.
1212 */
1313module Impl {
14+ private import rust
15+ private import codeql.rust.elements.internal.generated.ParentChild
16+ private import codeql.rust.elements.internal.generated.Synth
17+ private import codeql.rust.elements.internal.generated.Raw
18+ private import codeql.rust.elements.internal.LocationImpl
19+
20+ /**
21+ * Provides logic for classifying elements with respect to macro expansions.
22+ */
23+ cached
24+ module MacroExpansion {
25+ /**
26+ * Holds if `e` is superseded by an attribute macro expansion. That is, `e` is
27+ * a transitive child of an item with an attribute macro expansion.
28+ */
29+ private predicate supersededByAttributeMacroExpansionRaw ( Raw:: Item item , Raw:: Element e ) {
30+ exists ( item .getAttributeMacroExpansion ( ) ) and
31+ e = Raw:: getImmediateChild ( item , _) and
32+ not e = item .getAttributeMacroExpansion ( ) and
33+ // Don't consider attributes themselves to be superseded. E.g., in `#[a] fn
34+ // f() {}` the macro expansion supersedes `fn f() {}` but not `#[a]`.
35+ not e instanceof Raw:: Attr
36+ or
37+ exists ( Raw:: Element parent |
38+ e = Raw:: getImmediateChild ( parent , _) and
39+ supersededByAttributeMacroExpansionRaw ( item , parent )
40+ )
41+ }
42+
43+ private predicate isMacroExpansion ( AstNode macro , AstNode expansion ) {
44+ expansion = macro .( MacroCall ) .getMacroCallExpansion ( )
45+ or
46+ expansion = macro .( Adt ) .getDeriveMacroExpansion ( _)
47+ or
48+ expansion = macro .( Item ) .getAttributeMacroExpansion ( )
49+ }
50+
51+ /**
52+ * Gets the immediately enclosing macro call for element `e`, if any.
53+ *
54+ * The result is either a `MacroCall`, and `Adt` with a derive macro expansion, or
55+ * an `Item` with an attribute macro expansion.
56+ */
57+ cached
58+ AstNode getImmediatelyEnclosingMacroInvocation ( Element e ) {
59+ isMacroExpansion ( result , e )
60+ or
61+ exists ( Element mid |
62+ result = getImmediatelyEnclosingMacroInvocation ( mid ) and
63+ mid = getImmediateParent ( e ) and
64+ not isMacroExpansion ( mid , e )
65+ )
66+ }
67+
68+ pragma [ nomagic]
69+ private predicate isAttributeMacroExpansionSourceLocation ( Item i , Location l ) {
70+ exists ( Raw:: Locatable e , @location_default loc |
71+ supersededByAttributeMacroExpansionRaw ( Synth:: convertElementToRaw ( i ) , e ) and
72+ locatable_locations ( e , loc ) and
73+ l = LocationImpl:: TLocationDefault ( loc )
74+ )
75+ }
76+
77+ /** Gets an AST node whose location is inside the token tree belonging to `mc`. */
78+ pragma [ nomagic]
79+ private AstNode getATokenTreeNode ( MacroCall mc ) {
80+ mc = getImmediatelyEnclosingMacroInvocation ( result ) and
81+ mc .getTokenTree ( ) .getLocation ( ) .contains ( result .getLocation ( ) )
82+ }
83+
84+ /** Holds if `n` is inside a macro expansion. */
85+ cached
86+ predicate isInMacroExpansion ( AstNode n ) { exists ( getImmediatelyEnclosingMacroInvocation ( n ) ) }
87+
88+ /**
89+ * Holds if `n` exists only as the result of a macro expansion.
90+ *
91+ * This is the same as `isInMacroExpansion(n)`, but excludes AST nodes corresponding
92+ * to macro arguments, including attribute macro targets.
93+ */
94+ cached
95+ predicate isFromMacroExpansion ( AstNode n ) {
96+ exists ( AstNode macro |
97+ macro = getImmediatelyEnclosingMacroInvocation ( n ) and
98+ not n = getATokenTreeNode ( macro ) and
99+ not isAttributeMacroExpansionSourceLocation ( macro , n .getLocation ( ) )
100+ )
101+ }
102+
103+ cached
104+ predicate isRelevantElement ( Generated:: Element e ) {
105+ exists ( Raw:: Element raw |
106+ raw = Synth:: convertElementToRaw ( e ) and
107+ not supersededByAttributeMacroExpansionRaw ( _, raw )
108+ )
109+ or
110+ // Synthetic elements are relevant when their parent is
111+ Synth:: convertFormatArgsExprToRaw ( _) = Synth:: getSynthParent ( e )
112+ }
113+ }
114+
14115 class Element extends Generated:: Element {
116+ Element ( ) { MacroExpansion:: isRelevantElement ( this ) }
117+
15118 override string toStringImpl ( ) { result = this .getAPrimaryQlClass ( ) }
16119
17120 /**
0 commit comments