diff --git a/cpp/ql/lib/change-notes/2023-07-19-rename-should-print-function.md b/cpp/ql/lib/change-notes/2023-07-19-rename-should-print-function.md new file mode 100644 index 000000000000..61ebd0aab346 --- /dev/null +++ b/cpp/ql/lib/change-notes/2023-07-19-rename-should-print-function.md @@ -0,0 +1,5 @@ +--- +category: breaking +--- +* 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. +* 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. diff --git a/cpp/ql/lib/change-notes/2023-07-20-print-global-variables.md b/cpp/ql/lib/change-notes/2023-07-20-print-global-variables.md new file mode 100644 index 000000000000..95a2a396cbb4 --- /dev/null +++ b/cpp/ql/lib/change-notes/2023-07-20-print-global-variables.md @@ -0,0 +1,4 @@ +--- +category: majorAnalysis +--- +* The `PrintAST` library now also prints global and namespace variables and their initializers. diff --git a/cpp/ql/lib/printAst.ql b/cpp/ql/lib/printAst.ql index ae6b3052ec7c..2023beaec130 100644 --- a/cpp/ql/lib/printAst.ql +++ b/cpp/ql/lib/printAst.ql @@ -18,10 +18,10 @@ external string selectedSourceFile(); class Cfg extends PrintAstConfiguration { /** - * Holds if the AST for `func` should be printed. - * Print All functions from the selected file. + * Holds if the AST for `decl` should be printed. + * Print All declarations from the selected file. */ - override predicate shouldPrintFunction(Function func) { - func.getFile() = getFileBySourceArchiveName(selectedSourceFile()) + override predicate shouldPrintDeclaration(Declaration decl) { + decl.getFile() = getFileBySourceArchiveName(selectedSourceFile()) } } diff --git a/cpp/ql/lib/semmle/code/cpp/Print.qll b/cpp/ql/lib/semmle/code/cpp/Print.qll index 5df8f0876893..28a18bb0ac41 100644 --- a/cpp/ql/lib/semmle/code/cpp/Print.qll +++ b/cpp/ql/lib/semmle/code/cpp/Print.qll @@ -6,11 +6,9 @@ private import PrintAST * that requests that function, or no `PrintASTConfiguration` exists. */ private predicate shouldPrintDeclaration(Declaration decl) { - not decl instanceof Function + not (decl instanceof Function or decl instanceof GlobalOrNamespaceVariable) or - not exists(PrintAstConfiguration c) - or - exists(PrintAstConfiguration config | config.shouldPrintFunction(decl)) + exists(PrintAstConfiguration config | config.shouldPrintDeclaration(decl)) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/PrintAST.ql b/cpp/ql/lib/semmle/code/cpp/PrintAST.ql index bf7e345132c2..edf9ffec1e07 100644 --- a/cpp/ql/lib/semmle/code/cpp/PrintAST.ql +++ b/cpp/ql/lib/semmle/code/cpp/PrintAST.ql @@ -9,13 +9,13 @@ import cpp import PrintAST /** - * Temporarily tweak this class or make a copy to control which functions are + * Temporarily tweak this class or make a copy to control which declarations are * printed. */ class Cfg extends PrintAstConfiguration { /** * TWEAK THIS PREDICATE AS NEEDED. - * Holds if the AST for `func` should be printed. + * Holds if the AST for `decl` should be printed. */ - override predicate shouldPrintFunction(Function func) { any() } + override predicate shouldPrintDeclaration(Declaration decl) { any() } } diff --git a/cpp/ql/lib/semmle/code/cpp/PrintAST.qll b/cpp/ql/lib/semmle/code/cpp/PrintAST.qll index b552c6eeb383..46d9b34d8900 100644 --- a/cpp/ql/lib/semmle/code/cpp/PrintAST.qll +++ b/cpp/ql/lib/semmle/code/cpp/PrintAST.qll @@ -1,9 +1,9 @@ /** * Provides queries to pretty-print a C++ AST as a graph. * - * By default, this will print the AST for all functions in the database. To change this behavior, - * extend `PrintASTConfiguration` and override `shouldPrintFunction` to hold for only the functions - * you wish to view the AST for. + * By default, this will print the AST for all functions and global and namespace variables in + * the database. To change this behavior, extend `PrintASTConfiguration` and override + * `shouldPrintDeclaration` to hold for only the declarations you wish to view the AST for. */ import cpp @@ -12,7 +12,7 @@ private import semmle.code.cpp.Print private newtype TPrintAstConfiguration = MkPrintAstConfiguration() /** - * The query can extend this class to control which functions are printed. + * The query can extend this class to control which declarations are printed. */ class PrintAstConfiguration extends TPrintAstConfiguration { /** @@ -21,14 +21,16 @@ class PrintAstConfiguration extends TPrintAstConfiguration { string toString() { result = "PrintASTConfiguration" } /** - * Holds if the AST for `func` should be printed. By default, holds for all - * functions. + * Holds if the AST for `decl` should be printed. By default, holds for all + * functions and global and namespace variables. Currently, does not support any + * other declaration types. */ - predicate shouldPrintFunction(Function func) { any() } + predicate shouldPrintDeclaration(Declaration decl) { any() } } -private predicate shouldPrintFunction(Function func) { - exists(PrintAstConfiguration config | config.shouldPrintFunction(func)) +private predicate shouldPrintDeclaration(Declaration decl) { + exists(PrintAstConfiguration config | config.shouldPrintDeclaration(decl)) and + (decl instanceof Function or decl instanceof GlobalOrNamespaceVariable) } bindingset[s] @@ -69,7 +71,7 @@ private predicate locationSortKeys(Locatable ast, string file, int line, int col ) } -private Function getEnclosingFunction(Locatable ast) { +private Declaration getAnEnclosingDeclaration(Locatable ast) { result = ast.(Expr).getEnclosingFunction() or result = ast.(Stmt).getEnclosingFunction() @@ -78,6 +80,10 @@ private Function getEnclosingFunction(Locatable ast) { or result = ast.(Parameter).getFunction() or + result = ast.(Expr).getEnclosingDeclaration() + or + result = ast.(Initializer).getDeclaration() + or result = ast } @@ -86,21 +92,21 @@ private Function getEnclosingFunction(Locatable ast) { * nodes for things like parameter lists and constructor init lists. */ private newtype TPrintAstNode = - TAstNode(Locatable ast) { shouldPrintFunction(getEnclosingFunction(ast)) } or + TAstNode(Locatable ast) { shouldPrintDeclaration(getAnEnclosingDeclaration(ast)) } or TDeclarationEntryNode(DeclStmt stmt, DeclarationEntry entry) { // We create a unique node for each pair of (stmt, entry), to avoid having one node with // multiple parents due to extractor bug CPP-413. stmt.getADeclarationEntry() = entry and - shouldPrintFunction(stmt.getEnclosingFunction()) + shouldPrintDeclaration(stmt.getEnclosingFunction()) } or - TParametersNode(Function func) { shouldPrintFunction(func) } or + TParametersNode(Function func) { shouldPrintDeclaration(func) } or TConstructorInitializersNode(Constructor ctor) { ctor.hasEntryPoint() and - shouldPrintFunction(ctor) + shouldPrintDeclaration(ctor) } or TDestructorDestructionsNode(Destructor dtor) { dtor.hasEntryPoint() and - shouldPrintFunction(dtor) + shouldPrintDeclaration(dtor) } /** @@ -158,10 +164,10 @@ class PrintAstNode extends TPrintAstNode { /** * Holds if this node should be printed in the output. By default, all nodes - * within a function are printed, but the query can override - * `PrintASTConfiguration.shouldPrintFunction` to filter the output. + * within functions and global and namespace variables are printed, but the query + * can override `PrintASTConfiguration.shouldPrintDeclaration` to filter the output. */ - final predicate shouldPrint() { shouldPrintFunction(this.getEnclosingFunction()) } + final predicate shouldPrint() { shouldPrintDeclaration(this.getEnclosingDeclaration()) } /** * Gets the children of this node. @@ -229,10 +235,15 @@ class PrintAstNode extends TPrintAstNode { abstract string getChildAccessorPredicateInternal(int childIndex); /** - * Gets the `Function` that contains this node. + * Gets the `Declaration` that contains this node. + */ + private Declaration getEnclosingDeclaration() { result = this.getParent*().getDeclaration() } + + /** + * Gets the `Declaration` this node represents. */ - private Function getEnclosingFunction() { - result = this.getParent*().(FunctionNode).getFunction() + private Declaration getDeclaration() { + result = this.(AstNode).getAst() and shouldPrintDeclaration(result) } } @@ -571,16 +582,53 @@ class DestructorDestructionsNode extends PrintAstNode, TDestructorDestructionsNo final Destructor getDestructor() { result = dtor } } +abstract private class FunctionOrGlobalOrNamespaceVariableNode extends AstNode { + override string toString() { result = qlClass(ast) + getIdentityString(ast) } + + private int getOrder() { + this = + rank[result](FunctionOrGlobalOrNamespaceVariableNode node, Declaration decl, string file, + int line, int column | + node.getAst() = decl and + locationSortKeys(decl, file, line, column) + | + node order by file, line, column, getIdentityString(decl) + ) + } + + override string getProperty(string key) { + result = super.getProperty(key) + or + key = "semmle.order" and result = this.getOrder().toString() + } +} + +/** + * A node representing a `GlobalOrNamespaceVariable`. + */ +class GlobalOrNamespaceVariableNode extends FunctionOrGlobalOrNamespaceVariableNode { + GlobalOrNamespaceVariable var; + + GlobalOrNamespaceVariableNode() { var = ast } + + override PrintAstNode getChildInternal(int childIndex) { + childIndex = 0 and + result.(AstNode).getAst() = var.getInitializer() + } + + override string getChildAccessorPredicateInternal(int childIndex) { + childIndex = 0 and result = "getInitializer()" + } +} + /** * A node representing a `Function`. */ -class FunctionNode extends AstNode { +class FunctionNode extends FunctionOrGlobalOrNamespaceVariableNode { Function func; FunctionNode() { func = ast } - override string toString() { result = qlClass(func) + getIdentityString(func) } - override PrintAstNode getChildInternal(int childIndex) { childIndex = 0 and result.(ParametersNode).getFunction() = func @@ -604,31 +652,10 @@ class FunctionNode extends AstNode { or childIndex = 3 and result = "" } - - private int getOrder() { - this = - rank[result](FunctionNode node, Function function, string file, int line, int column | - node.getAst() = function and - locationSortKeys(function, file, line, column) - | - node order by file, line, column, getIdentityString(function) - ) - } - - override string getProperty(string key) { - result = super.getProperty(key) - or - key = "semmle.order" and result = this.getOrder().toString() - } - - /** - * Gets the `Function` this node represents. - */ - final Function getFunction() { result = func } } private string getChildAccessorWithoutConversions(Locatable parent, Element child) { - shouldPrintFunction(getEnclosingFunction(parent)) and + shouldPrintDeclaration(getAnEnclosingDeclaration(parent)) and ( exists(Stmt s | s = parent | namedStmtChildPredicates(s, child, result) @@ -647,7 +674,7 @@ private string getChildAccessorWithoutConversions(Locatable parent, Element chil } private predicate namedStmtChildPredicates(Locatable s, Element e, string pred) { - shouldPrintFunction(getEnclosingFunction(s)) and + shouldPrintDeclaration(getAnEnclosingDeclaration(s)) and ( exists(int n | s.(BlockStmt).getStmt(n) = e and pred = "getStmt(" + n + ")") or @@ -735,7 +762,7 @@ private predicate namedStmtChildPredicates(Locatable s, Element e, string pred) } private predicate namedExprChildPredicates(Expr expr, Element ele, string pred) { - shouldPrintFunction(expr.getEnclosingFunction()) and + shouldPrintDeclaration(expr.getEnclosingDeclaration()) and ( expr.(Access).getTarget() = ele and pred = "getTarget()" or diff --git a/cpp/ql/lib/semmle/code/cpp/ir/PrintIR.qll b/cpp/ql/lib/semmle/code/cpp/ir/PrintIR.qll index c4ebf2f1eba2..19ba71590897 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/PrintIR.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/PrintIR.qll @@ -4,8 +4,8 @@ * This file contains the actual implementation of `PrintIR.ql`. For test cases and very small * databases, `PrintIR.ql` can be run directly to dump the IR for the entire database. For most * uses, however, it is better to write a query that imports `PrintIR.qll`, extends - * `PrintIRConfiguration`, and overrides `shouldPrintFunction()` to select a subset of functions to - * dump. + * `PrintIRConfiguration`, and overrides `shouldPrintDeclaration()` to select a subset of declarations + * to dump. */ import implementation.aliased_ssa.PrintIR diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/PrintIR.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/PrintIR.qll index b9106a7bfc73..c4b18d9cb61c 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/PrintIR.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/PrintIR.qll @@ -4,8 +4,8 @@ * This file contains the actual implementation of `PrintIR.ql`. For test cases and very small * databases, `PrintIR.ql` can be run directly to dump the IR for the entire database. For most * uses, however, it is better to write a query that imports `PrintIR.qll`, extends - * `PrintIRConfiguration`, and overrides `shouldPrintFunction()` to select a subset of functions to - * dump. + * `PrintIRConfiguration`, and overrides `shouldPrintDeclaration()` to select a subset of declarations + * to dump. */ private import internal.IRInternal @@ -16,7 +16,7 @@ import Imports::IRConfiguration private newtype TPrintIRConfiguration = MkPrintIRConfiguration() /** - * The query can extend this class to control which functions are printed. + * The query can extend this class to control which declarations are printed. */ class PrintIRConfiguration extends TPrintIRConfiguration { /** Gets a textual representation of this configuration. */ @@ -24,9 +24,9 @@ class PrintIRConfiguration extends TPrintIRConfiguration { /** * Holds if the IR for `func` should be printed. By default, holds for all - * functions. + * functions, global and namespace variables, and static local variables. */ - predicate shouldPrintFunction(Language::Declaration decl) { any() } + predicate shouldPrintDeclaration(Language::Declaration decl) { any() } } /** @@ -34,12 +34,12 @@ class PrintIRConfiguration extends TPrintIRConfiguration { */ private class FilteredIRConfiguration extends IRConfiguration { override predicate shouldEvaluateDebugStringsForFunction(Language::Declaration func) { - shouldPrintFunction(func) + shouldPrintDeclaration(func) } } -private predicate shouldPrintFunction(Language::Declaration decl) { - exists(PrintIRConfiguration config | config.shouldPrintFunction(decl)) +private predicate shouldPrintDeclaration(Language::Declaration decl) { + exists(PrintIRConfiguration config | config.shouldPrintDeclaration(decl)) } private predicate shouldPrintInstruction(Instruction i) { @@ -90,10 +90,10 @@ private string getOperandPropertyString(Operand operand) { } private newtype TPrintableIRNode = - TPrintableIRFunction(IRFunction irFunc) { shouldPrintFunction(irFunc.getFunction()) } or - TPrintableIRBlock(IRBlock block) { shouldPrintFunction(block.getEnclosingFunction()) } or + TPrintableIRFunction(IRFunction irFunc) { shouldPrintDeclaration(irFunc.getFunction()) } or + TPrintableIRBlock(IRBlock block) { shouldPrintDeclaration(block.getEnclosingFunction()) } or TPrintableInstruction(Instruction instr) { - shouldPrintInstruction(instr) and shouldPrintFunction(instr.getEnclosingFunction()) + shouldPrintInstruction(instr) and shouldPrintDeclaration(instr.getEnclosingFunction()) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/PrintIR.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/PrintIR.qll index b9106a7bfc73..c4b18d9cb61c 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/PrintIR.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/PrintIR.qll @@ -4,8 +4,8 @@ * This file contains the actual implementation of `PrintIR.ql`. For test cases and very small * databases, `PrintIR.ql` can be run directly to dump the IR for the entire database. For most * uses, however, it is better to write a query that imports `PrintIR.qll`, extends - * `PrintIRConfiguration`, and overrides `shouldPrintFunction()` to select a subset of functions to - * dump. + * `PrintIRConfiguration`, and overrides `shouldPrintDeclaration()` to select a subset of declarations + * to dump. */ private import internal.IRInternal @@ -16,7 +16,7 @@ import Imports::IRConfiguration private newtype TPrintIRConfiguration = MkPrintIRConfiguration() /** - * The query can extend this class to control which functions are printed. + * The query can extend this class to control which declarations are printed. */ class PrintIRConfiguration extends TPrintIRConfiguration { /** Gets a textual representation of this configuration. */ @@ -24,9 +24,9 @@ class PrintIRConfiguration extends TPrintIRConfiguration { /** * Holds if the IR for `func` should be printed. By default, holds for all - * functions. + * functions, global and namespace variables, and static local variables. */ - predicate shouldPrintFunction(Language::Declaration decl) { any() } + predicate shouldPrintDeclaration(Language::Declaration decl) { any() } } /** @@ -34,12 +34,12 @@ class PrintIRConfiguration extends TPrintIRConfiguration { */ private class FilteredIRConfiguration extends IRConfiguration { override predicate shouldEvaluateDebugStringsForFunction(Language::Declaration func) { - shouldPrintFunction(func) + shouldPrintDeclaration(func) } } -private predicate shouldPrintFunction(Language::Declaration decl) { - exists(PrintIRConfiguration config | config.shouldPrintFunction(decl)) +private predicate shouldPrintDeclaration(Language::Declaration decl) { + exists(PrintIRConfiguration config | config.shouldPrintDeclaration(decl)) } private predicate shouldPrintInstruction(Instruction i) { @@ -90,10 +90,10 @@ private string getOperandPropertyString(Operand operand) { } private newtype TPrintableIRNode = - TPrintableIRFunction(IRFunction irFunc) { shouldPrintFunction(irFunc.getFunction()) } or - TPrintableIRBlock(IRBlock block) { shouldPrintFunction(block.getEnclosingFunction()) } or + TPrintableIRFunction(IRFunction irFunc) { shouldPrintDeclaration(irFunc.getFunction()) } or + TPrintableIRBlock(IRBlock block) { shouldPrintDeclaration(block.getEnclosingFunction()) } or TPrintableInstruction(Instruction instr) { - shouldPrintInstruction(instr) and shouldPrintFunction(instr.getEnclosingFunction()) + shouldPrintInstruction(instr) and shouldPrintDeclaration(instr.getEnclosingFunction()) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/PrintIR.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/PrintIR.qll index b9106a7bfc73..c4b18d9cb61c 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/PrintIR.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/PrintIR.qll @@ -4,8 +4,8 @@ * This file contains the actual implementation of `PrintIR.ql`. For test cases and very small * databases, `PrintIR.ql` can be run directly to dump the IR for the entire database. For most * uses, however, it is better to write a query that imports `PrintIR.qll`, extends - * `PrintIRConfiguration`, and overrides `shouldPrintFunction()` to select a subset of functions to - * dump. + * `PrintIRConfiguration`, and overrides `shouldPrintDeclaration()` to select a subset of declarations + * to dump. */ private import internal.IRInternal @@ -16,7 +16,7 @@ import Imports::IRConfiguration private newtype TPrintIRConfiguration = MkPrintIRConfiguration() /** - * The query can extend this class to control which functions are printed. + * The query can extend this class to control which declarations are printed. */ class PrintIRConfiguration extends TPrintIRConfiguration { /** Gets a textual representation of this configuration. */ @@ -24,9 +24,9 @@ class PrintIRConfiguration extends TPrintIRConfiguration { /** * Holds if the IR for `func` should be printed. By default, holds for all - * functions. + * functions, global and namespace variables, and static local variables. */ - predicate shouldPrintFunction(Language::Declaration decl) { any() } + predicate shouldPrintDeclaration(Language::Declaration decl) { any() } } /** @@ -34,12 +34,12 @@ class PrintIRConfiguration extends TPrintIRConfiguration { */ private class FilteredIRConfiguration extends IRConfiguration { override predicate shouldEvaluateDebugStringsForFunction(Language::Declaration func) { - shouldPrintFunction(func) + shouldPrintDeclaration(func) } } -private predicate shouldPrintFunction(Language::Declaration decl) { - exists(PrintIRConfiguration config | config.shouldPrintFunction(decl)) +private predicate shouldPrintDeclaration(Language::Declaration decl) { + exists(PrintIRConfiguration config | config.shouldPrintDeclaration(decl)) } private predicate shouldPrintInstruction(Instruction i) { @@ -90,10 +90,10 @@ private string getOperandPropertyString(Operand operand) { } private newtype TPrintableIRNode = - TPrintableIRFunction(IRFunction irFunc) { shouldPrintFunction(irFunc.getFunction()) } or - TPrintableIRBlock(IRBlock block) { shouldPrintFunction(block.getEnclosingFunction()) } or + TPrintableIRFunction(IRFunction irFunc) { shouldPrintDeclaration(irFunc.getFunction()) } or + TPrintableIRBlock(IRBlock block) { shouldPrintDeclaration(block.getEnclosingFunction()) } or TPrintableInstruction(Instruction instr) { - shouldPrintInstruction(instr) and shouldPrintFunction(instr.getEnclosingFunction()) + shouldPrintInstruction(instr) and shouldPrintDeclaration(instr.getEnclosingFunction()) } /** diff --git a/cpp/ql/test/examples/expressions/PrintAST.expected b/cpp/ql/test/examples/expressions/PrintAST.expected index 68ade61e255e..8de5ea5b9b0f 100644 --- a/cpp/ql/test/examples/expressions/PrintAST.expected +++ b/cpp/ql/test/examples/expressions/PrintAST.expected @@ -1308,6 +1308,11 @@ union_etc.cpp: # 6| Type = [IntType] int # 6| ValueCategory = prvalue(load) # 6| getStmt(1): [ReturnStmt] return ... +# 7| [GlobalVariable] S s +# 7| getInitializer(): [Initializer] initializer for s +# 7| getExpr(): [ConstructorCall] call to S +# 7| Type = [VoidType] void +# 7| ValueCategory = prvalue # 9| [CopyAssignmentOperator] C& C::operator=(C const&) # 9| : #-----| getParameter(0): [Parameter] (unnamed parameter 0) @@ -1332,6 +1337,7 @@ union_etc.cpp: # 12| : #-----| getParameter(0): [Parameter] (unnamed parameter 0) #-----| Type = [RValueReferenceType] U && +# 14| [GlobalVariable] C c # 16| [CopyAssignmentOperator] U& U::operator=(U const&) # 16| : #-----| getParameter(0): [Parameter] (unnamed parameter 0) @@ -1356,6 +1362,7 @@ union_etc.cpp: # 18| : #-----| getParameter(0): [Parameter] (unnamed parameter 0) #-----| Type = [RValueReferenceType] C && +# 20| [GlobalVariable] U u # 22| [TopLevelFunction] int foo() # 22| : # 22| getEntryPoint(): [BlockStmt] { ... } diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected index 4b22e3898e4e..3f4a29c59c6a 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected +++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected @@ -8529,6 +8529,11 @@ ir.cpp: # 1035| Type = [Struct] EmptyStruct # 1035| ValueCategory = prvalue # 1036| getStmt(1): [ReturnStmt] return ... +# 1038| [GlobalVariable] (lambda [] type at line 1038, col. 12) lam +# 1038| getInitializer(): [Initializer] initializer for lam +# 1038| getExpr(): [LambdaExpression] [...](...){...} +# 1038| Type = [Closure] decltype([...](...){...}) +# 1038| ValueCategory = prvalue # 1038| [CopyAssignmentOperator] (lambda [] type at line 1038, col. 12)& (lambda [] type at line 1038, col. 12)::operator=((lambda [] type at line 1038, col. 12) const&) # 1038| : #-----| getParameter(0): [Parameter] (unnamed parameter 0) @@ -13976,6 +13981,54 @@ ir.cpp: # 1815| Type = [IntType] int # 1815| ValueCategory = prvalue(load) # 1817| getStmt(8): [ReturnStmt] return ... +# 1821| [GlobalVariable] int global_2 +# 1821| getInitializer(): [Initializer] initializer for global_2 +# 1821| getExpr(): [Literal] 1 +# 1821| Type = [IntType] int +# 1821| Value = [Literal] 1 +# 1821| ValueCategory = prvalue +# 1823| [GlobalVariable] int const global_3 +# 1823| getInitializer(): [Initializer] initializer for global_3 +# 1823| getExpr(): [Literal] 2 +# 1823| Type = [IntType] int +# 1823| Value = [Literal] 2 +# 1823| ValueCategory = prvalue +# 1825| [GlobalVariable] constructor_only global_4 +# 1825| getInitializer(): [Initializer] initializer for global_4 +# 1825| getExpr(): [ConstructorCall] call to constructor_only +# 1825| Type = [VoidType] void +# 1825| ValueCategory = prvalue +# 1825| getArgument(0): [Literal] 1 +# 1825| Type = [IntType] int +# 1825| Value = [Literal] 1 +# 1825| ValueCategory = prvalue +# 1827| [GlobalVariable] constructor_only global_5 +# 1827| getInitializer(): [Initializer] initializer for global_5 +# 1827| getExpr(): [ConstructorCall] call to constructor_only +# 1827| Type = [VoidType] void +# 1827| ValueCategory = prvalue +# 1827| getArgument(0): [Literal] 2 +# 1827| Type = [IntType] int +# 1827| Value = [Literal] 2 +# 1827| ValueCategory = prvalue +# 1829| [GlobalVariable] char* global_string +# 1829| getInitializer(): [Initializer] initializer for global_string +# 1829| getExpr(): global string +# 1829| Type = [ArrayType] const char[14] +# 1829| Value = [StringLiteral] "global string" +# 1829| ValueCategory = lvalue +# 1829| getExpr().getFullyConverted(): [CStyleCast] (char *)... +# 1829| Conversion = [PointerConversion] pointer conversion +# 1829| Type = [CharPointerType] char * +# 1829| ValueCategory = prvalue +# 1829| getExpr(): [ArrayToPointerConversion] array to pointer conversion +# 1829| Type = [PointerType] const char * +# 1829| ValueCategory = prvalue +# 1831| [GlobalVariable] int global_6 +# 1831| getInitializer(): [Initializer] initializer for global_6 +# 1831| getExpr(): [VariableAccess] global_2 +# 1831| Type = [IntType] int +# 1831| ValueCategory = prvalue(load) # 1834| [CopyAssignmentOperator] block_assignment::A& block_assignment::A::operator=(block_assignment::A const&) # 1834| : #-----| getParameter(0): [Parameter] (unnamed parameter 0) @@ -14377,6 +14430,23 @@ ir.cpp: # 1885| Type = [ClassTemplateInstantiation,Struct] Bar2 # 1885| ValueCategory = lvalue # 1886| getStmt(2): [ReturnStmt] return ... +# 1889| [GlobalVariable] char global_template +# 1889| getInitializer(): [Initializer] initializer for global_template +# 1889| getExpr(): [Literal] 42 +# 1889| Type = [IntType] int +# 1889| Value = [Literal] 42 +# 1889| ValueCategory = prvalue +# 1889| getExpr().getFullyConverted(): [CStyleCast] (char)... +# 1889| Conversion = [IntegralConversion] integral conversion +# 1889| Type = [PlainCharType] char +# 1889| Value = [CStyleCast] 42 +# 1889| ValueCategory = prvalue +# 1889| [GlobalVariable] int global_template +# 1889| getInitializer(): [Initializer] initializer for global_template +# 1889| getExpr(): [Literal] 42 +# 1889| Type = [IntType] int +# 1889| Value = [Literal] 42 +# 1889| ValueCategory = prvalue # 1891| [TopLevelFunction] int test_global_template_int() # 1891| : # 1891| getEntryPoint(): [BlockStmt] { ... } @@ -15596,6 +15666,40 @@ struct_init.cpp: # 4| : #-----| getParameter(0): [Parameter] (unnamed parameter 0) #-----| Type = [RValueReferenceType] Info && +# 9| [GlobalVariable] Info infos_in_file[] +# 9| getInitializer(): [Initializer] initializer for infos_in_file +# 9| getExpr(): [ArrayAggregateLiteral] {...} +# 9| Type = [ArrayType] Info[2] +# 9| ValueCategory = prvalue +# 10| getAnElementExpr(0): [ClassAggregateLiteral] {...} +# 10| Type = [Struct] Info +# 10| ValueCategory = prvalue +# 10| getAFieldExpr(name): 1 +# 10| Type = [ArrayType] const char[2] +# 10| Value = [StringLiteral] "1" +# 10| ValueCategory = lvalue +# 10| getAFieldExpr(handler): [FunctionAccess] handler1 +# 10| Type = [FunctionPointerType] ..(*)(..) +# 10| ValueCategory = prvalue(load) +# 10| getAFieldExpr(name).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion +# 10| Type = [PointerType] const char * +# 10| ValueCategory = prvalue +# 11| getAnElementExpr(1): [ClassAggregateLiteral] {...} +# 11| Type = [Struct] Info +# 11| ValueCategory = prvalue +# 11| getAFieldExpr(name): 3 +# 11| Type = [ArrayType] const char[2] +# 11| Value = [StringLiteral] "3" +# 11| ValueCategory = lvalue +# 11| getAFieldExpr(handler): [AddressOfExpr] & ... +# 11| Type = [FunctionPointerType] ..(*)(..) +# 11| ValueCategory = prvalue +# 11| getOperand(): [FunctionAccess] handler2 +# 11| Type = [RoutineType] ..()(..) +# 11| ValueCategory = lvalue +# 11| getAFieldExpr(name).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion +# 11| Type = [PointerType] const char * +# 11| ValueCategory = prvalue # 16| [TopLevelFunction] void let_info_escape(Info*) # 16| : # 16| getParameter(0): [Parameter] info diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.ql b/cpp/ql/test/library-tests/ir/ir/PrintAST.ql index 471b12ed3e53..03321d9e4910 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintAST.ql +++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.ql @@ -7,5 +7,5 @@ private import semmle.code.cpp.PrintAST private import PrintConfig private class PrintConfig extends PrintAstConfiguration { - override predicate shouldPrintFunction(Function func) { shouldDumpFunction(func) } + override predicate shouldPrintDeclaration(Declaration decl) { shouldDumpDeclaration(decl) } } diff --git a/cpp/ql/test/library-tests/ir/ir/PrintConfig.qll b/cpp/ql/test/library-tests/ir/ir/PrintConfig.qll index 6d3db1649007..aa23cf423add 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintConfig.qll +++ b/cpp/ql/test/library-tests/ir/ir/PrintConfig.qll @@ -8,11 +8,11 @@ predicate locationIsInStandardHeaders(Location loc) { } /** - * Holds if the AST or IR for the specified function should be printed in the test output. + * Holds if the AST or IR for the specified declaration should be printed in the test output. * - * This predicate excludes functions defined in standard headers. + * This predicate excludes declarations defined in standard headers. */ -predicate shouldDumpFunction(Declaration decl) { +predicate shouldDumpDeclaration(Declaration decl) { not locationIsInStandardHeaders(decl.getLocation()) and ( decl instanceof Function diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.ql b/cpp/ql/test/library-tests/ir/ir/raw_ir.ql index ae37a4a932b7..a40eaead5115 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.ql +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.ql @@ -7,5 +7,5 @@ private import semmle.code.cpp.ir.implementation.raw.PrintIR private import PrintConfig private class PrintConfig extends PrintIRConfiguration { - override predicate shouldPrintFunction(Declaration decl) { shouldDumpFunction(decl) } + override predicate shouldPrintDeclaration(Declaration decl) { shouldDumpDeclaration(decl) } } diff --git a/csharp/ql/src/experimental/ir/implementation/raw/PrintIR.qll b/csharp/ql/src/experimental/ir/implementation/raw/PrintIR.qll index b9106a7bfc73..c4b18d9cb61c 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/PrintIR.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/PrintIR.qll @@ -4,8 +4,8 @@ * This file contains the actual implementation of `PrintIR.ql`. For test cases and very small * databases, `PrintIR.ql` can be run directly to dump the IR for the entire database. For most * uses, however, it is better to write a query that imports `PrintIR.qll`, extends - * `PrintIRConfiguration`, and overrides `shouldPrintFunction()` to select a subset of functions to - * dump. + * `PrintIRConfiguration`, and overrides `shouldPrintDeclaration()` to select a subset of declarations + * to dump. */ private import internal.IRInternal @@ -16,7 +16,7 @@ import Imports::IRConfiguration private newtype TPrintIRConfiguration = MkPrintIRConfiguration() /** - * The query can extend this class to control which functions are printed. + * The query can extend this class to control which declarations are printed. */ class PrintIRConfiguration extends TPrintIRConfiguration { /** Gets a textual representation of this configuration. */ @@ -24,9 +24,9 @@ class PrintIRConfiguration extends TPrintIRConfiguration { /** * Holds if the IR for `func` should be printed. By default, holds for all - * functions. + * functions, global and namespace variables, and static local variables. */ - predicate shouldPrintFunction(Language::Declaration decl) { any() } + predicate shouldPrintDeclaration(Language::Declaration decl) { any() } } /** @@ -34,12 +34,12 @@ class PrintIRConfiguration extends TPrintIRConfiguration { */ private class FilteredIRConfiguration extends IRConfiguration { override predicate shouldEvaluateDebugStringsForFunction(Language::Declaration func) { - shouldPrintFunction(func) + shouldPrintDeclaration(func) } } -private predicate shouldPrintFunction(Language::Declaration decl) { - exists(PrintIRConfiguration config | config.shouldPrintFunction(decl)) +private predicate shouldPrintDeclaration(Language::Declaration decl) { + exists(PrintIRConfiguration config | config.shouldPrintDeclaration(decl)) } private predicate shouldPrintInstruction(Instruction i) { @@ -90,10 +90,10 @@ private string getOperandPropertyString(Operand operand) { } private newtype TPrintableIRNode = - TPrintableIRFunction(IRFunction irFunc) { shouldPrintFunction(irFunc.getFunction()) } or - TPrintableIRBlock(IRBlock block) { shouldPrintFunction(block.getEnclosingFunction()) } or + TPrintableIRFunction(IRFunction irFunc) { shouldPrintDeclaration(irFunc.getFunction()) } or + TPrintableIRBlock(IRBlock block) { shouldPrintDeclaration(block.getEnclosingFunction()) } or TPrintableInstruction(Instruction instr) { - shouldPrintInstruction(instr) and shouldPrintFunction(instr.getEnclosingFunction()) + shouldPrintInstruction(instr) and shouldPrintDeclaration(instr.getEnclosingFunction()) } /** diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/PrintIR.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/PrintIR.qll index b9106a7bfc73..c4b18d9cb61c 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/PrintIR.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/PrintIR.qll @@ -4,8 +4,8 @@ * This file contains the actual implementation of `PrintIR.ql`. For test cases and very small * databases, `PrintIR.ql` can be run directly to dump the IR for the entire database. For most * uses, however, it is better to write a query that imports `PrintIR.qll`, extends - * `PrintIRConfiguration`, and overrides `shouldPrintFunction()` to select a subset of functions to - * dump. + * `PrintIRConfiguration`, and overrides `shouldPrintDeclaration()` to select a subset of declarations + * to dump. */ private import internal.IRInternal @@ -16,7 +16,7 @@ import Imports::IRConfiguration private newtype TPrintIRConfiguration = MkPrintIRConfiguration() /** - * The query can extend this class to control which functions are printed. + * The query can extend this class to control which declarations are printed. */ class PrintIRConfiguration extends TPrintIRConfiguration { /** Gets a textual representation of this configuration. */ @@ -24,9 +24,9 @@ class PrintIRConfiguration extends TPrintIRConfiguration { /** * Holds if the IR for `func` should be printed. By default, holds for all - * functions. + * functions, global and namespace variables, and static local variables. */ - predicate shouldPrintFunction(Language::Declaration decl) { any() } + predicate shouldPrintDeclaration(Language::Declaration decl) { any() } } /** @@ -34,12 +34,12 @@ class PrintIRConfiguration extends TPrintIRConfiguration { */ private class FilteredIRConfiguration extends IRConfiguration { override predicate shouldEvaluateDebugStringsForFunction(Language::Declaration func) { - shouldPrintFunction(func) + shouldPrintDeclaration(func) } } -private predicate shouldPrintFunction(Language::Declaration decl) { - exists(PrintIRConfiguration config | config.shouldPrintFunction(decl)) +private predicate shouldPrintDeclaration(Language::Declaration decl) { + exists(PrintIRConfiguration config | config.shouldPrintDeclaration(decl)) } private predicate shouldPrintInstruction(Instruction i) { @@ -90,10 +90,10 @@ private string getOperandPropertyString(Operand operand) { } private newtype TPrintableIRNode = - TPrintableIRFunction(IRFunction irFunc) { shouldPrintFunction(irFunc.getFunction()) } or - TPrintableIRBlock(IRBlock block) { shouldPrintFunction(block.getEnclosingFunction()) } or + TPrintableIRFunction(IRFunction irFunc) { shouldPrintDeclaration(irFunc.getFunction()) } or + TPrintableIRBlock(IRBlock block) { shouldPrintDeclaration(block.getEnclosingFunction()) } or TPrintableInstruction(Instruction instr) { - shouldPrintInstruction(instr) and shouldPrintFunction(instr.getEnclosingFunction()) + shouldPrintInstruction(instr) and shouldPrintDeclaration(instr.getEnclosingFunction()) } /**