mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
C++: Support printing of global and namespace variables in PrintAST
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: majorAnalysis
|
||||
---
|
||||
* The `PrintAST` library now also prints global and namespace variables and their initializers.
|
||||
@@ -6,7 +6,7 @@ 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
|
||||
|
||||
@@ -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 `shouldPrintDeclaration` to hold for only the
|
||||
* declarations 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
|
||||
@@ -22,16 +22,15 @@ class PrintAstConfiguration extends TPrintAstConfiguration {
|
||||
|
||||
/**
|
||||
* Holds if the AST for `decl` should be printed. By default, holds for all
|
||||
* functions. Currently, does not support any other declaration types.
|
||||
* functions and global and namespace variables. Currently, does not support any
|
||||
* other declaration types.
|
||||
*/
|
||||
predicate shouldPrintDeclaration(Declaration decl) { any() }
|
||||
}
|
||||
|
||||
private predicate shouldPrintDeclaration(Declaration decl) {
|
||||
exists(PrintAstConfiguration config |
|
||||
config.shouldPrintDeclaration(decl) and
|
||||
decl instanceof Function
|
||||
)
|
||||
exists(PrintAstConfiguration config | config.shouldPrintDeclaration(decl)) and
|
||||
(decl instanceof Function or decl instanceof GlobalOrNamespaceVariable)
|
||||
}
|
||||
|
||||
bindingset[s]
|
||||
@@ -72,7 +71,7 @@ private predicate locationSortKeys(Locatable ast, string file, int line, int col
|
||||
)
|
||||
}
|
||||
|
||||
private Function getEnclosingFunction(Locatable ast) {
|
||||
private Declaration getEnclosingDeclaration(Locatable ast) {
|
||||
result = ast.(Expr).getEnclosingFunction()
|
||||
or
|
||||
result = ast.(Stmt).getEnclosingFunction()
|
||||
@@ -81,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
|
||||
}
|
||||
|
||||
@@ -89,7 +92,7 @@ private Function getEnclosingFunction(Locatable ast) {
|
||||
* nodes for things like parameter lists and constructor init lists.
|
||||
*/
|
||||
private newtype TPrintAstNode =
|
||||
TAstNode(Locatable ast) { shouldPrintDeclaration(getEnclosingFunction(ast)) } or
|
||||
TAstNode(Locatable ast) { shouldPrintDeclaration(getEnclosingDeclaration(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.
|
||||
@@ -161,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.shouldPrintDeclaration` 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() { shouldPrintDeclaration(this.getEnclosingFunction()) }
|
||||
final predicate shouldPrint() { shouldPrintDeclaration(this.getEnclosingDeclaration()) }
|
||||
|
||||
/**
|
||||
* Gets the children of this node.
|
||||
@@ -232,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 Function getEnclosingFunction() {
|
||||
result = this.getParent*().(FunctionNode).getFunction()
|
||||
private Declaration getEnclosingDeclaration() { result = this.getParent*().getDeclaration() }
|
||||
|
||||
/**
|
||||
* Gets the `Declaration` this node represents.
|
||||
*/
|
||||
private Declaration getDeclaration() {
|
||||
result = this.(AstNode).getAst() and shouldPrintDeclaration(result)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -574,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
|
||||
@@ -607,31 +652,10 @@ class FunctionNode extends AstNode {
|
||||
or
|
||||
childIndex = 3 and result = "<destructions>"
|
||||
}
|
||||
|
||||
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) {
|
||||
shouldPrintDeclaration(getEnclosingFunction(parent)) and
|
||||
shouldPrintDeclaration(getEnclosingDeclaration(parent)) and
|
||||
(
|
||||
exists(Stmt s | s = parent |
|
||||
namedStmtChildPredicates(s, child, result)
|
||||
@@ -650,7 +674,7 @@ private string getChildAccessorWithoutConversions(Locatable parent, Element chil
|
||||
}
|
||||
|
||||
private predicate namedStmtChildPredicates(Locatable s, Element e, string pred) {
|
||||
shouldPrintDeclaration(getEnclosingFunction(s)) and
|
||||
shouldPrintDeclaration(getEnclosingDeclaration(s)) and
|
||||
(
|
||||
exists(int n | s.(BlockStmt).getStmt(n) = e and pred = "getStmt(" + n + ")")
|
||||
or
|
||||
@@ -738,7 +762,7 @@ private predicate namedStmtChildPredicates(Locatable s, Element e, string pred)
|
||||
}
|
||||
|
||||
private predicate namedExprChildPredicates(Expr expr, Element ele, string pred) {
|
||||
shouldPrintDeclaration(expr.getEnclosingFunction()) and
|
||||
shouldPrintDeclaration(expr.getEnclosingDeclaration()) and
|
||||
(
|
||||
expr.(Access).getTarget() = ele and pred = "getTarget()"
|
||||
or
|
||||
|
||||
@@ -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| <params>:
|
||||
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
|
||||
@@ -1332,6 +1337,7 @@ union_etc.cpp:
|
||||
# 12| <params>:
|
||||
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
|
||||
#-----| Type = [RValueReferenceType] U &&
|
||||
# 14| [GlobalVariable] C c
|
||||
# 16| [CopyAssignmentOperator] U& U::operator=(U const&)
|
||||
# 16| <params>:
|
||||
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
|
||||
@@ -1356,6 +1362,7 @@ union_etc.cpp:
|
||||
# 18| <params>:
|
||||
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
|
||||
#-----| Type = [RValueReferenceType] C &&
|
||||
# 20| [GlobalVariable] U u
|
||||
# 22| [TopLevelFunction] int foo()
|
||||
# 22| <params>:
|
||||
# 22| getEntryPoint(): [BlockStmt] { ... }
|
||||
|
||||
@@ -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| <params>:
|
||||
#-----| 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| <params>:
|
||||
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
|
||||
@@ -14377,6 +14430,23 @@ ir.cpp:
|
||||
# 1885| Type = [ClassTemplateInstantiation,Struct] Bar2<int>
|
||||
# 1885| ValueCategory = lvalue
|
||||
# 1886| getStmt(2): [ReturnStmt] return ...
|
||||
# 1889| [GlobalVariable] char global_template<char>
|
||||
# 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<int>
|
||||
# 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| <params>:
|
||||
# 1891| getEntryPoint(): [BlockStmt] { ... }
|
||||
@@ -15170,6 +15240,40 @@ struct_init.cpp:
|
||||
# 4| <params>:
|
||||
#-----| 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| <params>:
|
||||
# 16| getParameter(0): [Parameter] info
|
||||
|
||||
Reference in New Issue
Block a user