1
1
/**
2
2
* Provides queries to pretty-print a C++ AST as a graph.
3
3
*
4
- * By default, this will print the AST for all functions in the database. To change this behavior,
5
- * extend `PrintASTConfiguration` and override `shouldPrintFunction` to hold for only the functions
6
- * you wish to view the AST for.
4
+ * By default, this will print the AST for all functions and global and namespace variables in
5
+ * the database. To change this behavior, extend `PrintASTConfiguration` and override
6
+ * `shouldPrintDeclaration` to hold for only the declarations you wish to view the AST for.
7
7
*/
8
8
9
9
import cpp
@@ -12,7 +12,7 @@ private import semmle.code.cpp.Print
12
12
private newtype TPrintAstConfiguration = MkPrintAstConfiguration ( )
13
13
14
14
/**
15
- * The query can extend this class to control which functions are printed.
15
+ * The query can extend this class to control which declarations are printed.
16
16
*/
17
17
class PrintAstConfiguration extends TPrintAstConfiguration {
18
18
/**
@@ -21,14 +21,16 @@ class PrintAstConfiguration extends TPrintAstConfiguration {
21
21
string toString ( ) { result = "PrintASTConfiguration" }
22
22
23
23
/**
24
- * Holds if the AST for `func` should be printed. By default, holds for all
25
- * functions.
24
+ * Holds if the AST for `decl` should be printed. By default, holds for all
25
+ * functions and global and namespace variables. Currently, does not support any
26
+ * other declaration types.
26
27
*/
27
- predicate shouldPrintFunction ( Function func ) { any ( ) }
28
+ predicate shouldPrintDeclaration ( Declaration decl ) { any ( ) }
28
29
}
29
30
30
- private predicate shouldPrintFunction ( Function func ) {
31
- exists ( PrintAstConfiguration config | config .shouldPrintFunction ( func ) )
31
+ private predicate shouldPrintDeclaration ( Declaration decl ) {
32
+ exists ( PrintAstConfiguration config | config .shouldPrintDeclaration ( decl ) ) and
33
+ ( decl instanceof Function or decl instanceof GlobalOrNamespaceVariable )
32
34
}
33
35
34
36
bindingset [ s]
@@ -69,7 +71,7 @@ private predicate locationSortKeys(Locatable ast, string file, int line, int col
69
71
)
70
72
}
71
73
72
- private Function getEnclosingFunction ( Locatable ast ) {
74
+ private Declaration getAnEnclosingDeclaration ( Locatable ast ) {
73
75
result = ast .( Expr ) .getEnclosingFunction ( )
74
76
or
75
77
result = ast .( Stmt ) .getEnclosingFunction ( )
@@ -78,6 +80,10 @@ private Function getEnclosingFunction(Locatable ast) {
78
80
or
79
81
result = ast .( Parameter ) .getFunction ( )
80
82
or
83
+ result = ast .( Expr ) .getEnclosingDeclaration ( )
84
+ or
85
+ result = ast .( Initializer ) .getDeclaration ( )
86
+ or
81
87
result = ast
82
88
}
83
89
@@ -86,21 +92,21 @@ private Function getEnclosingFunction(Locatable ast) {
86
92
* nodes for things like parameter lists and constructor init lists.
87
93
*/
88
94
private newtype TPrintAstNode =
89
- TAstNode ( Locatable ast ) { shouldPrintFunction ( getEnclosingFunction ( ast ) ) } or
95
+ TAstNode ( Locatable ast ) { shouldPrintDeclaration ( getAnEnclosingDeclaration ( ast ) ) } or
90
96
TDeclarationEntryNode ( DeclStmt stmt , DeclarationEntry entry ) {
91
97
// We create a unique node for each pair of (stmt, entry), to avoid having one node with
92
98
// multiple parents due to extractor bug CPP-413.
93
99
stmt .getADeclarationEntry ( ) = entry and
94
- shouldPrintFunction ( stmt .getEnclosingFunction ( ) )
100
+ shouldPrintDeclaration ( stmt .getEnclosingFunction ( ) )
95
101
} or
96
- TParametersNode ( Function func ) { shouldPrintFunction ( func ) } or
102
+ TParametersNode ( Function func ) { shouldPrintDeclaration ( func ) } or
97
103
TConstructorInitializersNode ( Constructor ctor ) {
98
104
ctor .hasEntryPoint ( ) and
99
- shouldPrintFunction ( ctor )
105
+ shouldPrintDeclaration ( ctor )
100
106
} or
101
107
TDestructorDestructionsNode ( Destructor dtor ) {
102
108
dtor .hasEntryPoint ( ) and
103
- shouldPrintFunction ( dtor )
109
+ shouldPrintDeclaration ( dtor )
104
110
}
105
111
106
112
/**
@@ -158,10 +164,10 @@ class PrintAstNode extends TPrintAstNode {
158
164
159
165
/**
160
166
* Holds if this node should be printed in the output. By default, all nodes
161
- * within a function are printed, but the query can override
162
- * `PrintASTConfiguration.shouldPrintFunction ` to filter the output.
167
+ * within functions and global and namespace variables are printed, but the query
168
+ * can override `PrintASTConfiguration.shouldPrintDeclaration ` to filter the output.
163
169
*/
164
- final predicate shouldPrint ( ) { shouldPrintFunction ( this .getEnclosingFunction ( ) ) }
170
+ final predicate shouldPrint ( ) { shouldPrintDeclaration ( this .getEnclosingDeclaration ( ) ) }
165
171
166
172
/**
167
173
* Gets the children of this node.
@@ -229,10 +235,15 @@ class PrintAstNode extends TPrintAstNode {
229
235
abstract string getChildAccessorPredicateInternal ( int childIndex ) ;
230
236
231
237
/**
232
- * Gets the `Function` that contains this node.
238
+ * Gets the `Declaration` that contains this node.
239
+ */
240
+ private Declaration getEnclosingDeclaration ( ) { result = this .getParent * ( ) .getDeclaration ( ) }
241
+
242
+ /**
243
+ * Gets the `Declaration` this node represents.
233
244
*/
234
- private Function getEnclosingFunction ( ) {
235
- result = this .getParent * ( ) . ( FunctionNode ) . getFunction ( )
245
+ private Declaration getDeclaration ( ) {
246
+ result = this .( AstNode ) . getAst ( ) and shouldPrintDeclaration ( result )
236
247
}
237
248
}
238
249
@@ -571,16 +582,53 @@ class DestructorDestructionsNode extends PrintAstNode, TDestructorDestructionsNo
571
582
final Destructor getDestructor ( ) { result = dtor }
572
583
}
573
584
585
+ abstract private class FunctionOrGlobalOrNamespaceVariableNode extends AstNode {
586
+ override string toString ( ) { result = qlClass ( ast ) + getIdentityString ( ast ) }
587
+
588
+ private int getOrder ( ) {
589
+ this =
590
+ rank [ result ] ( FunctionOrGlobalOrNamespaceVariableNode node , Declaration decl , string file ,
591
+ int line , int column |
592
+ node .getAst ( ) = decl and
593
+ locationSortKeys ( decl , file , line , column )
594
+ |
595
+ node order by file , line , column , getIdentityString ( decl )
596
+ )
597
+ }
598
+
599
+ override string getProperty ( string key ) {
600
+ result = super .getProperty ( key )
601
+ or
602
+ key = "semmle.order" and result = this .getOrder ( ) .toString ( )
603
+ }
604
+ }
605
+
606
+ /**
607
+ * A node representing a `GlobalOrNamespaceVariable`.
608
+ */
609
+ class GlobalOrNamespaceVariableNode extends FunctionOrGlobalOrNamespaceVariableNode {
610
+ GlobalOrNamespaceVariable var ;
611
+
612
+ GlobalOrNamespaceVariableNode ( ) { var = ast }
613
+
614
+ override PrintAstNode getChildInternal ( int childIndex ) {
615
+ childIndex = 0 and
616
+ result .( AstNode ) .getAst ( ) = var .getInitializer ( )
617
+ }
618
+
619
+ override string getChildAccessorPredicateInternal ( int childIndex ) {
620
+ childIndex = 0 and result = "getInitializer()"
621
+ }
622
+ }
623
+
574
624
/**
575
625
* A node representing a `Function`.
576
626
*/
577
- class FunctionNode extends AstNode {
627
+ class FunctionNode extends FunctionOrGlobalOrNamespaceVariableNode {
578
628
Function func ;
579
629
580
630
FunctionNode ( ) { func = ast }
581
631
582
- override string toString ( ) { result = qlClass ( func ) + getIdentityString ( func ) }
583
-
584
632
override PrintAstNode getChildInternal ( int childIndex ) {
585
633
childIndex = 0 and
586
634
result .( ParametersNode ) .getFunction ( ) = func
@@ -604,31 +652,10 @@ class FunctionNode extends AstNode {
604
652
or
605
653
childIndex = 3 and result = "<destructions>"
606
654
}
607
-
608
- private int getOrder ( ) {
609
- this =
610
- rank [ result ] ( FunctionNode node , Function function , string file , int line , int column |
611
- node .getAst ( ) = function and
612
- locationSortKeys ( function , file , line , column )
613
- |
614
- node order by file , line , column , getIdentityString ( function )
615
- )
616
- }
617
-
618
- override string getProperty ( string key ) {
619
- result = super .getProperty ( key )
620
- or
621
- key = "semmle.order" and result = this .getOrder ( ) .toString ( )
622
- }
623
-
624
- /**
625
- * Gets the `Function` this node represents.
626
- */
627
- final Function getFunction ( ) { result = func }
628
655
}
629
656
630
657
private string getChildAccessorWithoutConversions ( Locatable parent , Element child ) {
631
- shouldPrintFunction ( getEnclosingFunction ( parent ) ) and
658
+ shouldPrintDeclaration ( getAnEnclosingDeclaration ( parent ) ) and
632
659
(
633
660
exists ( Stmt s | s = parent |
634
661
namedStmtChildPredicates ( s , child , result )
@@ -647,7 +674,7 @@ private string getChildAccessorWithoutConversions(Locatable parent, Element chil
647
674
}
648
675
649
676
private predicate namedStmtChildPredicates ( Locatable s , Element e , string pred ) {
650
- shouldPrintFunction ( getEnclosingFunction ( s ) ) and
677
+ shouldPrintDeclaration ( getAnEnclosingDeclaration ( s ) ) and
651
678
(
652
679
exists ( int n | s .( BlockStmt ) .getStmt ( n ) = e and pred = "getStmt(" + n + ")" )
653
680
or
@@ -735,7 +762,7 @@ private predicate namedStmtChildPredicates(Locatable s, Element e, string pred)
735
762
}
736
763
737
764
private predicate namedExprChildPredicates ( Expr expr , Element ele , string pred ) {
738
- shouldPrintFunction ( expr .getEnclosingFunction ( ) ) and
765
+ shouldPrintDeclaration ( expr .getEnclosingDeclaration ( ) ) and
739
766
(
740
767
expr .( Access ) .getTarget ( ) = ele and pred = "getTarget()"
741
768
or
0 commit comments