11/**
22 * Provides queries to pretty-print a C++ AST as a graph.
33 *
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.
77 */
88
99import cpp
@@ -12,7 +12,7 @@ private import semmle.code.cpp.Print
1212private newtype TPrintAstConfiguration = MkPrintAstConfiguration ( )
1313
1414/**
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.
1616 */
1717class PrintAstConfiguration extends TPrintAstConfiguration {
1818 /**
@@ -21,14 +21,16 @@ class PrintAstConfiguration extends TPrintAstConfiguration {
2121 string toString ( ) { result = "PrintASTConfiguration" }
2222
2323 /**
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.
2627 */
27- predicate shouldPrintFunction ( Function func ) { any ( ) }
28+ predicate shouldPrintDeclaration ( Declaration decl ) { any ( ) }
2829}
2930
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 )
3234}
3335
3436bindingset [ s]
@@ -69,7 +71,7 @@ private predicate locationSortKeys(Locatable ast, string file, int line, int col
6971 )
7072}
7173
72- private Function getEnclosingFunction ( Locatable ast ) {
74+ private Declaration getAnEnclosingDeclaration ( Locatable ast ) {
7375 result = ast .( Expr ) .getEnclosingFunction ( )
7476 or
7577 result = ast .( Stmt ) .getEnclosingFunction ( )
@@ -78,6 +80,10 @@ private Function getEnclosingFunction(Locatable ast) {
7880 or
7981 result = ast .( Parameter ) .getFunction ( )
8082 or
83+ result = ast .( Expr ) .getEnclosingDeclaration ( )
84+ or
85+ result = ast .( Initializer ) .getDeclaration ( )
86+ or
8187 result = ast
8288}
8389
@@ -86,21 +92,21 @@ private Function getEnclosingFunction(Locatable ast) {
8692 * nodes for things like parameter lists and constructor init lists.
8793 */
8894private newtype TPrintAstNode =
89- TAstNode ( Locatable ast ) { shouldPrintFunction ( getEnclosingFunction ( ast ) ) } or
95+ TAstNode ( Locatable ast ) { shouldPrintDeclaration ( getAnEnclosingDeclaration ( ast ) ) } or
9096 TDeclarationEntryNode ( DeclStmt stmt , DeclarationEntry entry ) {
9197 // We create a unique node for each pair of (stmt, entry), to avoid having one node with
9298 // multiple parents due to extractor bug CPP-413.
9399 stmt .getADeclarationEntry ( ) = entry and
94- shouldPrintFunction ( stmt .getEnclosingFunction ( ) )
100+ shouldPrintDeclaration ( stmt .getEnclosingFunction ( ) )
95101 } or
96- TParametersNode ( Function func ) { shouldPrintFunction ( func ) } or
102+ TParametersNode ( Function func ) { shouldPrintDeclaration ( func ) } or
97103 TConstructorInitializersNode ( Constructor ctor ) {
98104 ctor .hasEntryPoint ( ) and
99- shouldPrintFunction ( ctor )
105+ shouldPrintDeclaration ( ctor )
100106 } or
101107 TDestructorDestructionsNode ( Destructor dtor ) {
102108 dtor .hasEntryPoint ( ) and
103- shouldPrintFunction ( dtor )
109+ shouldPrintDeclaration ( dtor )
104110 }
105111
106112/**
@@ -158,10 +164,10 @@ class PrintAstNode extends TPrintAstNode {
158164
159165 /**
160166 * 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.
163169 */
164- final predicate shouldPrint ( ) { shouldPrintFunction ( this .getEnclosingFunction ( ) ) }
170+ final predicate shouldPrint ( ) { shouldPrintDeclaration ( this .getEnclosingDeclaration ( ) ) }
165171
166172 /**
167173 * Gets the children of this node.
@@ -229,10 +235,15 @@ class PrintAstNode extends TPrintAstNode {
229235 abstract string getChildAccessorPredicateInternal ( int childIndex ) ;
230236
231237 /**
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.
233244 */
234- private Function getEnclosingFunction ( ) {
235- result = this .getParent * ( ) . ( FunctionNode ) . getFunction ( )
245+ private Declaration getDeclaration ( ) {
246+ result = this .( AstNode ) . getAst ( ) and shouldPrintDeclaration ( result )
236247 }
237248}
238249
@@ -571,16 +582,53 @@ class DestructorDestructionsNode extends PrintAstNode, TDestructorDestructionsNo
571582 final Destructor getDestructor ( ) { result = dtor }
572583}
573584
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+
574624/**
575625 * A node representing a `Function`.
576626 */
577- class FunctionNode extends AstNode {
627+ class FunctionNode extends FunctionOrGlobalOrNamespaceVariableNode {
578628 Function func ;
579629
580630 FunctionNode ( ) { func = ast }
581631
582- override string toString ( ) { result = qlClass ( func ) + getIdentityString ( func ) }
583-
584632 override PrintAstNode getChildInternal ( int childIndex ) {
585633 childIndex = 0 and
586634 result .( ParametersNode ) .getFunction ( ) = func
@@ -604,31 +652,10 @@ class FunctionNode extends AstNode {
604652 or
605653 childIndex = 3 and result = "<destructions>"
606654 }
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 }
628655}
629656
630657private string getChildAccessorWithoutConversions ( Locatable parent , Element child ) {
631- shouldPrintFunction ( getEnclosingFunction ( parent ) ) and
658+ shouldPrintDeclaration ( getAnEnclosingDeclaration ( parent ) ) and
632659 (
633660 exists ( Stmt s | s = parent |
634661 namedStmtChildPredicates ( s , child , result )
@@ -647,7 +674,7 @@ private string getChildAccessorWithoutConversions(Locatable parent, Element chil
647674}
648675
649676private predicate namedStmtChildPredicates ( Locatable s , Element e , string pred ) {
650- shouldPrintFunction ( getEnclosingFunction ( s ) ) and
677+ shouldPrintDeclaration ( getAnEnclosingDeclaration ( s ) ) and
651678 (
652679 exists ( int n | s .( BlockStmt ) .getStmt ( n ) = e and pred = "getStmt(" + n + ")" )
653680 or
@@ -735,7 +762,7 @@ private predicate namedStmtChildPredicates(Locatable s, Element e, string pred)
735762}
736763
737764private predicate namedExprChildPredicates ( Expr expr , Element ele , string pred ) {
738- shouldPrintFunction ( expr .getEnclosingFunction ( ) ) and
765+ shouldPrintDeclaration ( expr .getEnclosingDeclaration ( ) ) and
739766 (
740767 expr .( Access ) .getTarget ( ) = ele and pred = "getTarget()"
741768 or
0 commit comments