Skip to content

Commit a4a4926

Browse files
authored
Merge pull request #13775 from jketema/print-global
C++: Support printing of global and namespace variables in `PrintAST`
2 parents aa59741 + 409471c commit a4a4926

File tree

17 files changed

+266
-121
lines changed

17 files changed

+266
-121
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
category: breaking
3+
---
4+
* The `shouldPrintFunction` predicate from `PrintAstConfiguration` has been replaced by `shouldPrintDeclaration`. Users should now override `shouldPrintDeclaration` if they want to limit the declarations that should be printed.
5+
* The `shouldPrintFunction` predicate from `PrintIRConfiguration` has been replaced by `shouldPrintDeclaration`. Users should now override `shouldPrintDeclaration` if they want to limit the declarations that should be printed.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: majorAnalysis
3+
---
4+
* The `PrintAST` library now also prints global and namespace variables and their initializers.

cpp/ql/lib/printAst.ql

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ external string selectedSourceFile();
1818

1919
class Cfg extends PrintAstConfiguration {
2020
/**
21-
* Holds if the AST for `func` should be printed.
22-
* Print All functions from the selected file.
21+
* Holds if the AST for `decl` should be printed.
22+
* Print All declarations from the selected file.
2323
*/
24-
override predicate shouldPrintFunction(Function func) {
25-
func.getFile() = getFileBySourceArchiveName(selectedSourceFile())
24+
override predicate shouldPrintDeclaration(Declaration decl) {
25+
decl.getFile() = getFileBySourceArchiveName(selectedSourceFile())
2626
}
2727
}

cpp/ql/lib/semmle/code/cpp/Print.qll

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,9 @@ private import PrintAST
66
* that requests that function, or no `PrintASTConfiguration` exists.
77
*/
88
private predicate shouldPrintDeclaration(Declaration decl) {
9-
not decl instanceof Function
9+
not (decl instanceof Function or decl instanceof GlobalOrNamespaceVariable)
1010
or
11-
not exists(PrintAstConfiguration c)
12-
or
13-
exists(PrintAstConfiguration config | config.shouldPrintFunction(decl))
11+
exists(PrintAstConfiguration config | config.shouldPrintDeclaration(decl))
1412
}
1513

1614
/**

cpp/ql/lib/semmle/code/cpp/PrintAST.ql

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ import cpp
99
import PrintAST
1010

1111
/**
12-
* Temporarily tweak this class or make a copy to control which functions are
12+
* Temporarily tweak this class or make a copy to control which declarations are
1313
* printed.
1414
*/
1515
class Cfg extends PrintAstConfiguration {
1616
/**
1717
* TWEAK THIS PREDICATE AS NEEDED.
18-
* Holds if the AST for `func` should be printed.
18+
* Holds if the AST for `decl` should be printed.
1919
*/
20-
override predicate shouldPrintFunction(Function func) { any() }
20+
override predicate shouldPrintDeclaration(Declaration decl) { any() }
2121
}

cpp/ql/lib/semmle/code/cpp/PrintAST.qll

Lines changed: 75 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
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

99
import cpp
@@ -12,7 +12,7 @@ private import semmle.code.cpp.Print
1212
private 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
*/
1717
class 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

3436
bindingset[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
*/
8894
private 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

630657
private 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

649676
private 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

737764
private 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

cpp/ql/lib/semmle/code/cpp/ir/PrintIR.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
* This file contains the actual implementation of `PrintIR.ql`. For test cases and very small
55
* databases, `PrintIR.ql` can be run directly to dump the IR for the entire database. For most
66
* uses, however, it is better to write a query that imports `PrintIR.qll`, extends
7-
* `PrintIRConfiguration`, and overrides `shouldPrintFunction()` to select a subset of functions to
8-
* dump.
7+
* `PrintIRConfiguration`, and overrides `shouldPrintDeclaration()` to select a subset of declarations
8+
* to dump.
99
*/
1010

1111
import implementation.aliased_ssa.PrintIR

cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/PrintIR.qll

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
* This file contains the actual implementation of `PrintIR.ql`. For test cases and very small
55
* databases, `PrintIR.ql` can be run directly to dump the IR for the entire database. For most
66
* uses, however, it is better to write a query that imports `PrintIR.qll`, extends
7-
* `PrintIRConfiguration`, and overrides `shouldPrintFunction()` to select a subset of functions to
8-
* dump.
7+
* `PrintIRConfiguration`, and overrides `shouldPrintDeclaration()` to select a subset of declarations
8+
* to dump.
99
*/
1010

1111
private import internal.IRInternal
@@ -16,30 +16,30 @@ import Imports::IRConfiguration
1616
private newtype TPrintIRConfiguration = MkPrintIRConfiguration()
1717

1818
/**
19-
* The query can extend this class to control which functions are printed.
19+
* The query can extend this class to control which declarations are printed.
2020
*/
2121
class PrintIRConfiguration extends TPrintIRConfiguration {
2222
/** Gets a textual representation of this configuration. */
2323
string toString() { result = "PrintIRConfiguration" }
2424

2525
/**
2626
* Holds if the IR for `func` should be printed. By default, holds for all
27-
* functions.
27+
* functions, global and namespace variables, and static local variables.
2828
*/
29-
predicate shouldPrintFunction(Language::Declaration decl) { any() }
29+
predicate shouldPrintDeclaration(Language::Declaration decl) { any() }
3030
}
3131

3232
/**
3333
* Override of `IRConfiguration` to only evaluate debug strings for the functions that are to be dumped.
3434
*/
3535
private class FilteredIRConfiguration extends IRConfiguration {
3636
override predicate shouldEvaluateDebugStringsForFunction(Language::Declaration func) {
37-
shouldPrintFunction(func)
37+
shouldPrintDeclaration(func)
3838
}
3939
}
4040

41-
private predicate shouldPrintFunction(Language::Declaration decl) {
42-
exists(PrintIRConfiguration config | config.shouldPrintFunction(decl))
41+
private predicate shouldPrintDeclaration(Language::Declaration decl) {
42+
exists(PrintIRConfiguration config | config.shouldPrintDeclaration(decl))
4343
}
4444

4545
private predicate shouldPrintInstruction(Instruction i) {
@@ -90,10 +90,10 @@ private string getOperandPropertyString(Operand operand) {
9090
}
9191

9292
private newtype TPrintableIRNode =
93-
TPrintableIRFunction(IRFunction irFunc) { shouldPrintFunction(irFunc.getFunction()) } or
94-
TPrintableIRBlock(IRBlock block) { shouldPrintFunction(block.getEnclosingFunction()) } or
93+
TPrintableIRFunction(IRFunction irFunc) { shouldPrintDeclaration(irFunc.getFunction()) } or
94+
TPrintableIRBlock(IRBlock block) { shouldPrintDeclaration(block.getEnclosingFunction()) } or
9595
TPrintableInstruction(Instruction instr) {
96-
shouldPrintInstruction(instr) and shouldPrintFunction(instr.getEnclosingFunction())
96+
shouldPrintInstruction(instr) and shouldPrintDeclaration(instr.getEnclosingFunction())
9797
}
9898

9999
/**

0 commit comments

Comments
 (0)