From 0eeddc37bf545557e49f1aa0cbd8951f178800a0 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Thu, 9 Jul 2026 14:42:01 +0100 Subject: [PATCH 1/2] Go: skip extracting ast.ParenExpr nodes Instead of creating a database entry for parenthesised expressions, extract their child expression directly in their place. This makes the extracted AST act as if ParenExpr nodes do not exist while still correctly extracting children. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- go/extractor/extractor.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/go/extractor/extractor.go b/go/extractor/extractor.go index 158f0029704d..6e305a73fbf6 100644 --- a/go/extractor/extractor.go +++ b/go/extractor/extractor.go @@ -1013,6 +1013,12 @@ func extractExpr(tw *trap.Writer, expr ast.Expr, parent trap.Label, idx int, ski return } + // Skip parenthesised expressions and extract their child directly in their place + if paren, ok := expr.(*ast.ParenExpr); ok { + extractExpr(tw, paren.X, parent, idx, skipExtractingValue) + return + } + lbl := tw.Labeler.LocalID(expr) extractTypeOf(tw, expr, lbl) @@ -1087,9 +1093,6 @@ func extractExpr(tw *trap.Writer, expr ast.Expr, parent trap.Label, idx int, ski kind = dbscheme.CompositeLitExpr.Index() extractExpr(tw, expr.Type, lbl, 0, false) extractExprs(tw, expr.Elts, lbl, 1, 1) - case *ast.ParenExpr: - kind = dbscheme.ParenExpr.Index() - extractExpr(tw, expr.X, lbl, 0, false) case *ast.SelectorExpr: kind = dbscheme.SelectorExpr.Index() extractExpr(tw, expr.X, lbl, 0, false) From af28d2c8ffde5cc2701d4cf39a3c06f8a3701cb1 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Thu, 9 Jul 2026 15:20:05 +0100 Subject: [PATCH 2/2] Go: deprecate ParenExpr and remove all references Since the extractor no longer produces ParenExpr nodes, deprecate the class so existing user code gets a warning rather than breaking, and remove all references from library code where it was used to look through parentheses. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../learn-ql/go/ast-class-reference.rst | 2 -- go/ql/lib/semmle/go/Expr.qll | 19 ++++--------------- .../go/controlflow/ControlFlowGraph.qll | 2 -- .../go/controlflow/ControlFlowGraphImpl.qll | 9 +-------- go/ql/lib/semmle/go/controlflow/IR.qll | 5 +---- go/ql/lib/semmle/go/dataflow/Properties.qll | 4 ---- .../IntegerOverflow/RangeAnalysis.qll | 17 ----------------- 7 files changed, 6 insertions(+), 52 deletions(-) diff --git a/go/docs/language/learn-ql/go/ast-class-reference.rst b/go/docs/language/learn-ql/go/ast-class-reference.rst index d874652a8946..fc46df7c65d4 100644 --- a/go/docs/language/learn-ql/go/ast-class-reference.rst +++ b/go/docs/language/learn-ql/go/ast-class-reference.rst @@ -450,8 +450,6 @@ Miscellaneous +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | ``...`` | `Ellipsis `__ | | | +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``(``\ `Expr `__\ ``)`` | `ParenExpr `__ | | | -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | `Ident `__\ ``.``\ `Ident `__ | `SelectorExpr `__ | | | +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | `Expr `__\ ``[``\ `Expr `__\ ``]`` | `IndexExpr `__ | | | diff --git a/go/ql/lib/semmle/go/Expr.qll b/go/ql/lib/semmle/go/Expr.qll index 9a8481a2dcc8..bc9655891d7a 100644 --- a/go/ql/lib/semmle/go/Expr.qll +++ b/go/ql/lib/semmle/go/Expr.qll @@ -544,15 +544,11 @@ class SliceLit extends ArrayOrSliceLit { } /** - * A parenthesized expression. - * - * Examples: - * - * ```go - * (x + y) - * ``` + * DEPRECATED: `ParenExpr` is no longer extracted. Parenthesized expressions are + * transparent in the AST; the child expression takes the place of the parenthesized + * expression directly. */ -class ParenExpr extends @parenexpr, Expr { +deprecated class ParenExpr extends @parenexpr, Expr { /** Gets the expression between parentheses. */ Expr getExpr() { result = this.getChildExpr(0) } @@ -2137,8 +2133,6 @@ private predicate isTypeExprBottomUp(Expr e) { or e instanceof @indexexpr and isTypeExprBottomUp(e.getChildExpr(0)) or - isTypeExprBottomUp(e.(ParenExpr).getExpr()) - or isTypeExprBottomUp(e.(StarExpr).getBase()) or isTypeExprBottomUp(e.(Ellipsis).getOperand()) @@ -2189,8 +2183,6 @@ private predicate isTypeExprTopDown(Expr e) { or e = any(SelectorExpr sel | isTypeExprTopDown(sel)).getBase() or - e = any(ParenExpr pe | isTypeExprTopDown(pe)).getExpr() - or e = any(StarExpr se | isTypeExprTopDown(se)).getBase() or e = any(Ellipsis ell | isTypeExprTopDown(ell)).getOperand() @@ -2239,8 +2231,6 @@ class ReferenceExpr extends Expr { not this = any(MethodSpec md).getNameExpr() and not this = any(StructLit sl).getKey(_) or - this.(ParenExpr).getExpr() instanceof ReferenceExpr - or this.(StarExpr).getBase() instanceof ReferenceExpr or this instanceof DerefExpr @@ -2290,7 +2280,6 @@ class ValueExpr extends Expr { this instanceof BasicLit or this instanceof FuncLit or this instanceof CompositeLit or - this.(ParenExpr).getExpr() instanceof ValueExpr or this instanceof SliceExpr or this instanceof TypeAssertExpr or this instanceof CallOrConversionExpr or diff --git a/go/ql/lib/semmle/go/controlflow/ControlFlowGraph.qll b/go/ql/lib/semmle/go/controlflow/ControlFlowGraph.qll index 77bb94d89f8c..0dc5d1d0f1c5 100644 --- a/go/ql/lib/semmle/go/controlflow/ControlFlowGraph.qll +++ b/go/ql/lib/semmle/go/controlflow/ControlFlowGraph.qll @@ -259,8 +259,6 @@ module ControlFlow { private predicate ensuresAux(Expr expr, boolean b) { expr = cond and b = outcome or - expr = any(ParenExpr par | this.ensuresAux(par, b)).getExpr() - or expr = any(NotExpr ne | this.ensuresAux(ne, b.booleanNot())).getOperand() or expr = any(LandExpr land | this.ensuresAux(land, true)).getAnOperand() and diff --git a/go/ql/lib/semmle/go/controlflow/ControlFlowGraphImpl.qll b/go/ql/lib/semmle/go/controlflow/ControlFlowGraphImpl.qll index a26ab3adaf5f..6e09d3724801 100644 --- a/go/ql/lib/semmle/go/controlflow/ControlFlowGraphImpl.qll +++ b/go/ql/lib/semmle/go/controlflow/ControlFlowGraphImpl.qll @@ -46,8 +46,7 @@ private predicate isCondRoot(Expr e) { */ private predicate isCond(Expr e) { isCondRoot(e) or - e = any(LogicalBinaryExpr lbe | isCond(lbe)).getRightOperand() or - e = any(ParenExpr par | isCond(par)).getExpr() + e = any(LogicalBinaryExpr lbe | isCond(lbe)).getRightOperand() } /** @@ -586,9 +585,6 @@ module CFG { // `else` block, so there is no control-flow step where `x && y` is specifically calculated) e instanceof LogicalBinaryExpr and isCond(e) - or - // Purely concrete-syntactic structural expression: - e instanceof ParenExpr } /** @@ -774,7 +770,6 @@ module CFG { this instanceof ExprStmt or this instanceof KeyValueExpr or this instanceof LabeledStmt or - this instanceof ParenExpr or this instanceof PlainBlock or this instanceof VarDecl } @@ -811,8 +806,6 @@ module CFG { or i = 0 and result = this.(LabeledStmt).getStmt() or - i = 0 and result = this.(ParenExpr).getExpr() - or result = this.(PlainBlock).getStmt(i) } } diff --git a/go/ql/lib/semmle/go/controlflow/IR.qll b/go/ql/lib/semmle/go/controlflow/IR.qll index a4c730041082..e98f71ff5606 100644 --- a/go/ql/lib/semmle/go/controlflow/IR.qll +++ b/go/ql/lib/semmle/go/controlflow/IR.qll @@ -1511,10 +1511,7 @@ module IR { * value is not stored in a variable or used to compute the value of a non-shortcircuiting * expression) do not have a final instruction either. */ - Instruction evalExprInstruction(Expr e) { - result = MkExprNode(e) or - result = evalExprInstruction(e.(ParenExpr).getExpr()) - } + Instruction evalExprInstruction(Expr e) { result = MkExprNode(e) } /** * Gets the instruction corresponding to the initialization of `r`. diff --git a/go/ql/lib/semmle/go/dataflow/Properties.qll b/go/ql/lib/semmle/go/dataflow/Properties.qll index 573b001a3c36..0ec2654f8610 100644 --- a/go/ql/lib/semmle/go/dataflow/Properties.qll +++ b/go/ql/lib/semmle/go/dataflow/Properties.qll @@ -32,10 +32,6 @@ class Property extends TProperty { // then !test = !outcome ==> nd matches this this.checkOnExpr(test.(NotExpr).getOperand(), outcome.booleanNot(), nd) or - // if test = outcome ==> nd matches this - // then (test) = outcome ==> nd matches this - this.checkOnExpr(test.(ParenExpr).getExpr(), outcome, nd) - or // if test = true ==> nd matches this // then (test && e) = true ==> nd matches this outcome = true and diff --git a/go/ql/src/experimental/IntegerOverflow/RangeAnalysis.qll b/go/ql/src/experimental/IntegerOverflow/RangeAnalysis.qll index f3f4c15f0085..5e9037609438 100644 --- a/go/ql/src/experimental/IntegerOverflow/RangeAnalysis.qll +++ b/go/ql/src/experimental/IntegerOverflow/RangeAnalysis.qll @@ -31,12 +31,6 @@ float getAnUpperBound(Expr expr) { if expr.isConst() then result = expr.getNumericValue() else ( - //if an expression with parenthesis, strip the parenthesis first - exists(ParenExpr paren | - paren = expr and - result = getAnUpperBound(paren.stripParens()) - ) - or //if this expression is an identifier exists(SsaVariable v, Ident identifier | identifier = expr and @@ -188,11 +182,6 @@ float getALowerBound(Expr expr) { result = expr.getIntValue() or result = expr.getExactValue().toFloat() else ( - exists(ParenExpr paren | - paren = expr and - result = getALowerBound(paren.stripParens()) - ) - or //if this expression is an identifer exists(SsaVariable v, Ident identifier | identifier = expr and @@ -571,12 +560,6 @@ predicate ssaDependsOnExpr(SsaDefinition def, Expr expr) { if expr.isConst() then none() else ( - //if an expression with parenthesis, strip the parenthesis - exists(ParenExpr paren | - paren = expr and - ssaDependsOnExpr(def, paren.stripParens()) - ) - or exists(Ident ident | ident = expr and getAUse(def) = ident