Go: adopt ForeachStmt with destructuring

This commit is contained in:
Owen Mansel-Chan
2026-07-09 11:01:38 +01:00
parent 107717d473
commit 832f8443bb
21 changed files with 2652 additions and 263 deletions

View File

@@ -0,0 +1,31 @@
class Expr_ extends @expr {
string toString() { result = "Expr" }
}
class ExprParent_ extends @exprparent {
string toString() { result = "ExprParent" }
}
// The schema for exprs is:
//
// exprs(unique int id: @expr,
// int kind: int ref,
// int parent: @exprparent ref,
// int idx: int ref);
//
// `@rangeelementexpr` (kind 55) is a synthesized node that groups the loop
// variables (the key and value) of a `range` statement. To downgrade we remove
// those nodes and reparent their children (the key and value expressions)
// directly onto the `range` statement, at the same indices.
from Expr_ id, int kind, ExprParent_ newparent, int idx
where
exists(ExprParent_ parent | exprs(id, kind, parent, idx) and kind != 55 |
// A key or value grouped by a range element node: reparent it onto the
// range statement (the range element node's own parent).
exists(Expr_ pe | pe = parent and exprs(pe, 55, newparent, _))
or
// Any other expression keeps its parent unchanged.
not exists(Expr_ pe | pe = parent and exprs(pe, 55, _, _)) and
newparent = parent
)
select id, kind, newparent, idx

View File

@@ -0,0 +1,563 @@
/** Auto-generated dbscheme; do not edit. Run `make gen` in directory `go/` to regenerate. */
/** Duplicate code **/
duplicateCode(
unique int id : @duplication,
varchar(900) relativePath : string ref,
int equivClass : int ref);
similarCode(
unique int id : @similarity,
varchar(900) relativePath : string ref,
int equivClass : int ref);
@duplication_or_similarity = @duplication | @similarity;
tokens(
int id : @duplication_or_similarity ref,
int offset : int ref,
int beginLine : int ref,
int beginColumn : int ref,
int endLine : int ref,
int endColumn : int ref);
/** External data **/
externalData(
int id : @externalDataElement,
varchar(900) path : string ref,
int column: int ref,
varchar(900) value : string ref
);
snapshotDate(unique date snapshotDate : date ref);
sourceLocationPrefix(varchar(900) prefix : string ref);
/** Overlay support **/
databaseMetadata(
string metadataKey: string ref,
string value: string ref
);
overlayChangedFiles(
string path: string ref
);
/*
* XML Files
*/
xmlEncoding(
unique int id: @file ref,
string encoding: string ref
);
xmlDTDs(
unique int id: @xmldtd,
string root: string ref,
string publicId: string ref,
string systemId: string ref,
int fileid: @file ref
);
xmlElements(
unique int id: @xmlelement,
string name: string ref,
int parentid: @xmlparent ref,
int idx: int ref,
int fileid: @file ref
);
xmlAttrs(
unique int id: @xmlattribute,
int elementid: @xmlelement ref,
string name: string ref,
string value: string ref,
int idx: int ref,
int fileid: @file ref
);
xmlNs(
int id: @xmlnamespace,
string prefixName: string ref,
string URI: string ref,
int fileid: @file ref
);
xmlHasNs(
int elementId: @xmlnamespaceable ref,
int nsId: @xmlnamespace ref,
int fileid: @file ref
);
xmlComments(
unique int id: @xmlcomment,
string text: string ref,
int parentid: @xmlparent ref,
int fileid: @file ref
);
xmlChars(
unique int id: @xmlcharacters,
string text: string ref,
int parentid: @xmlparent ref,
int idx: int ref,
int isCDATA: int ref,
int fileid: @file ref
);
@xmlparent = @file | @xmlelement;
@xmlnamespaceable = @xmlelement | @xmlattribute;
xmllocations(
int xmlElement: @xmllocatable ref,
int location: @location_default ref
);
@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace;
compilations(unique int id: @compilation, string cwd: string ref);
#keyset[id, num]
compilation_args(int id: @compilation ref, int num: int ref, string arg: string ref);
#keyset[id, num, kind]
compilation_time(int id: @compilation ref, int num: int ref, int kind: int ref, float secs: float ref);
diagnostic_for(unique int diagnostic: @diagnostic ref, int compilation: @compilation ref, int file_number: int ref, int file_number_diagnostic_number: int ref);
compilation_finished(unique int id: @compilation ref, float cpu_seconds: float ref, float elapsed_seconds: float ref);
#keyset[id, num]
compilation_compiling_files(int id: @compilation ref, int num: int ref, int file: @file ref);
diagnostics(unique int id: @diagnostic, int severity: int ref, string error_tag: string ref, string error_message: string ref,
string full_error_message: string ref, int location: @location ref);
locations_default(unique int id: @location_default, int file: @file ref, int beginLine: int ref, int beginColumn: int ref,
int endLine: int ref, int endColumn: int ref);
numlines(int element_id: @sourceline ref, int num_lines: int ref, int num_code: int ref, int num_comment: int ref);
files(unique int id: @file, string name: string ref);
folders(unique int id: @folder, string name: string ref);
containerparent(int parent: @container ref, unique int child: @container ref);
has_location(unique int locatable: @locatable ref, int location: @location ref);
#keyset[parent, idx]
comment_groups(unique int id: @comment_group, int parent: @file ref, int idx: int ref);
comments(unique int id: @comment, int kind: int ref, int parent: @comment_group ref, int idx: int ref, string text: string ref);
doc_comments(unique int node: @documentable ref, int comment: @comment_group ref);
#keyset[parent, idx]
exprs(unique int id: @expr, int kind: int ref, int parent: @exprparent ref, int idx: int ref);
literals(unique int expr: @expr ref, string value: string ref, string raw: string ref);
constvalues(unique int expr: @expr ref, string value: string ref, string exact: string ref);
fields(unique int id: @field, int parent: @fieldparent ref, int idx: int ref);
typeparamdecls(unique int id: @typeparamdecl, int parent: @typeparamdeclparent ref, int idx: int ref);
#keyset[parent, idx]
stmts(unique int id: @stmt, int kind: int ref, int parent: @stmtparent ref, int idx: int ref);
#keyset[parent, idx]
decls(unique int id: @decl, int kind: int ref, int parent: @declparent ref, int idx: int ref);
#keyset[parent, idx]
specs(unique int id: @spec, int kind: int ref, int parent: @gendecl ref, int idx: int ref);
scopes(unique int id: @scope, int kind: int ref);
scopenesting(unique int inner: @scope ref, int outer: @scope ref);
scopenodes(unique int node: @scopenode ref, int scope: @localscope ref);
objects(unique int id: @object, int kind: int ref, string name: string ref);
objectscopes(unique int object: @object ref, int scope: @scope ref);
objecttypes(unique int object: @object ref, int tp: @type ref);
methodreceivers(unique int method: @object ref, int receiver: @object ref);
fieldstructs(unique int field: @object ref, int struct: @structtype ref);
methodhosts(int method: @object ref, int host: @definedtype ref);
defs(int ident: @ident ref, int object: @object ref);
uses(int ident: @ident ref, int object: @object ref);
types(unique int id: @type, int kind: int ref);
type_of(unique int expr: @expr ref, int tp: @type ref);
typename(unique int tp: @type ref, string name: string ref);
key_type(unique int map: @maptype ref, int tp: @type ref);
element_type(unique int container: @containertype ref, int tp: @type ref);
base_type(unique int ptr: @pointertype ref, int tp: @type ref);
underlying_type(unique int defined: @definedtype ref, int tp: @type ref);
#keyset[parent, index]
component_types(int parent: @compositetype ref, int index: int ref, string name: string ref, int tp: @type ref);
#keyset[parent, index]
struct_tags(int parent: @structtype ref, int index: int ref, string tag: string ref);
#keyset[interface, index]
interface_private_method_ids(int interface: @interfacetype ref, int index: int ref, string id: string ref);
array_length(unique int tp: @arraytype ref, string len: string ref);
type_objects(unique int tp: @type ref, int object: @object ref);
packages(unique int id: @package, string name: string ref, string path: string ref, int scope: @packagescope ref);
#keyset[parent, idx]
modexprs(unique int id: @modexpr, int kind: int ref, int parent: @modexprparent ref, int idx: int ref);
#keyset[parent, idx]
modtokens(string token: string ref, int parent: @modexpr ref, int idx: int ref);
#keyset[package, idx]
errors(unique int id: @error, int kind: int ref, string msg: string ref, string rawpos: string ref,
string file: string ref, int line: int ref, int col: int ref, int package: @package ref, int idx: int ref);
has_ellipsis(int id: @callorconversionexpr ref);
variadic(int id: @signaturetype ref);
#keyset[parent, idx]
typeparam(unique int tp: @typeparamtype ref, string name: string ref, int bound: @compositetype ref,
int parent: @typeparamparentobject ref, int idx: int ref);
@container = @file | @folder;
@locatable = @xmllocatable | @node | @localscope;
@node = @documentable | @exprparent | @modexprparent | @fieldparent | @stmtparent | @declparent | @typeparamdeclparent
| @scopenode | @comment_group | @comment;
@documentable = @file | @field | @typeparamdecl | @spec | @gendecl | @funcdecl | @modexpr;
@exprparent = @funcdef | @file | @expr | @field | @stmt | @decl | @typeparamdecl | @spec;
@modexprparent = @file | @modexpr;
@fieldparent = @decl | @structtypeexpr | @functypeexpr | @interfacetypeexpr;
@stmtparent = @funcdef | @stmt | @decl;
@declparent = @file | @declstmt;
@typeparamdeclparent = @funcdecl | @typespec;
@funcdef = @funclit | @funcdecl;
@scopenode = @file | @functypeexpr | @blockstmt | @ifstmt | @caseclause | @switchstmt | @commclause | @loopstmt;
@location = @location_default;
@sourceline = @locatable;
case @comment.kind of
0 = @slashslashcomment
| 1 = @slashstarcomment;
case @expr.kind of
0 = @badexpr
| 1 = @ident
| 2 = @ellipsis
| 3 = @intlit
| 4 = @floatlit
| 5 = @imaglit
| 6 = @charlit
| 7 = @stringlit
| 8 = @funclit
| 9 = @compositelit
| 10 = @parenexpr
| 11 = @selectorexpr
| 12 = @indexexpr
| 13 = @genericfunctioninstantiationexpr
| 14 = @generictypeinstantiationexpr
| 15 = @sliceexpr
| 16 = @typeassertexpr
| 17 = @callorconversionexpr
| 18 = @starexpr
| 19 = @keyvalueexpr
| 20 = @arraytypeexpr
| 21 = @structtypeexpr
| 22 = @functypeexpr
| 23 = @interfacetypeexpr
| 24 = @maptypeexpr
| 25 = @typesetliteralexpr
| 26 = @plusexpr
| 27 = @minusexpr
| 28 = @notexpr
| 29 = @complementexpr
| 30 = @derefexpr
| 31 = @addressexpr
| 32 = @arrowexpr
| 33 = @lorexpr
| 34 = @landexpr
| 35 = @eqlexpr
| 36 = @neqexpr
| 37 = @lssexpr
| 38 = @leqexpr
| 39 = @gtrexpr
| 40 = @geqexpr
| 41 = @addexpr
| 42 = @subexpr
| 43 = @orexpr
| 44 = @xorexpr
| 45 = @mulexpr
| 46 = @quoexpr
| 47 = @remexpr
| 48 = @shlexpr
| 49 = @shrexpr
| 50 = @andexpr
| 51 = @andnotexpr
| 52 = @sendchantypeexpr
| 53 = @recvchantypeexpr
| 54 = @sendrcvchantypeexpr;
@basiclit = @intlit | @floatlit | @imaglit | @charlit | @stringlit;
@operatorexpr = @logicalexpr | @arithmeticexpr | @bitwiseexpr | @unaryexpr | @binaryexpr;
@logicalexpr = @logicalunaryexpr | @logicalbinaryexpr;
@arithmeticexpr = @arithmeticunaryexpr | @arithmeticbinaryexpr;
@bitwiseexpr = @bitwiseunaryexpr | @bitwisebinaryexpr;
@unaryexpr = @logicalunaryexpr | @bitwiseunaryexpr | @arithmeticunaryexpr | @derefexpr | @addressexpr | @arrowexpr;
@logicalunaryexpr = @notexpr;
@bitwiseunaryexpr = @complementexpr;
@arithmeticunaryexpr = @plusexpr | @minusexpr;
@binaryexpr = @logicalbinaryexpr | @bitwisebinaryexpr | @arithmeticbinaryexpr | @comparison;
@logicalbinaryexpr = @lorexpr | @landexpr;
@bitwisebinaryexpr = @shiftexpr | @orexpr | @xorexpr | @andexpr | @andnotexpr;
@arithmeticbinaryexpr = @addexpr | @subexpr | @mulexpr | @quoexpr | @remexpr;
@shiftexpr = @shlexpr | @shrexpr;
@comparison = @equalitytest | @relationalcomparison;
@equalitytest = @eqlexpr | @neqexpr;
@relationalcomparison = @lssexpr | @leqexpr | @gtrexpr | @geqexpr;
@chantypeexpr = @sendchantypeexpr | @recvchantypeexpr | @sendrcvchantypeexpr;
case @stmt.kind of
0 = @badstmt
| 1 = @declstmt
| 2 = @emptystmt
| 3 = @labeledstmt
| 4 = @exprstmt
| 5 = @sendstmt
| 6 = @incstmt
| 7 = @decstmt
| 8 = @gostmt
| 9 = @deferstmt
| 10 = @returnstmt
| 11 = @breakstmt
| 12 = @continuestmt
| 13 = @gotostmt
| 14 = @fallthroughstmt
| 15 = @blockstmt
| 16 = @ifstmt
| 17 = @caseclause
| 18 = @exprswitchstmt
| 19 = @typeswitchstmt
| 20 = @commclause
| 21 = @selectstmt
| 22 = @forstmt
| 23 = @rangestmt
| 24 = @assignstmt
| 25 = @definestmt
| 26 = @addassignstmt
| 27 = @subassignstmt
| 28 = @mulassignstmt
| 29 = @quoassignstmt
| 30 = @remassignstmt
| 31 = @andassignstmt
| 32 = @orassignstmt
| 33 = @xorassignstmt
| 34 = @shlassignstmt
| 35 = @shrassignstmt
| 36 = @andnotassignstmt;
@incdecstmt = @incstmt | @decstmt;
@assignment = @simpleassignstmt | @compoundassignstmt;
@simpleassignstmt = @assignstmt | @definestmt;
@compoundassignstmt = @addassignstmt | @subassignstmt | @mulassignstmt | @quoassignstmt | @remassignstmt
| @andassignstmt | @orassignstmt | @xorassignstmt | @shlassignstmt | @shrassignstmt | @andnotassignstmt;
@branchstmt = @breakstmt | @continuestmt | @gotostmt | @fallthroughstmt;
@switchstmt = @exprswitchstmt | @typeswitchstmt;
@loopstmt = @forstmt | @rangestmt;
case @decl.kind of
0 = @baddecl
| 1 = @importdecl
| 2 = @constdecl
| 3 = @typedecl
| 4 = @vardecl
| 5 = @funcdecl;
@gendecl = @importdecl | @constdecl | @typedecl | @vardecl;
case @spec.kind of
0 = @importspec
| 1 = @valuespec
| 2 = @typedefspec
| 3 = @aliasspec;
@typespec = @typedefspec | @aliasspec;
case @object.kind of
0 = @pkgobject
| 1 = @decltypeobject
| 2 = @builtintypeobject
| 3 = @declconstobject
| 4 = @builtinconstobject
| 5 = @declvarobject
| 6 = @declfunctionobject
| 7 = @builtinfunctionobject
| 8 = @labelobject;
@typeparamparentobject = @decltypeobject | @declfunctionobject;
@declobject = @decltypeobject | @declconstobject | @declvarobject | @declfunctionobject;
@builtinobject = @builtintypeobject | @builtinconstobject | @builtinfunctionobject;
@typeobject = @decltypeobject | @builtintypeobject;
@valueobject = @constobject | @varobject | @functionobject;
@constobject = @declconstobject | @builtinconstobject;
@varobject = @declvarobject;
@functionobject = @declfunctionobject | @builtinfunctionobject;
case @scope.kind of
0 = @universescope
| 1 = @packagescope
| 2 = @localscope;
case @type.kind of
0 = @invalidtype
| 1 = @boolexprtype
| 2 = @inttype
| 3 = @int8type
| 4 = @int16type
| 5 = @int32type
| 6 = @int64type
| 7 = @uinttype
| 8 = @uint8type
| 9 = @uint16type
| 10 = @uint32type
| 11 = @uint64type
| 12 = @uintptrtype
| 13 = @float32type
| 14 = @float64type
| 15 = @complex64type
| 16 = @complex128type
| 17 = @stringexprtype
| 18 = @unsafepointertype
| 19 = @boolliteraltype
| 20 = @intliteraltype
| 21 = @runeliteraltype
| 22 = @floatliteraltype
| 23 = @complexliteraltype
| 24 = @stringliteraltype
| 25 = @nilliteraltype
| 26 = @typeparamtype
| 27 = @arraytype
| 28 = @slicetype
| 29 = @structtype
| 30 = @pointertype
| 31 = @interfacetype
| 32 = @tupletype
| 33 = @signaturetype
| 34 = @maptype
| 35 = @sendchantype
| 36 = @recvchantype
| 37 = @sendrcvchantype
| 38 = @definedtype
| 39 = @typesetliteraltype;
@basictype = @booltype | @numerictype | @stringtype | @literaltype | @invalidtype | @unsafepointertype;
@booltype = @boolexprtype | @boolliteraltype;
@numerictype = @integertype | @floattype | @complextype;
@integertype = @signedintegertype | @unsignedintegertype;
@signedintegertype = @inttype | @int8type | @int16type | @int32type | @int64type | @intliteraltype | @runeliteraltype;
@unsignedintegertype = @uinttype | @uint8type | @uint16type | @uint32type | @uint64type | @uintptrtype;
@floattype = @float32type | @float64type | @floatliteraltype;
@complextype = @complex64type | @complex128type | @complexliteraltype;
@stringtype = @stringexprtype | @stringliteraltype;
@literaltype = @boolliteraltype | @intliteraltype | @runeliteraltype | @floatliteraltype | @complexliteraltype
| @stringliteraltype | @nilliteraltype;
@compositetype = @typeparamtype | @containertype | @structtype | @pointertype | @interfacetype | @tupletype
| @signaturetype | @definedtype | @typesetliteraltype;
@containertype = @arraytype | @slicetype | @maptype | @chantype;
@chantype = @sendchantype | @recvchantype | @sendrcvchantype;
case @modexpr.kind of
0 = @modcommentblock
| 1 = @modline
| 2 = @modlineblock
| 3 = @modlparen
| 4 = @modrparen;
case @error.kind of
0 = @unknownerror
| 1 = @listerror
| 2 = @parseerror
| 3 = @typeerror;

View File

@@ -0,0 +1,23 @@
class Locatable_ extends @locatable {
string toString() { result = "Locatable" }
}
class Location_ extends @location {
string toString() { result = "Location" }
}
class Expr_ extends @expr {
string toString() { result = "Expr" }
}
// The schema for has_location is:
//
// has_location(unique int locatable: @locatable ref, int location: @location ref);
//
// The synthesized `@rangeelementexpr` nodes (kind 55) are removed by the
// accompanying `exprs` downgrade, so their locations must be removed too.
from Locatable_ locatable, Location_ location
where
has_location(locatable, location) and
not exists(Expr_ e | e = locatable and exprs(e, 55, _, _))
select locatable, location

View File

@@ -0,0 +1,564 @@
/** Auto-generated dbscheme; do not edit. Run `make gen` in directory `go/` to regenerate. */
/** Duplicate code **/
duplicateCode(
unique int id : @duplication,
varchar(900) relativePath : string ref,
int equivClass : int ref);
similarCode(
unique int id : @similarity,
varchar(900) relativePath : string ref,
int equivClass : int ref);
@duplication_or_similarity = @duplication | @similarity;
tokens(
int id : @duplication_or_similarity ref,
int offset : int ref,
int beginLine : int ref,
int beginColumn : int ref,
int endLine : int ref,
int endColumn : int ref);
/** External data **/
externalData(
int id : @externalDataElement,
varchar(900) path : string ref,
int column: int ref,
varchar(900) value : string ref
);
snapshotDate(unique date snapshotDate : date ref);
sourceLocationPrefix(varchar(900) prefix : string ref);
/** Overlay support **/
databaseMetadata(
string metadataKey: string ref,
string value: string ref
);
overlayChangedFiles(
string path: string ref
);
/*
* XML Files
*/
xmlEncoding(
unique int id: @file ref,
string encoding: string ref
);
xmlDTDs(
unique int id: @xmldtd,
string root: string ref,
string publicId: string ref,
string systemId: string ref,
int fileid: @file ref
);
xmlElements(
unique int id: @xmlelement,
string name: string ref,
int parentid: @xmlparent ref,
int idx: int ref,
int fileid: @file ref
);
xmlAttrs(
unique int id: @xmlattribute,
int elementid: @xmlelement ref,
string name: string ref,
string value: string ref,
int idx: int ref,
int fileid: @file ref
);
xmlNs(
int id: @xmlnamespace,
string prefixName: string ref,
string URI: string ref,
int fileid: @file ref
);
xmlHasNs(
int elementId: @xmlnamespaceable ref,
int nsId: @xmlnamespace ref,
int fileid: @file ref
);
xmlComments(
unique int id: @xmlcomment,
string text: string ref,
int parentid: @xmlparent ref,
int fileid: @file ref
);
xmlChars(
unique int id: @xmlcharacters,
string text: string ref,
int parentid: @xmlparent ref,
int idx: int ref,
int isCDATA: int ref,
int fileid: @file ref
);
@xmlparent = @file | @xmlelement;
@xmlnamespaceable = @xmlelement | @xmlattribute;
xmllocations(
int xmlElement: @xmllocatable ref,
int location: @location_default ref
);
@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace;
compilations(unique int id: @compilation, string cwd: string ref);
#keyset[id, num]
compilation_args(int id: @compilation ref, int num: int ref, string arg: string ref);
#keyset[id, num, kind]
compilation_time(int id: @compilation ref, int num: int ref, int kind: int ref, float secs: float ref);
diagnostic_for(unique int diagnostic: @diagnostic ref, int compilation: @compilation ref, int file_number: int ref, int file_number_diagnostic_number: int ref);
compilation_finished(unique int id: @compilation ref, float cpu_seconds: float ref, float elapsed_seconds: float ref);
#keyset[id, num]
compilation_compiling_files(int id: @compilation ref, int num: int ref, int file: @file ref);
diagnostics(unique int id: @diagnostic, int severity: int ref, string error_tag: string ref, string error_message: string ref,
string full_error_message: string ref, int location: @location ref);
locations_default(unique int id: @location_default, int file: @file ref, int beginLine: int ref, int beginColumn: int ref,
int endLine: int ref, int endColumn: int ref);
numlines(int element_id: @sourceline ref, int num_lines: int ref, int num_code: int ref, int num_comment: int ref);
files(unique int id: @file, string name: string ref);
folders(unique int id: @folder, string name: string ref);
containerparent(int parent: @container ref, unique int child: @container ref);
has_location(unique int locatable: @locatable ref, int location: @location ref);
#keyset[parent, idx]
comment_groups(unique int id: @comment_group, int parent: @file ref, int idx: int ref);
comments(unique int id: @comment, int kind: int ref, int parent: @comment_group ref, int idx: int ref, string text: string ref);
doc_comments(unique int node: @documentable ref, int comment: @comment_group ref);
#keyset[parent, idx]
exprs(unique int id: @expr, int kind: int ref, int parent: @exprparent ref, int idx: int ref);
literals(unique int expr: @expr ref, string value: string ref, string raw: string ref);
constvalues(unique int expr: @expr ref, string value: string ref, string exact: string ref);
fields(unique int id: @field, int parent: @fieldparent ref, int idx: int ref);
typeparamdecls(unique int id: @typeparamdecl, int parent: @typeparamdeclparent ref, int idx: int ref);
#keyset[parent, idx]
stmts(unique int id: @stmt, int kind: int ref, int parent: @stmtparent ref, int idx: int ref);
#keyset[parent, idx]
decls(unique int id: @decl, int kind: int ref, int parent: @declparent ref, int idx: int ref);
#keyset[parent, idx]
specs(unique int id: @spec, int kind: int ref, int parent: @gendecl ref, int idx: int ref);
scopes(unique int id: @scope, int kind: int ref);
scopenesting(unique int inner: @scope ref, int outer: @scope ref);
scopenodes(unique int node: @scopenode ref, int scope: @localscope ref);
objects(unique int id: @object, int kind: int ref, string name: string ref);
objectscopes(unique int object: @object ref, int scope: @scope ref);
objecttypes(unique int object: @object ref, int tp: @type ref);
methodreceivers(unique int method: @object ref, int receiver: @object ref);
fieldstructs(unique int field: @object ref, int struct: @structtype ref);
methodhosts(int method: @object ref, int host: @definedtype ref);
defs(int ident: @ident ref, int object: @object ref);
uses(int ident: @ident ref, int object: @object ref);
types(unique int id: @type, int kind: int ref);
type_of(unique int expr: @expr ref, int tp: @type ref);
typename(unique int tp: @type ref, string name: string ref);
key_type(unique int map: @maptype ref, int tp: @type ref);
element_type(unique int container: @containertype ref, int tp: @type ref);
base_type(unique int ptr: @pointertype ref, int tp: @type ref);
underlying_type(unique int defined: @definedtype ref, int tp: @type ref);
#keyset[parent, index]
component_types(int parent: @compositetype ref, int index: int ref, string name: string ref, int tp: @type ref);
#keyset[parent, index]
struct_tags(int parent: @structtype ref, int index: int ref, string tag: string ref);
#keyset[interface, index]
interface_private_method_ids(int interface: @interfacetype ref, int index: int ref, string id: string ref);
array_length(unique int tp: @arraytype ref, string len: string ref);
type_objects(unique int tp: @type ref, int object: @object ref);
packages(unique int id: @package, string name: string ref, string path: string ref, int scope: @packagescope ref);
#keyset[parent, idx]
modexprs(unique int id: @modexpr, int kind: int ref, int parent: @modexprparent ref, int idx: int ref);
#keyset[parent, idx]
modtokens(string token: string ref, int parent: @modexpr ref, int idx: int ref);
#keyset[package, idx]
errors(unique int id: @error, int kind: int ref, string msg: string ref, string rawpos: string ref,
string file: string ref, int line: int ref, int col: int ref, int package: @package ref, int idx: int ref);
has_ellipsis(int id: @callorconversionexpr ref);
variadic(int id: @signaturetype ref);
#keyset[parent, idx]
typeparam(unique int tp: @typeparamtype ref, string name: string ref, int bound: @compositetype ref,
int parent: @typeparamparentobject ref, int idx: int ref);
@container = @file | @folder;
@locatable = @xmllocatable | @node | @localscope;
@node = @documentable | @exprparent | @modexprparent | @fieldparent | @stmtparent | @declparent | @typeparamdeclparent
| @scopenode | @comment_group | @comment;
@documentable = @file | @field | @typeparamdecl | @spec | @gendecl | @funcdecl | @modexpr;
@exprparent = @funcdef | @file | @expr | @field | @stmt | @decl | @typeparamdecl | @spec;
@modexprparent = @file | @modexpr;
@fieldparent = @decl | @structtypeexpr | @functypeexpr | @interfacetypeexpr;
@stmtparent = @funcdef | @stmt | @decl;
@declparent = @file | @declstmt;
@typeparamdeclparent = @funcdecl | @typespec;
@funcdef = @funclit | @funcdecl;
@scopenode = @file | @functypeexpr | @blockstmt | @ifstmt | @caseclause | @switchstmt | @commclause | @loopstmt;
@location = @location_default;
@sourceline = @locatable;
case @comment.kind of
0 = @slashslashcomment
| 1 = @slashstarcomment;
case @expr.kind of
0 = @badexpr
| 1 = @ident
| 2 = @ellipsis
| 3 = @intlit
| 4 = @floatlit
| 5 = @imaglit
| 6 = @charlit
| 7 = @stringlit
| 8 = @funclit
| 9 = @compositelit
| 10 = @parenexpr
| 11 = @selectorexpr
| 12 = @indexexpr
| 13 = @genericfunctioninstantiationexpr
| 14 = @generictypeinstantiationexpr
| 15 = @sliceexpr
| 16 = @typeassertexpr
| 17 = @callorconversionexpr
| 18 = @starexpr
| 19 = @keyvalueexpr
| 20 = @arraytypeexpr
| 21 = @structtypeexpr
| 22 = @functypeexpr
| 23 = @interfacetypeexpr
| 24 = @maptypeexpr
| 25 = @typesetliteralexpr
| 26 = @plusexpr
| 27 = @minusexpr
| 28 = @notexpr
| 29 = @complementexpr
| 30 = @derefexpr
| 31 = @addressexpr
| 32 = @arrowexpr
| 33 = @lorexpr
| 34 = @landexpr
| 35 = @eqlexpr
| 36 = @neqexpr
| 37 = @lssexpr
| 38 = @leqexpr
| 39 = @gtrexpr
| 40 = @geqexpr
| 41 = @addexpr
| 42 = @subexpr
| 43 = @orexpr
| 44 = @xorexpr
| 45 = @mulexpr
| 46 = @quoexpr
| 47 = @remexpr
| 48 = @shlexpr
| 49 = @shrexpr
| 50 = @andexpr
| 51 = @andnotexpr
| 52 = @sendchantypeexpr
| 53 = @recvchantypeexpr
| 54 = @sendrcvchantypeexpr
| 55 = @rangeelementexpr;
@basiclit = @intlit | @floatlit | @imaglit | @charlit | @stringlit;
@operatorexpr = @logicalexpr | @arithmeticexpr | @bitwiseexpr | @unaryexpr | @binaryexpr;
@logicalexpr = @logicalunaryexpr | @logicalbinaryexpr;
@arithmeticexpr = @arithmeticunaryexpr | @arithmeticbinaryexpr;
@bitwiseexpr = @bitwiseunaryexpr | @bitwisebinaryexpr;
@unaryexpr = @logicalunaryexpr | @bitwiseunaryexpr | @arithmeticunaryexpr | @derefexpr | @addressexpr | @arrowexpr;
@logicalunaryexpr = @notexpr;
@bitwiseunaryexpr = @complementexpr;
@arithmeticunaryexpr = @plusexpr | @minusexpr;
@binaryexpr = @logicalbinaryexpr | @bitwisebinaryexpr | @arithmeticbinaryexpr | @comparison;
@logicalbinaryexpr = @lorexpr | @landexpr;
@bitwisebinaryexpr = @shiftexpr | @orexpr | @xorexpr | @andexpr | @andnotexpr;
@arithmeticbinaryexpr = @addexpr | @subexpr | @mulexpr | @quoexpr | @remexpr;
@shiftexpr = @shlexpr | @shrexpr;
@comparison = @equalitytest | @relationalcomparison;
@equalitytest = @eqlexpr | @neqexpr;
@relationalcomparison = @lssexpr | @leqexpr | @gtrexpr | @geqexpr;
@chantypeexpr = @sendchantypeexpr | @recvchantypeexpr | @sendrcvchantypeexpr;
case @stmt.kind of
0 = @badstmt
| 1 = @declstmt
| 2 = @emptystmt
| 3 = @labeledstmt
| 4 = @exprstmt
| 5 = @sendstmt
| 6 = @incstmt
| 7 = @decstmt
| 8 = @gostmt
| 9 = @deferstmt
| 10 = @returnstmt
| 11 = @breakstmt
| 12 = @continuestmt
| 13 = @gotostmt
| 14 = @fallthroughstmt
| 15 = @blockstmt
| 16 = @ifstmt
| 17 = @caseclause
| 18 = @exprswitchstmt
| 19 = @typeswitchstmt
| 20 = @commclause
| 21 = @selectstmt
| 22 = @forstmt
| 23 = @rangestmt
| 24 = @assignstmt
| 25 = @definestmt
| 26 = @addassignstmt
| 27 = @subassignstmt
| 28 = @mulassignstmt
| 29 = @quoassignstmt
| 30 = @remassignstmt
| 31 = @andassignstmt
| 32 = @orassignstmt
| 33 = @xorassignstmt
| 34 = @shlassignstmt
| 35 = @shrassignstmt
| 36 = @andnotassignstmt;
@incdecstmt = @incstmt | @decstmt;
@assignment = @simpleassignstmt | @compoundassignstmt;
@simpleassignstmt = @assignstmt | @definestmt;
@compoundassignstmt = @addassignstmt | @subassignstmt | @mulassignstmt | @quoassignstmt | @remassignstmt
| @andassignstmt | @orassignstmt | @xorassignstmt | @shlassignstmt | @shrassignstmt | @andnotassignstmt;
@branchstmt = @breakstmt | @continuestmt | @gotostmt | @fallthroughstmt;
@switchstmt = @exprswitchstmt | @typeswitchstmt;
@loopstmt = @forstmt | @rangestmt;
case @decl.kind of
0 = @baddecl
| 1 = @importdecl
| 2 = @constdecl
| 3 = @typedecl
| 4 = @vardecl
| 5 = @funcdecl;
@gendecl = @importdecl | @constdecl | @typedecl | @vardecl;
case @spec.kind of
0 = @importspec
| 1 = @valuespec
| 2 = @typedefspec
| 3 = @aliasspec;
@typespec = @typedefspec | @aliasspec;
case @object.kind of
0 = @pkgobject
| 1 = @decltypeobject
| 2 = @builtintypeobject
| 3 = @declconstobject
| 4 = @builtinconstobject
| 5 = @declvarobject
| 6 = @declfunctionobject
| 7 = @builtinfunctionobject
| 8 = @labelobject;
@typeparamparentobject = @decltypeobject | @declfunctionobject;
@declobject = @decltypeobject | @declconstobject | @declvarobject | @declfunctionobject;
@builtinobject = @builtintypeobject | @builtinconstobject | @builtinfunctionobject;
@typeobject = @decltypeobject | @builtintypeobject;
@valueobject = @constobject | @varobject | @functionobject;
@constobject = @declconstobject | @builtinconstobject;
@varobject = @declvarobject;
@functionobject = @declfunctionobject | @builtinfunctionobject;
case @scope.kind of
0 = @universescope
| 1 = @packagescope
| 2 = @localscope;
case @type.kind of
0 = @invalidtype
| 1 = @boolexprtype
| 2 = @inttype
| 3 = @int8type
| 4 = @int16type
| 5 = @int32type
| 6 = @int64type
| 7 = @uinttype
| 8 = @uint8type
| 9 = @uint16type
| 10 = @uint32type
| 11 = @uint64type
| 12 = @uintptrtype
| 13 = @float32type
| 14 = @float64type
| 15 = @complex64type
| 16 = @complex128type
| 17 = @stringexprtype
| 18 = @unsafepointertype
| 19 = @boolliteraltype
| 20 = @intliteraltype
| 21 = @runeliteraltype
| 22 = @floatliteraltype
| 23 = @complexliteraltype
| 24 = @stringliteraltype
| 25 = @nilliteraltype
| 26 = @typeparamtype
| 27 = @arraytype
| 28 = @slicetype
| 29 = @structtype
| 30 = @pointertype
| 31 = @interfacetype
| 32 = @tupletype
| 33 = @signaturetype
| 34 = @maptype
| 35 = @sendchantype
| 36 = @recvchantype
| 37 = @sendrcvchantype
| 38 = @definedtype
| 39 = @typesetliteraltype;
@basictype = @booltype | @numerictype | @stringtype | @literaltype | @invalidtype | @unsafepointertype;
@booltype = @boolexprtype | @boolliteraltype;
@numerictype = @integertype | @floattype | @complextype;
@integertype = @signedintegertype | @unsignedintegertype;
@signedintegertype = @inttype | @int8type | @int16type | @int32type | @int64type | @intliteraltype | @runeliteraltype;
@unsignedintegertype = @uinttype | @uint8type | @uint16type | @uint32type | @uint64type | @uintptrtype;
@floattype = @float32type | @float64type | @floatliteraltype;
@complextype = @complex64type | @complex128type | @complexliteraltype;
@stringtype = @stringexprtype | @stringliteraltype;
@literaltype = @boolliteraltype | @intliteraltype | @runeliteraltype | @floatliteraltype | @complexliteraltype
| @stringliteraltype | @nilliteraltype;
@compositetype = @typeparamtype | @containertype | @structtype | @pointertype | @interfacetype | @tupletype
| @signaturetype | @definedtype | @typesetliteraltype;
@containertype = @arraytype | @slicetype | @maptype | @chantype;
@chantype = @sendchantype | @recvchantype | @sendrcvchantype;
case @modexpr.kind of
0 = @modcommentblock
| 1 = @modline
| 2 = @modlineblock
| 3 = @modlparen
| 4 = @modrparen;
case @error.kind of
0 = @unknownerror
| 1 = @listerror
| 2 = @parseerror
| 3 = @typeerror;

View File

@@ -0,0 +1,4 @@
description: Remove @rangeelementexpr, reparenting range loop variables onto the range statement
compatibility: full
exprs.rel: run exprs.qlo
has_location.rel: run has_location.qlo

View File

@@ -532,6 +532,12 @@ var ChanTypeExprs = map[ast.ChanDir]*BranchType{
ast.SEND | ast.RECV: ExprKind.NewBranch("@sendrcvchantypeexpr", ChanTypeExpr),
}
// RangeElementExpr is the type of the synthesized node representing the loop
// variables (key and value) bound by a `range` statement. It groups the key and
// value expressions into a single "tuple pattern" target, mirroring how other
// languages present a single variable node for a `foreach` loop.
var RangeElementExpr = ExprKind.NewBranch("@rangeelementexpr")
// StmtKind is a case type for distinguishing different kinds of statement AST nodes
var StmtKind = NewCaseType(StmtType, "kind")

View File

@@ -1416,8 +1416,18 @@ func extractStmt(tw *trap.Writer, stmt ast.Stmt, parent trap.Label, idx int) {
emitScopeNodeInfo(tw, stmt, lbl)
case *ast.RangeStmt:
kind = dbscheme.RangeStmtType.Index()
extractExpr(tw, stmt.Key, lbl, 0, false)
extractExpr(tw, stmt.Value, lbl, 1, false)
// Synthesize a "range element" node that groups the loop variables (the
// key and value) into a single target. This mirrors how other languages
// present a single loop-variable node for a `foreach` loop and lets the
// shared control-flow library drive the destructuring through this node.
patternLbl := tw.Labeler.FreshID()
dbscheme.ExprsTable.Emit(tw, patternLbl, dbscheme.RangeElementExpr.Index(), lbl, 0)
// The range element node uses the location of the whole range statement,
// so that the destructuring control-flow and data-flow nodes derived from
// it keep the same location they had before this node was introduced.
extractNodeLocation(tw, stmt, patternLbl)
extractExpr(tw, stmt.Key, patternLbl, 0, false)
extractExpr(tw, stmt.Value, patternLbl, 1, false)
extractExpr(tw, stmt.X, lbl, 2, false)
extractStmt(tw, stmt.Body, lbl, 3)
emitScopeNodeInfo(tw, stmt, lbl)

View File

@@ -336,7 +336,8 @@ case @expr.kind of
| 51 = @andnotexpr
| 52 = @sendchantypeexpr
| 53 = @recvchantypeexpr
| 54 = @sendrcvchantypeexpr;
| 54 = @sendrcvchantypeexpr
| 55 = @rangeelementexpr;
@basiclit = @intlit | @floatlit | @imaglit | @charlit | @stringlit;

View File

@@ -1148,11 +1148,14 @@ class ForStmt extends @forstmt, LoopStmt {
* ```
*/
class RangeStmt extends @rangestmt, LoopStmt {
/** Gets the synthesized node grouping the loop variables of this `range` statement. */
RangeElementExpr getPattern() { result = this.getChildExpr(0) }
/** Gets the expression denoting the key of this `range` statement. */
Expr getKey() { result = this.getChildExpr(0) }
Expr getKey() { result = this.getPattern().getKey() }
/** Get the expression denoting the value of this `range` statement. */
Expr getValue() { result = this.getChildExpr(1) }
Expr getValue() { result = this.getPattern().getValue() }
/** Gets the domain of this `range` statement. */
Expr getDomain() { result = this.getChildExpr(2) }
@@ -1165,3 +1168,31 @@ class RangeStmt extends @rangestmt, LoopStmt {
override string getAPrimaryQlClass() { result = "RangeStmt" }
}
/**
* A synthesized node grouping the loop variables (key and value) bound by a
* `range` statement.
*
* This node acts as the single target of the destructuring performed on each
* iteration of the loop, so that a `range` statement can be modelled with a
* single loop-variable node in the same way as a `foreach` loop in other
* languages. It is present for every `range` statement, even when no loop
* variables are bound (as in `for range x`).
*/
class RangeElementExpr extends @rangeelementexpr, Expr {
/** Gets the `range` statement that this node belongs to. */
RangeStmt getRangeStmt() { result = this.getParent() }
/** Gets the expression denoting the key of the `range` statement. */
Expr getKey() { result = this.getChildExpr(0) }
/** Gets the expression denoting the value of the `range` statement. */
Expr getValue() { result = this.getChildExpr(1) }
/** Gets the domain of the `range` statement. */
Expr getDomain() { result = this.getRangeStmt().getDomain() }
override string toString() { result = "range element" }
override string getAPrimaryQlClass() { result = "RangeElementExpr" }
}

View File

@@ -212,11 +212,17 @@ module GoCfg {
}
class ForeachStmt extends LoopStmt {
ForeachStmt() { none() }
ForeachStmt() { this instanceof Go::RangeStmt }
Expr getVariable() { none() }
// Go's `range` statement binds its key and value by destructuring the
// current element. The extractor synthesizes a single "range element"
// node grouping the key and value (see `Go::RangeElementExpr`), which we
// present here as the loop variable. The shared library routes control
// flow into and out of this node, and Go wires the destructuring through
// it (see `rangeStmtStep`).
Expr getVariable() { result = this.(Go::RangeStmt).getPattern() }
Expr getCollection() { none() }
Expr getCollection() { result = this.(Go::RangeStmt).getDomain() }
}
class BreakStmt = Go::BreakStmt;
@@ -504,13 +510,16 @@ module GoCfg {
or
notBlankIdent(n.(Go::ValueSpec).getNameExpr(i))
or
notBlankIdent(n.(Go::RangeStmt).getKey()) and i = 0
notBlankIdent(n.(Go::RangeElementExpr).getKey()) and i = 0
or
notBlankIdent(n.(Go::RangeStmt).getValue()) and i = 1
notBlankIdent(n.(Go::RangeElementExpr).getValue()) and i = 1
) and
tag = "assign:" + i.toString()
)
or
// Get the next key-value pair produced by a `range` statement.
n instanceof Go::RangeElementExpr and tag = "next"
or
// Compound assignment implicit RHS
n instanceof Go::CompoundAssignStmt and tag = "compound-rhs"
or
@@ -574,9 +583,6 @@ module GoCfg {
tag = "result-zero-init:" + i.toString()
)
or
// Next node for range statements
n instanceof Go::RangeStmt and tag = "next"
or
// Implicit deref
implicitDerefCondition(n) and tag = "implicit-deref"
or
@@ -632,10 +638,10 @@ module GoCfg {
exists(spec.getNameExpr(i))
)
or
exists(Go::RangeStmt rs | s = rs |
exists(rs.getKey()) and i = 0
exists(Go::RangeElementExpr p | s = p |
exists(p.getKey()) and i = 0
or
exists(rs.getValue()) and i = 1
exists(p.getValue()) and i = 1
)
or
exists(Go::ReturnStmt ret, Go::SignatureType rettp |
@@ -1010,7 +1016,7 @@ module GoCfg {
predicate overridesCallableBodyExit(Ast::Callable c) { funcHasDefer(c.(Go::FuncDef)) }
predicate step(PreControlFlowNode n1, PreControlFlowNode n2) {
rangeLoop(n1, n2) or
rangeStmtStep(n1, n2) or
selectStmt(n1, n2) or
deferStmt(n1, n2) or
goStmtStep(n1, n2) or
@@ -1139,9 +1145,9 @@ module GoCfg {
or
notBlankIdent(assgn.(Go::ValueSpec).getNameExpr(j))
or
notBlankIdent(assgn.(Go::RangeStmt).getKey()) and j = 0
notBlankIdent(assgn.(Go::RangeElementExpr).getKey()) and j = 0
or
notBlankIdent(assgn.(Go::RangeStmt).getValue()) and j = 1
notBlankIdent(assgn.(Go::RangeElementExpr).getValue()) and j = 1
) and
result = "assign:" + j.toString() and
ord = 2 * j + 1
@@ -1511,34 +1517,31 @@ module GoCfg {
)
}
private predicate rangeLoop(PreControlFlowNode n1, PreControlFlowNode n2) {
exists(Go::RangeStmt s |
// Use the shared library's auto-created `[LoopHeader]` additional node
// (created for every `LoopStmt`) as the join/branch point of the range loop.
n1.isBefore(s) and n2.isBefore(s.getDomain())
private predicate rangeStmtStep(PreControlFlowNode n1, PreControlFlowNode n2) {
exists(Go::RangeElementExpr p |
// The shared `ForeachStmt` model owns the loop skeleton (testing the
// domain for emptiness, the `[LoopHeader]` join/branch point, and the
// loop exit) and routes control flow into `Before(p)` and out of
// `After(p)`, where `p` is the synthesized "range element" loop
// variable. Here we get the next key-value pair and destructure it into
// the key/value variables using the shared extract/assign epilogue
// machinery.
n1.isBefore(p) and n2.isAdditional(p, "next")
or
n1.isAfter(s.getDomain()) and n2.isAdditional(s, "[LoopHeader]")
or
n1.isAdditional(s, "[LoopHeader]") and n2.isAdditional(s, "next")
or
n1.isAdditional(s, "next") and
n1.isAdditional(p, "next") and
(
exists(getFirstEpilogueTag(s)) and n2.isAdditional(s, getFirstEpilogueTag(s))
exists(getFirstEpilogueTag(p)) and n2.isAdditional(p, getFirstEpilogueTag(p))
or
not exists(getFirstEpilogueTag(s)) and n2.isBefore(s.getBody())
not exists(getFirstEpilogueTag(p)) and n2.isAfter(p)
)
or
exists(string tag1, string tag2 |
epilogueSucc(s, tag1, tag2) and
n1.isAdditional(s, tag1) and
n2.isAdditional(s, tag2)
epilogueSucc(p, tag1, tag2) and
n1.isAdditional(p, tag1) and
n2.isAdditional(p, tag2)
)
or
n1.isAdditional(s, getLastEpilogueTag(s)) and n2.isBefore(s.getBody())
or
n1.isAfter(s.getBody()) and n2.isAdditional(s, "[LoopHeader]")
or
n1.isAdditional(s, "[LoopHeader]") and n2.isAfter(s)
n1.isAdditional(p, getLastEpilogueTag(p)) and n2.isAfter(p)
)
}

View File

@@ -709,7 +709,7 @@ module IR {
or
exists(assgn.(ValueSpec).getNameExpr(i))
or
assgn instanceof RangeStmt and i in [0, 1]
assgn instanceof RangeElementExpr and i in [0, 1]
)
}
@@ -763,7 +763,7 @@ module IR {
or
exists(s.(ValueSpec).getNameExpr(i))
or
s instanceof RangeStmt and i in [0, 1]
s instanceof RangeElementExpr and i in [0, 1]
or
exists(s.(ReturnStmt).getEnclosingFunction().getType().(SignatureType).getResultType(i))
or
@@ -803,7 +803,9 @@ module IR {
result = e.getType().(TupleType).getComponentType(pragma[only_bind_into](i))
)
or
exists(Type rangeType | rangeType = s.(RangeStmt).getDomain().getType().getUnderlyingType() |
exists(Type rangeType |
rangeType = s.(RangeElementExpr).getDomain().getType().getUnderlyingType()
|
exists(Type baseType |
baseType = rangeType.(ArrayType).getElementType() or
baseType =
@@ -1105,16 +1107,16 @@ module IR {
/** An instruction that gets the next key-value pair in a range loop. */
class GetNextEntryInstruction extends Instruction {
RangeStmt rs;
RangeElementExpr p;
GetNextEntryInstruction() { this.isAdditional(rs, "next") }
GetNextEntryInstruction() { this.isAdditional(p, "next") }
/**
* Gets the instruction computing the value whose key-value pairs this instruction reads.
*/
Instruction getDomain() { result = evalExprInstruction(rs.getDomain()) }
Instruction getDomain() { result = evalExprInstruction(p.getDomain()) }
override ControlFlow::Root getRoot() { result.isRootOf(rs) }
override ControlFlow::Root getRoot() { result.isRootOf(p.getRangeStmt()) }
}
/**
@@ -1240,10 +1242,10 @@ module IR {
or
lhs = assgn.(ValueSpec).getNameExpr(i)
or
exists(RangeStmt rs | rs = assgn |
i = 0 and lhs = rs.getKey().stripParens()
exists(RangeElementExpr p | p = assgn |
i = 0 and lhs = p.getKey().stripParens()
or
i = 1 and lhs = rs.getValue().stripParens()
i = 1 and lhs = p.getValue().stripParens()
)
)
or
@@ -1496,13 +1498,17 @@ module IR {
* Gets the instruction corresponding to the assignment of the key variable
* of range statement `rs`.
*/
AssignInstruction assignKeyInstruction(RangeStmt rs) { result.isAdditional(rs, "assign:0") }
AssignInstruction assignKeyInstruction(RangeStmt rs) {
result.isAdditional(rs.getPattern(), "assign:0")
}
/**
* Gets the instruction corresponding to the assignment of the value variable
* of range statement `rs`.
*/
AssignInstruction assignValueInstruction(RangeStmt rs) { result.isAdditional(rs, "assign:1") }
AssignInstruction assignValueInstruction(RangeStmt rs) {
result.isAdditional(rs.getPattern(), "assign:1")
}
/**
* Gets the instruction corresponding to the implicit initialization of `v`

View File

@@ -0,0 +1,564 @@
/** Auto-generated dbscheme; do not edit. Run `make gen` in directory `go/` to regenerate. */
/** Duplicate code **/
duplicateCode(
unique int id : @duplication,
varchar(900) relativePath : string ref,
int equivClass : int ref);
similarCode(
unique int id : @similarity,
varchar(900) relativePath : string ref,
int equivClass : int ref);
@duplication_or_similarity = @duplication | @similarity;
tokens(
int id : @duplication_or_similarity ref,
int offset : int ref,
int beginLine : int ref,
int beginColumn : int ref,
int endLine : int ref,
int endColumn : int ref);
/** External data **/
externalData(
int id : @externalDataElement,
varchar(900) path : string ref,
int column: int ref,
varchar(900) value : string ref
);
snapshotDate(unique date snapshotDate : date ref);
sourceLocationPrefix(varchar(900) prefix : string ref);
/** Overlay support **/
databaseMetadata(
string metadataKey: string ref,
string value: string ref
);
overlayChangedFiles(
string path: string ref
);
/*
* XML Files
*/
xmlEncoding(
unique int id: @file ref,
string encoding: string ref
);
xmlDTDs(
unique int id: @xmldtd,
string root: string ref,
string publicId: string ref,
string systemId: string ref,
int fileid: @file ref
);
xmlElements(
unique int id: @xmlelement,
string name: string ref,
int parentid: @xmlparent ref,
int idx: int ref,
int fileid: @file ref
);
xmlAttrs(
unique int id: @xmlattribute,
int elementid: @xmlelement ref,
string name: string ref,
string value: string ref,
int idx: int ref,
int fileid: @file ref
);
xmlNs(
int id: @xmlnamespace,
string prefixName: string ref,
string URI: string ref,
int fileid: @file ref
);
xmlHasNs(
int elementId: @xmlnamespaceable ref,
int nsId: @xmlnamespace ref,
int fileid: @file ref
);
xmlComments(
unique int id: @xmlcomment,
string text: string ref,
int parentid: @xmlparent ref,
int fileid: @file ref
);
xmlChars(
unique int id: @xmlcharacters,
string text: string ref,
int parentid: @xmlparent ref,
int idx: int ref,
int isCDATA: int ref,
int fileid: @file ref
);
@xmlparent = @file | @xmlelement;
@xmlnamespaceable = @xmlelement | @xmlattribute;
xmllocations(
int xmlElement: @xmllocatable ref,
int location: @location_default ref
);
@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace;
compilations(unique int id: @compilation, string cwd: string ref);
#keyset[id, num]
compilation_args(int id: @compilation ref, int num: int ref, string arg: string ref);
#keyset[id, num, kind]
compilation_time(int id: @compilation ref, int num: int ref, int kind: int ref, float secs: float ref);
diagnostic_for(unique int diagnostic: @diagnostic ref, int compilation: @compilation ref, int file_number: int ref, int file_number_diagnostic_number: int ref);
compilation_finished(unique int id: @compilation ref, float cpu_seconds: float ref, float elapsed_seconds: float ref);
#keyset[id, num]
compilation_compiling_files(int id: @compilation ref, int num: int ref, int file: @file ref);
diagnostics(unique int id: @diagnostic, int severity: int ref, string error_tag: string ref, string error_message: string ref,
string full_error_message: string ref, int location: @location ref);
locations_default(unique int id: @location_default, int file: @file ref, int beginLine: int ref, int beginColumn: int ref,
int endLine: int ref, int endColumn: int ref);
numlines(int element_id: @sourceline ref, int num_lines: int ref, int num_code: int ref, int num_comment: int ref);
files(unique int id: @file, string name: string ref);
folders(unique int id: @folder, string name: string ref);
containerparent(int parent: @container ref, unique int child: @container ref);
has_location(unique int locatable: @locatable ref, int location: @location ref);
#keyset[parent, idx]
comment_groups(unique int id: @comment_group, int parent: @file ref, int idx: int ref);
comments(unique int id: @comment, int kind: int ref, int parent: @comment_group ref, int idx: int ref, string text: string ref);
doc_comments(unique int node: @documentable ref, int comment: @comment_group ref);
#keyset[parent, idx]
exprs(unique int id: @expr, int kind: int ref, int parent: @exprparent ref, int idx: int ref);
literals(unique int expr: @expr ref, string value: string ref, string raw: string ref);
constvalues(unique int expr: @expr ref, string value: string ref, string exact: string ref);
fields(unique int id: @field, int parent: @fieldparent ref, int idx: int ref);
typeparamdecls(unique int id: @typeparamdecl, int parent: @typeparamdeclparent ref, int idx: int ref);
#keyset[parent, idx]
stmts(unique int id: @stmt, int kind: int ref, int parent: @stmtparent ref, int idx: int ref);
#keyset[parent, idx]
decls(unique int id: @decl, int kind: int ref, int parent: @declparent ref, int idx: int ref);
#keyset[parent, idx]
specs(unique int id: @spec, int kind: int ref, int parent: @gendecl ref, int idx: int ref);
scopes(unique int id: @scope, int kind: int ref);
scopenesting(unique int inner: @scope ref, int outer: @scope ref);
scopenodes(unique int node: @scopenode ref, int scope: @localscope ref);
objects(unique int id: @object, int kind: int ref, string name: string ref);
objectscopes(unique int object: @object ref, int scope: @scope ref);
objecttypes(unique int object: @object ref, int tp: @type ref);
methodreceivers(unique int method: @object ref, int receiver: @object ref);
fieldstructs(unique int field: @object ref, int struct: @structtype ref);
methodhosts(int method: @object ref, int host: @definedtype ref);
defs(int ident: @ident ref, int object: @object ref);
uses(int ident: @ident ref, int object: @object ref);
types(unique int id: @type, int kind: int ref);
type_of(unique int expr: @expr ref, int tp: @type ref);
typename(unique int tp: @type ref, string name: string ref);
key_type(unique int map: @maptype ref, int tp: @type ref);
element_type(unique int container: @containertype ref, int tp: @type ref);
base_type(unique int ptr: @pointertype ref, int tp: @type ref);
underlying_type(unique int defined: @definedtype ref, int tp: @type ref);
#keyset[parent, index]
component_types(int parent: @compositetype ref, int index: int ref, string name: string ref, int tp: @type ref);
#keyset[parent, index]
struct_tags(int parent: @structtype ref, int index: int ref, string tag: string ref);
#keyset[interface, index]
interface_private_method_ids(int interface: @interfacetype ref, int index: int ref, string id: string ref);
array_length(unique int tp: @arraytype ref, string len: string ref);
type_objects(unique int tp: @type ref, int object: @object ref);
packages(unique int id: @package, string name: string ref, string path: string ref, int scope: @packagescope ref);
#keyset[parent, idx]
modexprs(unique int id: @modexpr, int kind: int ref, int parent: @modexprparent ref, int idx: int ref);
#keyset[parent, idx]
modtokens(string token: string ref, int parent: @modexpr ref, int idx: int ref);
#keyset[package, idx]
errors(unique int id: @error, int kind: int ref, string msg: string ref, string rawpos: string ref,
string file: string ref, int line: int ref, int col: int ref, int package: @package ref, int idx: int ref);
has_ellipsis(int id: @callorconversionexpr ref);
variadic(int id: @signaturetype ref);
#keyset[parent, idx]
typeparam(unique int tp: @typeparamtype ref, string name: string ref, int bound: @compositetype ref,
int parent: @typeparamparentobject ref, int idx: int ref);
@container = @file | @folder;
@locatable = @xmllocatable | @node | @localscope;
@node = @documentable | @exprparent | @modexprparent | @fieldparent | @stmtparent | @declparent | @typeparamdeclparent
| @scopenode | @comment_group | @comment;
@documentable = @file | @field | @typeparamdecl | @spec | @gendecl | @funcdecl | @modexpr;
@exprparent = @funcdef | @file | @expr | @field | @stmt | @decl | @typeparamdecl | @spec;
@modexprparent = @file | @modexpr;
@fieldparent = @decl | @structtypeexpr | @functypeexpr | @interfacetypeexpr;
@stmtparent = @funcdef | @stmt | @decl;
@declparent = @file | @declstmt;
@typeparamdeclparent = @funcdecl | @typespec;
@funcdef = @funclit | @funcdecl;
@scopenode = @file | @functypeexpr | @blockstmt | @ifstmt | @caseclause | @switchstmt | @commclause | @loopstmt;
@location = @location_default;
@sourceline = @locatable;
case @comment.kind of
0 = @slashslashcomment
| 1 = @slashstarcomment;
case @expr.kind of
0 = @badexpr
| 1 = @ident
| 2 = @ellipsis
| 3 = @intlit
| 4 = @floatlit
| 5 = @imaglit
| 6 = @charlit
| 7 = @stringlit
| 8 = @funclit
| 9 = @compositelit
| 10 = @parenexpr
| 11 = @selectorexpr
| 12 = @indexexpr
| 13 = @genericfunctioninstantiationexpr
| 14 = @generictypeinstantiationexpr
| 15 = @sliceexpr
| 16 = @typeassertexpr
| 17 = @callorconversionexpr
| 18 = @starexpr
| 19 = @keyvalueexpr
| 20 = @arraytypeexpr
| 21 = @structtypeexpr
| 22 = @functypeexpr
| 23 = @interfacetypeexpr
| 24 = @maptypeexpr
| 25 = @typesetliteralexpr
| 26 = @plusexpr
| 27 = @minusexpr
| 28 = @notexpr
| 29 = @complementexpr
| 30 = @derefexpr
| 31 = @addressexpr
| 32 = @arrowexpr
| 33 = @lorexpr
| 34 = @landexpr
| 35 = @eqlexpr
| 36 = @neqexpr
| 37 = @lssexpr
| 38 = @leqexpr
| 39 = @gtrexpr
| 40 = @geqexpr
| 41 = @addexpr
| 42 = @subexpr
| 43 = @orexpr
| 44 = @xorexpr
| 45 = @mulexpr
| 46 = @quoexpr
| 47 = @remexpr
| 48 = @shlexpr
| 49 = @shrexpr
| 50 = @andexpr
| 51 = @andnotexpr
| 52 = @sendchantypeexpr
| 53 = @recvchantypeexpr
| 54 = @sendrcvchantypeexpr
| 55 = @rangeelementexpr;
@basiclit = @intlit | @floatlit | @imaglit | @charlit | @stringlit;
@operatorexpr = @logicalexpr | @arithmeticexpr | @bitwiseexpr | @unaryexpr | @binaryexpr;
@logicalexpr = @logicalunaryexpr | @logicalbinaryexpr;
@arithmeticexpr = @arithmeticunaryexpr | @arithmeticbinaryexpr;
@bitwiseexpr = @bitwiseunaryexpr | @bitwisebinaryexpr;
@unaryexpr = @logicalunaryexpr | @bitwiseunaryexpr | @arithmeticunaryexpr | @derefexpr | @addressexpr | @arrowexpr;
@logicalunaryexpr = @notexpr;
@bitwiseunaryexpr = @complementexpr;
@arithmeticunaryexpr = @plusexpr | @minusexpr;
@binaryexpr = @logicalbinaryexpr | @bitwisebinaryexpr | @arithmeticbinaryexpr | @comparison;
@logicalbinaryexpr = @lorexpr | @landexpr;
@bitwisebinaryexpr = @shiftexpr | @orexpr | @xorexpr | @andexpr | @andnotexpr;
@arithmeticbinaryexpr = @addexpr | @subexpr | @mulexpr | @quoexpr | @remexpr;
@shiftexpr = @shlexpr | @shrexpr;
@comparison = @equalitytest | @relationalcomparison;
@equalitytest = @eqlexpr | @neqexpr;
@relationalcomparison = @lssexpr | @leqexpr | @gtrexpr | @geqexpr;
@chantypeexpr = @sendchantypeexpr | @recvchantypeexpr | @sendrcvchantypeexpr;
case @stmt.kind of
0 = @badstmt
| 1 = @declstmt
| 2 = @emptystmt
| 3 = @labeledstmt
| 4 = @exprstmt
| 5 = @sendstmt
| 6 = @incstmt
| 7 = @decstmt
| 8 = @gostmt
| 9 = @deferstmt
| 10 = @returnstmt
| 11 = @breakstmt
| 12 = @continuestmt
| 13 = @gotostmt
| 14 = @fallthroughstmt
| 15 = @blockstmt
| 16 = @ifstmt
| 17 = @caseclause
| 18 = @exprswitchstmt
| 19 = @typeswitchstmt
| 20 = @commclause
| 21 = @selectstmt
| 22 = @forstmt
| 23 = @rangestmt
| 24 = @assignstmt
| 25 = @definestmt
| 26 = @addassignstmt
| 27 = @subassignstmt
| 28 = @mulassignstmt
| 29 = @quoassignstmt
| 30 = @remassignstmt
| 31 = @andassignstmt
| 32 = @orassignstmt
| 33 = @xorassignstmt
| 34 = @shlassignstmt
| 35 = @shrassignstmt
| 36 = @andnotassignstmt;
@incdecstmt = @incstmt | @decstmt;
@assignment = @simpleassignstmt | @compoundassignstmt;
@simpleassignstmt = @assignstmt | @definestmt;
@compoundassignstmt = @addassignstmt | @subassignstmt | @mulassignstmt | @quoassignstmt | @remassignstmt
| @andassignstmt | @orassignstmt | @xorassignstmt | @shlassignstmt | @shrassignstmt | @andnotassignstmt;
@branchstmt = @breakstmt | @continuestmt | @gotostmt | @fallthroughstmt;
@switchstmt = @exprswitchstmt | @typeswitchstmt;
@loopstmt = @forstmt | @rangestmt;
case @decl.kind of
0 = @baddecl
| 1 = @importdecl
| 2 = @constdecl
| 3 = @typedecl
| 4 = @vardecl
| 5 = @funcdecl;
@gendecl = @importdecl | @constdecl | @typedecl | @vardecl;
case @spec.kind of
0 = @importspec
| 1 = @valuespec
| 2 = @typedefspec
| 3 = @aliasspec;
@typespec = @typedefspec | @aliasspec;
case @object.kind of
0 = @pkgobject
| 1 = @decltypeobject
| 2 = @builtintypeobject
| 3 = @declconstobject
| 4 = @builtinconstobject
| 5 = @declvarobject
| 6 = @declfunctionobject
| 7 = @builtinfunctionobject
| 8 = @labelobject;
@typeparamparentobject = @decltypeobject | @declfunctionobject;
@declobject = @decltypeobject | @declconstobject | @declvarobject | @declfunctionobject;
@builtinobject = @builtintypeobject | @builtinconstobject | @builtinfunctionobject;
@typeobject = @decltypeobject | @builtintypeobject;
@valueobject = @constobject | @varobject | @functionobject;
@constobject = @declconstobject | @builtinconstobject;
@varobject = @declvarobject;
@functionobject = @declfunctionobject | @builtinfunctionobject;
case @scope.kind of
0 = @universescope
| 1 = @packagescope
| 2 = @localscope;
case @type.kind of
0 = @invalidtype
| 1 = @boolexprtype
| 2 = @inttype
| 3 = @int8type
| 4 = @int16type
| 5 = @int32type
| 6 = @int64type
| 7 = @uinttype
| 8 = @uint8type
| 9 = @uint16type
| 10 = @uint32type
| 11 = @uint64type
| 12 = @uintptrtype
| 13 = @float32type
| 14 = @float64type
| 15 = @complex64type
| 16 = @complex128type
| 17 = @stringexprtype
| 18 = @unsafepointertype
| 19 = @boolliteraltype
| 20 = @intliteraltype
| 21 = @runeliteraltype
| 22 = @floatliteraltype
| 23 = @complexliteraltype
| 24 = @stringliteraltype
| 25 = @nilliteraltype
| 26 = @typeparamtype
| 27 = @arraytype
| 28 = @slicetype
| 29 = @structtype
| 30 = @pointertype
| 31 = @interfacetype
| 32 = @tupletype
| 33 = @signaturetype
| 34 = @maptype
| 35 = @sendchantype
| 36 = @recvchantype
| 37 = @sendrcvchantype
| 38 = @definedtype
| 39 = @typesetliteraltype;
@basictype = @booltype | @numerictype | @stringtype | @literaltype | @invalidtype | @unsafepointertype;
@booltype = @boolexprtype | @boolliteraltype;
@numerictype = @integertype | @floattype | @complextype;
@integertype = @signedintegertype | @unsignedintegertype;
@signedintegertype = @inttype | @int8type | @int16type | @int32type | @int64type | @intliteraltype | @runeliteraltype;
@unsignedintegertype = @uinttype | @uint8type | @uint16type | @uint32type | @uint64type | @uintptrtype;
@floattype = @float32type | @float64type | @floatliteraltype;
@complextype = @complex64type | @complex128type | @complexliteraltype;
@stringtype = @stringexprtype | @stringliteraltype;
@literaltype = @boolliteraltype | @intliteraltype | @runeliteraltype | @floatliteraltype | @complexliteraltype
| @stringliteraltype | @nilliteraltype;
@compositetype = @typeparamtype | @containertype | @structtype | @pointertype | @interfacetype | @tupletype
| @signaturetype | @definedtype | @typesetliteraltype;
@containertype = @arraytype | @slicetype | @maptype | @chantype;
@chantype = @sendchantype | @recvchantype | @sendrcvchantype;
case @modexpr.kind of
0 = @modcommentblock
| 1 = @modline
| 2 = @modlineblock
| 3 = @modlparen
| 4 = @modrparen;
case @error.kind of
0 = @unknownerror
| 1 = @listerror
| 2 = @parseerror
| 3 = @typeerror;

View File

@@ -0,0 +1,563 @@
/** Auto-generated dbscheme; do not edit. Run `make gen` in directory `go/` to regenerate. */
/** Duplicate code **/
duplicateCode(
unique int id : @duplication,
varchar(900) relativePath : string ref,
int equivClass : int ref);
similarCode(
unique int id : @similarity,
varchar(900) relativePath : string ref,
int equivClass : int ref);
@duplication_or_similarity = @duplication | @similarity;
tokens(
int id : @duplication_or_similarity ref,
int offset : int ref,
int beginLine : int ref,
int beginColumn : int ref,
int endLine : int ref,
int endColumn : int ref);
/** External data **/
externalData(
int id : @externalDataElement,
varchar(900) path : string ref,
int column: int ref,
varchar(900) value : string ref
);
snapshotDate(unique date snapshotDate : date ref);
sourceLocationPrefix(varchar(900) prefix : string ref);
/** Overlay support **/
databaseMetadata(
string metadataKey: string ref,
string value: string ref
);
overlayChangedFiles(
string path: string ref
);
/*
* XML Files
*/
xmlEncoding(
unique int id: @file ref,
string encoding: string ref
);
xmlDTDs(
unique int id: @xmldtd,
string root: string ref,
string publicId: string ref,
string systemId: string ref,
int fileid: @file ref
);
xmlElements(
unique int id: @xmlelement,
string name: string ref,
int parentid: @xmlparent ref,
int idx: int ref,
int fileid: @file ref
);
xmlAttrs(
unique int id: @xmlattribute,
int elementid: @xmlelement ref,
string name: string ref,
string value: string ref,
int idx: int ref,
int fileid: @file ref
);
xmlNs(
int id: @xmlnamespace,
string prefixName: string ref,
string URI: string ref,
int fileid: @file ref
);
xmlHasNs(
int elementId: @xmlnamespaceable ref,
int nsId: @xmlnamespace ref,
int fileid: @file ref
);
xmlComments(
unique int id: @xmlcomment,
string text: string ref,
int parentid: @xmlparent ref,
int fileid: @file ref
);
xmlChars(
unique int id: @xmlcharacters,
string text: string ref,
int parentid: @xmlparent ref,
int idx: int ref,
int isCDATA: int ref,
int fileid: @file ref
);
@xmlparent = @file | @xmlelement;
@xmlnamespaceable = @xmlelement | @xmlattribute;
xmllocations(
int xmlElement: @xmllocatable ref,
int location: @location_default ref
);
@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace;
compilations(unique int id: @compilation, string cwd: string ref);
#keyset[id, num]
compilation_args(int id: @compilation ref, int num: int ref, string arg: string ref);
#keyset[id, num, kind]
compilation_time(int id: @compilation ref, int num: int ref, int kind: int ref, float secs: float ref);
diagnostic_for(unique int diagnostic: @diagnostic ref, int compilation: @compilation ref, int file_number: int ref, int file_number_diagnostic_number: int ref);
compilation_finished(unique int id: @compilation ref, float cpu_seconds: float ref, float elapsed_seconds: float ref);
#keyset[id, num]
compilation_compiling_files(int id: @compilation ref, int num: int ref, int file: @file ref);
diagnostics(unique int id: @diagnostic, int severity: int ref, string error_tag: string ref, string error_message: string ref,
string full_error_message: string ref, int location: @location ref);
locations_default(unique int id: @location_default, int file: @file ref, int beginLine: int ref, int beginColumn: int ref,
int endLine: int ref, int endColumn: int ref);
numlines(int element_id: @sourceline ref, int num_lines: int ref, int num_code: int ref, int num_comment: int ref);
files(unique int id: @file, string name: string ref);
folders(unique int id: @folder, string name: string ref);
containerparent(int parent: @container ref, unique int child: @container ref);
has_location(unique int locatable: @locatable ref, int location: @location ref);
#keyset[parent, idx]
comment_groups(unique int id: @comment_group, int parent: @file ref, int idx: int ref);
comments(unique int id: @comment, int kind: int ref, int parent: @comment_group ref, int idx: int ref, string text: string ref);
doc_comments(unique int node: @documentable ref, int comment: @comment_group ref);
#keyset[parent, idx]
exprs(unique int id: @expr, int kind: int ref, int parent: @exprparent ref, int idx: int ref);
literals(unique int expr: @expr ref, string value: string ref, string raw: string ref);
constvalues(unique int expr: @expr ref, string value: string ref, string exact: string ref);
fields(unique int id: @field, int parent: @fieldparent ref, int idx: int ref);
typeparamdecls(unique int id: @typeparamdecl, int parent: @typeparamdeclparent ref, int idx: int ref);
#keyset[parent, idx]
stmts(unique int id: @stmt, int kind: int ref, int parent: @stmtparent ref, int idx: int ref);
#keyset[parent, idx]
decls(unique int id: @decl, int kind: int ref, int parent: @declparent ref, int idx: int ref);
#keyset[parent, idx]
specs(unique int id: @spec, int kind: int ref, int parent: @gendecl ref, int idx: int ref);
scopes(unique int id: @scope, int kind: int ref);
scopenesting(unique int inner: @scope ref, int outer: @scope ref);
scopenodes(unique int node: @scopenode ref, int scope: @localscope ref);
objects(unique int id: @object, int kind: int ref, string name: string ref);
objectscopes(unique int object: @object ref, int scope: @scope ref);
objecttypes(unique int object: @object ref, int tp: @type ref);
methodreceivers(unique int method: @object ref, int receiver: @object ref);
fieldstructs(unique int field: @object ref, int struct: @structtype ref);
methodhosts(int method: @object ref, int host: @definedtype ref);
defs(int ident: @ident ref, int object: @object ref);
uses(int ident: @ident ref, int object: @object ref);
types(unique int id: @type, int kind: int ref);
type_of(unique int expr: @expr ref, int tp: @type ref);
typename(unique int tp: @type ref, string name: string ref);
key_type(unique int map: @maptype ref, int tp: @type ref);
element_type(unique int container: @containertype ref, int tp: @type ref);
base_type(unique int ptr: @pointertype ref, int tp: @type ref);
underlying_type(unique int defined: @definedtype ref, int tp: @type ref);
#keyset[parent, index]
component_types(int parent: @compositetype ref, int index: int ref, string name: string ref, int tp: @type ref);
#keyset[parent, index]
struct_tags(int parent: @structtype ref, int index: int ref, string tag: string ref);
#keyset[interface, index]
interface_private_method_ids(int interface: @interfacetype ref, int index: int ref, string id: string ref);
array_length(unique int tp: @arraytype ref, string len: string ref);
type_objects(unique int tp: @type ref, int object: @object ref);
packages(unique int id: @package, string name: string ref, string path: string ref, int scope: @packagescope ref);
#keyset[parent, idx]
modexprs(unique int id: @modexpr, int kind: int ref, int parent: @modexprparent ref, int idx: int ref);
#keyset[parent, idx]
modtokens(string token: string ref, int parent: @modexpr ref, int idx: int ref);
#keyset[package, idx]
errors(unique int id: @error, int kind: int ref, string msg: string ref, string rawpos: string ref,
string file: string ref, int line: int ref, int col: int ref, int package: @package ref, int idx: int ref);
has_ellipsis(int id: @callorconversionexpr ref);
variadic(int id: @signaturetype ref);
#keyset[parent, idx]
typeparam(unique int tp: @typeparamtype ref, string name: string ref, int bound: @compositetype ref,
int parent: @typeparamparentobject ref, int idx: int ref);
@container = @file | @folder;
@locatable = @xmllocatable | @node | @localscope;
@node = @documentable | @exprparent | @modexprparent | @fieldparent | @stmtparent | @declparent | @typeparamdeclparent
| @scopenode | @comment_group | @comment;
@documentable = @file | @field | @typeparamdecl | @spec | @gendecl | @funcdecl | @modexpr;
@exprparent = @funcdef | @file | @expr | @field | @stmt | @decl | @typeparamdecl | @spec;
@modexprparent = @file | @modexpr;
@fieldparent = @decl | @structtypeexpr | @functypeexpr | @interfacetypeexpr;
@stmtparent = @funcdef | @stmt | @decl;
@declparent = @file | @declstmt;
@typeparamdeclparent = @funcdecl | @typespec;
@funcdef = @funclit | @funcdecl;
@scopenode = @file | @functypeexpr | @blockstmt | @ifstmt | @caseclause | @switchstmt | @commclause | @loopstmt;
@location = @location_default;
@sourceline = @locatable;
case @comment.kind of
0 = @slashslashcomment
| 1 = @slashstarcomment;
case @expr.kind of
0 = @badexpr
| 1 = @ident
| 2 = @ellipsis
| 3 = @intlit
| 4 = @floatlit
| 5 = @imaglit
| 6 = @charlit
| 7 = @stringlit
| 8 = @funclit
| 9 = @compositelit
| 10 = @parenexpr
| 11 = @selectorexpr
| 12 = @indexexpr
| 13 = @genericfunctioninstantiationexpr
| 14 = @generictypeinstantiationexpr
| 15 = @sliceexpr
| 16 = @typeassertexpr
| 17 = @callorconversionexpr
| 18 = @starexpr
| 19 = @keyvalueexpr
| 20 = @arraytypeexpr
| 21 = @structtypeexpr
| 22 = @functypeexpr
| 23 = @interfacetypeexpr
| 24 = @maptypeexpr
| 25 = @typesetliteralexpr
| 26 = @plusexpr
| 27 = @minusexpr
| 28 = @notexpr
| 29 = @complementexpr
| 30 = @derefexpr
| 31 = @addressexpr
| 32 = @arrowexpr
| 33 = @lorexpr
| 34 = @landexpr
| 35 = @eqlexpr
| 36 = @neqexpr
| 37 = @lssexpr
| 38 = @leqexpr
| 39 = @gtrexpr
| 40 = @geqexpr
| 41 = @addexpr
| 42 = @subexpr
| 43 = @orexpr
| 44 = @xorexpr
| 45 = @mulexpr
| 46 = @quoexpr
| 47 = @remexpr
| 48 = @shlexpr
| 49 = @shrexpr
| 50 = @andexpr
| 51 = @andnotexpr
| 52 = @sendchantypeexpr
| 53 = @recvchantypeexpr
| 54 = @sendrcvchantypeexpr;
@basiclit = @intlit | @floatlit | @imaglit | @charlit | @stringlit;
@operatorexpr = @logicalexpr | @arithmeticexpr | @bitwiseexpr | @unaryexpr | @binaryexpr;
@logicalexpr = @logicalunaryexpr | @logicalbinaryexpr;
@arithmeticexpr = @arithmeticunaryexpr | @arithmeticbinaryexpr;
@bitwiseexpr = @bitwiseunaryexpr | @bitwisebinaryexpr;
@unaryexpr = @logicalunaryexpr | @bitwiseunaryexpr | @arithmeticunaryexpr | @derefexpr | @addressexpr | @arrowexpr;
@logicalunaryexpr = @notexpr;
@bitwiseunaryexpr = @complementexpr;
@arithmeticunaryexpr = @plusexpr | @minusexpr;
@binaryexpr = @logicalbinaryexpr | @bitwisebinaryexpr | @arithmeticbinaryexpr | @comparison;
@logicalbinaryexpr = @lorexpr | @landexpr;
@bitwisebinaryexpr = @shiftexpr | @orexpr | @xorexpr | @andexpr | @andnotexpr;
@arithmeticbinaryexpr = @addexpr | @subexpr | @mulexpr | @quoexpr | @remexpr;
@shiftexpr = @shlexpr | @shrexpr;
@comparison = @equalitytest | @relationalcomparison;
@equalitytest = @eqlexpr | @neqexpr;
@relationalcomparison = @lssexpr | @leqexpr | @gtrexpr | @geqexpr;
@chantypeexpr = @sendchantypeexpr | @recvchantypeexpr | @sendrcvchantypeexpr;
case @stmt.kind of
0 = @badstmt
| 1 = @declstmt
| 2 = @emptystmt
| 3 = @labeledstmt
| 4 = @exprstmt
| 5 = @sendstmt
| 6 = @incstmt
| 7 = @decstmt
| 8 = @gostmt
| 9 = @deferstmt
| 10 = @returnstmt
| 11 = @breakstmt
| 12 = @continuestmt
| 13 = @gotostmt
| 14 = @fallthroughstmt
| 15 = @blockstmt
| 16 = @ifstmt
| 17 = @caseclause
| 18 = @exprswitchstmt
| 19 = @typeswitchstmt
| 20 = @commclause
| 21 = @selectstmt
| 22 = @forstmt
| 23 = @rangestmt
| 24 = @assignstmt
| 25 = @definestmt
| 26 = @addassignstmt
| 27 = @subassignstmt
| 28 = @mulassignstmt
| 29 = @quoassignstmt
| 30 = @remassignstmt
| 31 = @andassignstmt
| 32 = @orassignstmt
| 33 = @xorassignstmt
| 34 = @shlassignstmt
| 35 = @shrassignstmt
| 36 = @andnotassignstmt;
@incdecstmt = @incstmt | @decstmt;
@assignment = @simpleassignstmt | @compoundassignstmt;
@simpleassignstmt = @assignstmt | @definestmt;
@compoundassignstmt = @addassignstmt | @subassignstmt | @mulassignstmt | @quoassignstmt | @remassignstmt
| @andassignstmt | @orassignstmt | @xorassignstmt | @shlassignstmt | @shrassignstmt | @andnotassignstmt;
@branchstmt = @breakstmt | @continuestmt | @gotostmt | @fallthroughstmt;
@switchstmt = @exprswitchstmt | @typeswitchstmt;
@loopstmt = @forstmt | @rangestmt;
case @decl.kind of
0 = @baddecl
| 1 = @importdecl
| 2 = @constdecl
| 3 = @typedecl
| 4 = @vardecl
| 5 = @funcdecl;
@gendecl = @importdecl | @constdecl | @typedecl | @vardecl;
case @spec.kind of
0 = @importspec
| 1 = @valuespec
| 2 = @typedefspec
| 3 = @aliasspec;
@typespec = @typedefspec | @aliasspec;
case @object.kind of
0 = @pkgobject
| 1 = @decltypeobject
| 2 = @builtintypeobject
| 3 = @declconstobject
| 4 = @builtinconstobject
| 5 = @declvarobject
| 6 = @declfunctionobject
| 7 = @builtinfunctionobject
| 8 = @labelobject;
@typeparamparentobject = @decltypeobject | @declfunctionobject;
@declobject = @decltypeobject | @declconstobject | @declvarobject | @declfunctionobject;
@builtinobject = @builtintypeobject | @builtinconstobject | @builtinfunctionobject;
@typeobject = @decltypeobject | @builtintypeobject;
@valueobject = @constobject | @varobject | @functionobject;
@constobject = @declconstobject | @builtinconstobject;
@varobject = @declvarobject;
@functionobject = @declfunctionobject | @builtinfunctionobject;
case @scope.kind of
0 = @universescope
| 1 = @packagescope
| 2 = @localscope;
case @type.kind of
0 = @invalidtype
| 1 = @boolexprtype
| 2 = @inttype
| 3 = @int8type
| 4 = @int16type
| 5 = @int32type
| 6 = @int64type
| 7 = @uinttype
| 8 = @uint8type
| 9 = @uint16type
| 10 = @uint32type
| 11 = @uint64type
| 12 = @uintptrtype
| 13 = @float32type
| 14 = @float64type
| 15 = @complex64type
| 16 = @complex128type
| 17 = @stringexprtype
| 18 = @unsafepointertype
| 19 = @boolliteraltype
| 20 = @intliteraltype
| 21 = @runeliteraltype
| 22 = @floatliteraltype
| 23 = @complexliteraltype
| 24 = @stringliteraltype
| 25 = @nilliteraltype
| 26 = @typeparamtype
| 27 = @arraytype
| 28 = @slicetype
| 29 = @structtype
| 30 = @pointertype
| 31 = @interfacetype
| 32 = @tupletype
| 33 = @signaturetype
| 34 = @maptype
| 35 = @sendchantype
| 36 = @recvchantype
| 37 = @sendrcvchantype
| 38 = @definedtype
| 39 = @typesetliteraltype;
@basictype = @booltype | @numerictype | @stringtype | @literaltype | @invalidtype | @unsafepointertype;
@booltype = @boolexprtype | @boolliteraltype;
@numerictype = @integertype | @floattype | @complextype;
@integertype = @signedintegertype | @unsignedintegertype;
@signedintegertype = @inttype | @int8type | @int16type | @int32type | @int64type | @intliteraltype | @runeliteraltype;
@unsignedintegertype = @uinttype | @uint8type | @uint16type | @uint32type | @uint64type | @uintptrtype;
@floattype = @float32type | @float64type | @floatliteraltype;
@complextype = @complex64type | @complex128type | @complexliteraltype;
@stringtype = @stringexprtype | @stringliteraltype;
@literaltype = @boolliteraltype | @intliteraltype | @runeliteraltype | @floatliteraltype | @complexliteraltype
| @stringliteraltype | @nilliteraltype;
@compositetype = @typeparamtype | @containertype | @structtype | @pointertype | @interfacetype | @tupletype
| @signaturetype | @definedtype | @typesetliteraltype;
@containertype = @arraytype | @slicetype | @maptype | @chantype;
@chantype = @sendchantype | @recvchantype | @sendrcvchantype;
case @modexpr.kind of
0 = @modcommentblock
| 1 = @modline
| 2 = @modlineblock
| 3 = @modlparen
| 4 = @modrparen;
case @error.kind of
0 = @unknownerror
| 1 = @listerror
| 2 = @parseerror
| 3 = @typeerror;

View File

@@ -0,0 +1,2 @@
description: Add @rangeelementexpr, grouping the loop variables of a range statement
compatibility: partial

View File

@@ -547,8 +547,9 @@ input.go:
# 133| Type = []int
# 133| 2: [BlockStmt] block statement
# 134| 0: [RangeStmt] range statement
# 134| 0: [Ident, VariableName] x
# 134| Type = int
# 134| 0: [RangeElementExpr] range element
# 134| 0: [Ident, VariableName] x
# 134| Type = int
# 134| 1: [Ident, VariableName] xs
# 134| Type = []int
# 134| 2: [BlockStmt] block statement
@@ -573,13 +574,14 @@ input.go:
# 138| 1: [Ident, VariableName] x
# 138| Type = int
# 141| 1: [RangeStmt] range statement
# 141| 0: [Ident, VariableName] i
# 141| Type = int
# 141| 1: [Ident, VariableName] v
# 141| Type = int
# 141| 2: [Ident, VariableName] xs
# 141| 0: [RangeElementExpr] range element
# 141| 0: [Ident, VariableName] i
# 141| Type = int
# 141| 1: [Ident, VariableName] v
# 141| Type = int
# 141| 1: [Ident, VariableName] xs
# 141| Type = []int
# 141| 3: [BlockStmt] block statement
# 141| 2: [BlockStmt] block statement
# 142| 0: [ExprStmt] expression statement
# 142| 0: [CallExpr] call to Print
# 142| Type = (int, error)
@@ -593,9 +595,10 @@ input.go:
# 142| 2: [Ident, VariableName] v
# 142| Type = int
# 145| 2: [RangeStmt] range statement
# 145| 0: [Ident, VariableName] xs
# 145| 0: [RangeElementExpr] range element
# 145| 1: [Ident, VariableName] xs
# 145| Type = []int
# 145| 1: [BlockStmt] block statement
# 145| 2: [BlockStmt] block statement
other.go:
# 0| [GoFile] other.go
# 1| package: [Ident] main

View File

@@ -527,8 +527,9 @@ input.go:
# 133| Type = []int
# 133| 2: [BlockStmt] block statement
# 134| 0: [RangeStmt] range statement
# 134| 0: [Ident, VariableName] x
# 134| Type = int
# 134| 0: [RangeElementExpr] range element
# 134| 0: [Ident, VariableName] x
# 134| Type = int
# 134| 1: [Ident, VariableName] xs
# 134| Type = []int
# 134| 2: [BlockStmt] block statement
@@ -553,13 +554,14 @@ input.go:
# 138| 1: [Ident, VariableName] x
# 138| Type = int
# 141| 1: [RangeStmt] range statement
# 141| 0: [Ident, VariableName] i
# 141| Type = int
# 141| 1: [Ident, VariableName] v
# 141| Type = int
# 141| 2: [Ident, VariableName] xs
# 141| 0: [RangeElementExpr] range element
# 141| 0: [Ident, VariableName] i
# 141| Type = int
# 141| 1: [Ident, VariableName] v
# 141| Type = int
# 141| 1: [Ident, VariableName] xs
# 141| Type = []int
# 141| 3: [BlockStmt] block statement
# 141| 2: [BlockStmt] block statement
# 142| 0: [ExprStmt] expression statement
# 142| 0: [CallExpr] call to Print
# 142| Type = (int, error)
@@ -573,9 +575,10 @@ input.go:
# 142| 2: [Ident, VariableName] v
# 142| Type = int
# 145| 2: [RangeStmt] range statement
# 145| 0: [Ident, VariableName] xs
# 145| 0: [RangeElementExpr] range element
# 145| 1: [Ident, VariableName] xs
# 145| Type = []int
# 145| 1: [BlockStmt] block statement
# 145| 2: [BlockStmt] block statement
other.go:
# 0| [GoFile] other.go
# 1| package: [Ident] main

View File

@@ -3981,16 +3981,20 @@
| stmts.go:145:23:159:1 | arg:0 block statement | stmts.go:145:23:159:1 | param-init:0 block statement |
| stmts.go:145:23:159:1 | block statement | stmts.go:145:23:159:1 | arg:0 block statement |
| stmts.go:145:23:159:1 | param-init:0 block statement | stmts.go:146:2:151:2 | range statement |
| stmts.go:146:2:151:2 | After range element | stmts.go:146:20:151:2 | block statement |
| stmts.go:146:2:151:2 | After range statement | stmts.go:153:2:155:2 | range statement |
| stmts.go:146:2:151:2 | [LoopHeader] range statement | stmts.go:146:2:151:2 | After range statement |
| stmts.go:146:2:151:2 | [LoopHeader] range statement | stmts.go:146:2:151:2 | next range statement |
| stmts.go:146:2:151:2 | assign:0 range statement | stmts.go:146:20:151:2 | block statement |
| stmts.go:146:2:151:2 | extract:0 range statement | stmts.go:146:2:151:2 | assign:0 range statement |
| stmts.go:146:2:151:2 | next range statement | stmts.go:146:2:151:2 | extract:0 range statement |
| stmts.go:146:2:151:2 | [LoopHeader] range statement | stmts.go:146:2:151:2 | range element |
| stmts.go:146:2:151:2 | assign:0 range element | stmts.go:146:2:151:2 | After range element |
| stmts.go:146:2:151:2 | extract:0 range element | stmts.go:146:2:151:2 | assign:0 range element |
| stmts.go:146:2:151:2 | next range element | stmts.go:146:2:151:2 | extract:0 range element |
| stmts.go:146:2:151:2 | range element | stmts.go:146:2:151:2 | next range element |
| stmts.go:146:2:151:2 | range statement | stmts.go:146:17:146:18 | Before xs |
| stmts.go:146:17:146:18 | After xs | stmts.go:146:2:151:2 | [LoopHeader] range statement |
| stmts.go:146:17:146:18 | After xs [empty] | stmts.go:146:2:151:2 | After range statement |
| stmts.go:146:17:146:18 | After xs [non-empty] | stmts.go:146:2:151:2 | range element |
| stmts.go:146:17:146:18 | Before xs | stmts.go:146:17:146:18 | xs |
| stmts.go:146:17:146:18 | xs | stmts.go:146:17:146:18 | After xs |
| stmts.go:146:17:146:18 | xs | stmts.go:146:17:146:18 | After xs [empty] |
| stmts.go:146:17:146:18 | xs | stmts.go:146:17:146:18 | After xs [non-empty] |
| stmts.go:146:20:151:2 | After block statement | stmts.go:146:2:151:2 | [LoopHeader] range statement |
| stmts.go:146:20:151:2 | block statement | stmts.go:147:3:149:3 | if statement |
| stmts.go:147:3:149:3 | After if statement | stmts.go:150:3:150:14 | expression statement |
@@ -4021,18 +4025,22 @@
| stmts.go:150:13:150:13 | After x | stmts.go:150:3:150:14 | call to Print |
| stmts.go:150:13:150:13 | Before x | stmts.go:150:13:150:13 | x |
| stmts.go:150:13:150:13 | x | stmts.go:150:13:150:13 | After x |
| stmts.go:153:2:155:2 | After range element | stmts.go:153:23:155:2 | block statement |
| stmts.go:153:2:155:2 | After range statement | stmts.go:157:2:158:2 | range statement |
| stmts.go:153:2:155:2 | [LoopHeader] range statement | stmts.go:153:2:155:2 | After range statement |
| stmts.go:153:2:155:2 | [LoopHeader] range statement | stmts.go:153:2:155:2 | next range statement |
| stmts.go:153:2:155:2 | assign:0 range statement | stmts.go:153:2:155:2 | extract:1 range statement |
| stmts.go:153:2:155:2 | assign:1 range statement | stmts.go:153:23:155:2 | block statement |
| stmts.go:153:2:155:2 | extract:0 range statement | stmts.go:153:2:155:2 | assign:0 range statement |
| stmts.go:153:2:155:2 | extract:1 range statement | stmts.go:153:2:155:2 | assign:1 range statement |
| stmts.go:153:2:155:2 | next range statement | stmts.go:153:2:155:2 | extract:0 range statement |
| stmts.go:153:2:155:2 | [LoopHeader] range statement | stmts.go:153:2:155:2 | range element |
| stmts.go:153:2:155:2 | assign:0 range element | stmts.go:153:2:155:2 | extract:1 range element |
| stmts.go:153:2:155:2 | assign:1 range element | stmts.go:153:2:155:2 | After range element |
| stmts.go:153:2:155:2 | extract:0 range element | stmts.go:153:2:155:2 | assign:0 range element |
| stmts.go:153:2:155:2 | extract:1 range element | stmts.go:153:2:155:2 | assign:1 range element |
| stmts.go:153:2:155:2 | next range element | stmts.go:153:2:155:2 | extract:0 range element |
| stmts.go:153:2:155:2 | range element | stmts.go:153:2:155:2 | next range element |
| stmts.go:153:2:155:2 | range statement | stmts.go:153:20:153:21 | Before xs |
| stmts.go:153:20:153:21 | After xs | stmts.go:153:2:155:2 | [LoopHeader] range statement |
| stmts.go:153:20:153:21 | After xs [empty] | stmts.go:153:2:155:2 | After range statement |
| stmts.go:153:20:153:21 | After xs [non-empty] | stmts.go:153:2:155:2 | range element |
| stmts.go:153:20:153:21 | Before xs | stmts.go:153:20:153:21 | xs |
| stmts.go:153:20:153:21 | xs | stmts.go:153:20:153:21 | After xs |
| stmts.go:153:20:153:21 | xs | stmts.go:153:20:153:21 | After xs [empty] |
| stmts.go:153:20:153:21 | xs | stmts.go:153:20:153:21 | After xs [non-empty] |
| stmts.go:153:23:155:2 | After block statement | stmts.go:153:2:155:2 | [LoopHeader] range statement |
| stmts.go:153:23:155:2 | block statement | stmts.go:154:3:154:17 | expression statement |
| stmts.go:154:3:154:11 | After selection of Print | stmts.go:154:13:154:13 | Before i |
@@ -4050,14 +4058,18 @@
| stmts.go:154:16:154:16 | After v | stmts.go:154:3:154:17 | call to Print |
| stmts.go:154:16:154:16 | Before v | stmts.go:154:16:154:16 | v |
| stmts.go:154:16:154:16 | v | stmts.go:154:16:154:16 | After v |
| stmts.go:157:2:158:2 | After range element | stmts.go:157:15:158:2 | block statement |
| stmts.go:157:2:158:2 | After range statement | stmts.go:145:23:159:1 | After block statement |
| stmts.go:157:2:158:2 | [LoopHeader] range statement | stmts.go:157:2:158:2 | After range statement |
| stmts.go:157:2:158:2 | [LoopHeader] range statement | stmts.go:157:2:158:2 | next range statement |
| stmts.go:157:2:158:2 | next range statement | stmts.go:157:15:158:2 | block statement |
| stmts.go:157:2:158:2 | [LoopHeader] range statement | stmts.go:157:2:158:2 | range element |
| stmts.go:157:2:158:2 | next range element | stmts.go:157:2:158:2 | After range element |
| stmts.go:157:2:158:2 | range element | stmts.go:157:2:158:2 | next range element |
| stmts.go:157:2:158:2 | range statement | stmts.go:157:12:157:13 | Before xs |
| stmts.go:157:12:157:13 | After xs | stmts.go:157:2:158:2 | [LoopHeader] range statement |
| stmts.go:157:12:157:13 | After xs [empty] | stmts.go:157:2:158:2 | After range statement |
| stmts.go:157:12:157:13 | After xs [non-empty] | stmts.go:157:2:158:2 | range element |
| stmts.go:157:12:157:13 | Before xs | stmts.go:157:12:157:13 | xs |
| stmts.go:157:12:157:13 | xs | stmts.go:157:12:157:13 | After xs |
| stmts.go:157:12:157:13 | xs | stmts.go:157:12:157:13 | After xs [empty] |
| stmts.go:157:12:157:13 | xs | stmts.go:157:12:157:13 | After xs [non-empty] |
| stmts.go:157:15:158:2 | block statement | stmts.go:157:2:158:2 | [LoopHeader] range statement |
| tst.go:0:0:0:0 | After tst.go | tst.go:0:0:0:0 | Normal Exit |
| tst.go:0:0:0:0 | Entry | tst.go:0:0:0:0 | tst.go |

View File

@@ -1,169 +1,169 @@
| main.go:3:12:3:12 | SSA def(x) | main.go:5:5:5:5 | x |
| main.go:3:12:3:12 | argument corresponding to x | main.go:3:12:3:12 | SSA def(x) |
| main.go:3:19:3:20 | SSA def(fn) | main.go:10:24:10:25 | fn |
| main.go:3:19:3:20 | argument corresponding to fn | main.go:3:19:3:20 | SSA def(fn) |
| main.go:3:39:12:1 | SSA def(fn) | main.go:10:24:10:25 | fn |
| main.go:3:39:12:1 | SSA def(x) | main.go:5:5:5:5 | x |
| main.go:3:39:12:1 | arg:0 block statement | main.go:3:39:12:1 | SSA def(x) |
| main.go:3:39:12:1 | arg:1 block statement | main.go:3:39:12:1 | SSA def(fn) |
| main.go:5:5:5:5 | x | main.go:6:7:6:7 | x |
| main.go:5:5:5:5 | x | main.go:8:8:8:8 | x |
| main.go:6:3:6:3 | SSA def(y) | main.go:10:12:10:12 | y |
| main.go:6:7:6:7 | x | main.go:6:3:6:3 | SSA def(y) |
| main.go:6:3:6:7 | SSA def(y) | main.go:10:12:10:12 | y |
| main.go:6:7:6:7 | x | main.go:6:3:6:7 | SSA def(y) |
| main.go:6:7:6:7 | x | main.go:10:7:10:7 | x |
| main.go:8:3:8:3 | SSA def(y) | main.go:10:12:10:12 | y |
| main.go:8:7:8:8 | -... | main.go:8:3:8:3 | SSA def(y) |
| main.go:8:3:8:8 | SSA def(y) | main.go:10:12:10:12 | y |
| main.go:8:7:8:8 | -... | main.go:8:3:8:8 | SSA def(y) |
| main.go:8:8:8:8 | x | main.go:10:7:10:7 | x |
| main.go:10:2:10:2 | SSA def(z) | main.go:11:14:11:14 | z |
| main.go:10:2:10:27 | SSA def(z) | main.go:11:14:11:14 | z |
| main.go:10:7:10:7 | x | main.go:10:22:10:22 | x |
| main.go:10:7:10:12 | ...<=... | main.go:10:7:10:27 | ...&&... |
| main.go:10:7:10:27 | ...&&... | main.go:10:2:10:2 | SSA def(z) |
| main.go:10:7:10:12 | ...<=... | main.go:10:7:10:27 | After ...&&... |
| main.go:10:7:10:27 | After ...&&... | main.go:10:2:10:27 | SSA def(z) |
| main.go:10:12:10:12 | y | main.go:10:17:10:17 | y |
| main.go:10:17:10:27 | ...>=... | main.go:10:7:10:27 | ...&&... |
| main.go:10:17:10:27 | ...>=... | main.go:10:7:10:27 | After ...&&... |
| main.go:11:14:11:14 | z | main.go:11:9:11:15 | type conversion |
| main.go:15:9:15:9 | 0 | main.go:15:2:15:4 | SSA def(acc) |
| main.go:15:9:15:9 | 0 | main.go:15:2:15:9 | SSA def(acc) |
| main.go:16:9:19:2 | SSA def(acc) | main.go:17:3:17:5 | acc |
| main.go:17:3:17:7 | SSA def(acc) | main.go:18:10:18:12 | acc |
| main.go:17:3:17:7 | rhs of increment statement | main.go:17:3:17:7 | SSA def(acc) |
| main.go:22:12:22:12 | SSA def(b) | main.go:23:5:23:5 | b |
| main.go:22:12:22:12 | argument corresponding to b | main.go:22:12:22:12 | SSA def(b) |
| main.go:22:20:22:20 | SSA def(x) | main.go:24:10:24:10 | x |
| main.go:22:20:22:20 | SSA def(x) | main.go:26:11:26:11 | x |
| main.go:22:20:22:20 | argument corresponding to x | main.go:22:20:22:20 | SSA def(x) |
| main.go:17:3:17:7 | incdec-rhs increment statement | main.go:17:3:17:7 | SSA def(acc) |
| main.go:22:42:31:1 | SSA def(b) | main.go:23:5:23:5 | b |
| main.go:22:42:31:1 | SSA def(x) | main.go:24:10:24:10 | x |
| main.go:22:42:31:1 | SSA def(x) | main.go:26:11:26:11 | x |
| main.go:22:42:31:1 | arg:0 block statement | main.go:22:42:31:1 | SSA def(b) |
| main.go:22:42:31:1 | arg:1 block statement | main.go:22:42:31:1 | SSA def(x) |
| main.go:24:10:24:10 | x | main.go:24:10:24:19 | type assertion |
| main.go:26:2:26:2 | SSA def(n) | main.go:27:11:27:11 | n |
| main.go:26:2:26:17 | ... := ...[0] | main.go:26:2:26:2 | SSA def(n) |
| main.go:26:2:26:17 | ... := ...[1] | main.go:26:5:26:6 | SSA def(ok) |
| main.go:26:5:26:6 | SSA def(ok) | main.go:27:5:27:6 | ok |
| main.go:26:11:26:11 | x | main.go:26:2:26:17 | ... := ...[0] |
| main.go:38:2:38:2 | SSA def(s) | main.go:39:15:39:15 | s |
| main.go:38:7:38:20 | slice literal | main.go:38:2:38:2 | SSA def(s) |
| main.go:38:7:38:20 | slice literal [postupdate] | main.go:38:2:38:2 | SSA def(s) |
| main.go:39:2:39:3 | SSA def(s1) | main.go:40:18:40:19 | s1 |
| main.go:39:8:39:25 | call to append | main.go:39:2:39:3 | SSA def(s1) |
| main.go:26:2:26:17 | SSA def(n) | main.go:27:11:27:11 | n |
| main.go:26:2:26:17 | SSA def(ok) | main.go:27:5:27:6 | ok |
| main.go:26:2:26:17 | extract:0 ... := ... | main.go:26:2:26:17 | SSA def(n) |
| main.go:26:2:26:17 | extract:1 ... := ... | main.go:26:2:26:17 | SSA def(ok) |
| main.go:26:11:26:11 | x | main.go:26:2:26:17 | extract:0 ... := ... |
| main.go:38:2:38:20 | SSA def(s) | main.go:39:15:39:15 | s |
| main.go:38:7:38:20 | slice literal | main.go:38:2:38:20 | SSA def(s) |
| main.go:38:7:38:20 | slice literal [postupdate] | main.go:38:2:38:20 | SSA def(s) |
| main.go:39:2:39:25 | SSA def(s1) | main.go:40:18:40:19 | s1 |
| main.go:39:8:39:25 | call to append | main.go:39:2:39:25 | SSA def(s1) |
| main.go:39:15:39:15 | s | main.go:40:15:40:15 | s |
| main.go:39:15:39:15 | s [postupdate] | main.go:40:15:40:15 | s |
| main.go:40:2:40:3 | SSA def(s2) | main.go:43:9:43:10 | s2 |
| main.go:40:8:40:23 | call to append | main.go:40:2:40:3 | SSA def(s2) |
| main.go:40:2:40:23 | SSA def(s2) | main.go:43:9:43:10 | s2 |
| main.go:40:8:40:23 | call to append | main.go:40:2:40:23 | SSA def(s2) |
| main.go:40:15:40:15 | s | main.go:42:7:42:7 | s |
| main.go:40:15:40:15 | s [postupdate] | main.go:42:7:42:7 | s |
| main.go:41:2:41:3 | SSA def(s4) | main.go:42:10:42:11 | s4 |
| main.go:41:8:41:21 | call to make | main.go:41:2:41:3 | SSA def(s4) |
| main.go:46:13:46:14 | SSA def(xs) | main.go:47:20:47:21 | xs |
| main.go:46:13:46:14 | argument corresponding to xs | main.go:46:13:46:14 | SSA def(xs) |
| main.go:46:24:46:27 | SSA def(keys) | main.go:46:24:46:27 | implicit read of keys |
| main.go:46:24:46:27 | SSA def(keys) | main.go:49:3:49:6 | keys |
| main.go:46:24:46:27 | zero value for keys | main.go:46:24:46:27 | SSA def(keys) |
| main.go:46:34:46:37 | SSA def(vals) | main.go:46:34:46:37 | implicit read of vals |
| main.go:46:34:46:37 | SSA def(vals) | main.go:48:3:48:6 | vals |
| main.go:46:34:46:37 | zero value for vals | main.go:46:34:46:37 | SSA def(vals) |
| main.go:47:2:50:2 | range statement[0] | main.go:47:6:47:6 | SSA def(k) |
| main.go:47:2:50:2 | range statement[1] | main.go:47:9:47:9 | SSA def(v) |
| main.go:47:6:47:6 | SSA def(k) | main.go:49:11:49:11 | k |
| main.go:47:9:47:9 | SSA def(v) | main.go:48:11:48:11 | v |
| main.go:48:3:48:6 | SSA def(vals) | main.go:46:34:46:37 | implicit read of vals |
| main.go:48:3:48:6 | SSA def(vals) | main.go:48:3:48:6 | vals |
| main.go:48:3:48:11 | ... += ... | main.go:48:3:48:6 | SSA def(vals) |
| main.go:49:3:49:6 | SSA def(keys) | main.go:46:24:46:27 | implicit read of keys |
| main.go:49:3:49:6 | SSA def(keys) | main.go:49:3:49:6 | keys |
| main.go:49:3:49:11 | ... += ... | main.go:49:3:49:6 | SSA def(keys) |
| main.go:55:6:55:7 | SSA def(ch) | main.go:56:2:56:3 | ch |
| main.go:55:6:55:7 | zero value for ch | main.go:55:6:55:7 | SSA def(ch) |
| main.go:41:2:41:21 | SSA def(s4) | main.go:42:10:42:11 | s4 |
| main.go:41:8:41:21 | call to make | main.go:41:2:41:21 | SSA def(s4) |
| main.go:46:44:52:1 | SSA def(keys) | main.go:46:44:52:1 | result-read:0 block statement |
| main.go:46:44:52:1 | SSA def(keys) | main.go:49:3:49:6 | keys |
| main.go:46:44:52:1 | SSA def(vals) | main.go:46:44:52:1 | result-read:1 block statement |
| main.go:46:44:52:1 | SSA def(vals) | main.go:48:3:48:6 | vals |
| main.go:46:44:52:1 | SSA def(xs) | main.go:47:20:47:21 | xs |
| main.go:46:44:52:1 | arg:0 block statement | main.go:46:44:52:1 | SSA def(xs) |
| main.go:46:44:52:1 | result-zero-init:0 block statement | main.go:46:44:52:1 | SSA def(keys) |
| main.go:46:44:52:1 | result-zero-init:1 block statement | main.go:46:44:52:1 | SSA def(vals) |
| main.go:47:2:50:2 | SSA def(k) | main.go:49:11:49:11 | k |
| main.go:47:2:50:2 | SSA def(v) | main.go:48:11:48:11 | v |
| main.go:47:2:50:2 | extract:0 range element | main.go:47:2:50:2 | SSA def(k) |
| main.go:47:2:50:2 | extract:1 range element | main.go:47:2:50:2 | SSA def(v) |
| main.go:48:3:48:11 | SSA def(vals) | main.go:46:44:52:1 | result-read:1 block statement |
| main.go:48:3:48:11 | SSA def(vals) | main.go:48:3:48:6 | vals |
| main.go:48:3:48:11 | compound-rhs ... += ... | main.go:48:3:48:11 | SSA def(vals) |
| main.go:49:3:49:11 | SSA def(keys) | main.go:46:44:52:1 | result-read:0 block statement |
| main.go:49:3:49:11 | SSA def(keys) | main.go:49:3:49:6 | keys |
| main.go:49:3:49:11 | compound-rhs ... += ... | main.go:49:3:49:11 | SSA def(keys) |
| main.go:55:6:55:17 | SSA def(ch) | main.go:56:2:56:3 | ch |
| main.go:55:6:55:17 | zero-init:0 value declaration specifier | main.go:55:6:55:17 | SSA def(ch) |
| main.go:56:2:56:3 | ch | main.go:57:4:57:5 | ch |
| main.go:56:2:56:3 | ch [postupdate] | main.go:57:4:57:5 | ch |
| main.go:61:2:61:2 | SSA def(x) | main.go:64:11:64:11 | x |
| main.go:61:7:61:7 | 1 | main.go:61:2:61:2 | SSA def(x) |
| main.go:62:2:62:2 | SSA def(y) | main.go:64:14:64:14 | y |
| main.go:62:7:62:7 | 2 | main.go:62:2:62:2 | SSA def(y) |
| main.go:63:2:63:2 | SSA def(z) | main.go:64:17:64:17 | z |
| main.go:63:7:63:7 | 3 | main.go:63:2:63:2 | SSA def(z) |
| main.go:64:2:64:2 | SSA def(a) | main.go:66:9:66:9 | a |
| main.go:64:7:64:18 | call to min | main.go:64:2:64:2 | SSA def(a) |
| main.go:61:2:61:7 | SSA def(x) | main.go:64:11:64:11 | x |
| main.go:61:7:61:7 | 1 | main.go:61:2:61:7 | SSA def(x) |
| main.go:62:2:62:7 | SSA def(y) | main.go:64:14:64:14 | y |
| main.go:62:7:62:7 | 2 | main.go:62:2:62:7 | SSA def(y) |
| main.go:63:2:63:7 | SSA def(z) | main.go:64:17:64:17 | z |
| main.go:63:7:63:7 | 3 | main.go:63:2:63:7 | SSA def(z) |
| main.go:64:2:64:18 | SSA def(a) | main.go:66:9:66:9 | a |
| main.go:64:7:64:18 | call to min | main.go:64:2:64:18 | SSA def(a) |
| main.go:64:11:64:11 | x | main.go:64:7:64:18 | call to min |
| main.go:64:11:64:11 | x | main.go:65:11:65:11 | x |
| main.go:64:14:64:14 | y | main.go:64:7:64:18 | call to min |
| main.go:64:14:64:14 | y | main.go:65:14:65:14 | y |
| main.go:64:17:64:17 | z | main.go:64:7:64:18 | call to min |
| main.go:64:17:64:17 | z | main.go:65:17:65:17 | z |
| main.go:65:2:65:2 | SSA def(b) | main.go:66:12:66:12 | b |
| main.go:65:7:65:18 | call to max | main.go:65:2:65:2 | SSA def(b) |
| main.go:65:2:65:18 | SSA def(b) | main.go:66:12:66:12 | b |
| main.go:65:7:65:18 | call to max | main.go:65:2:65:18 | SSA def(b) |
| main.go:65:11:65:11 | x | main.go:65:7:65:18 | call to max |
| main.go:65:14:65:14 | y | main.go:65:7:65:18 | call to max |
| main.go:65:17:65:17 | z | main.go:65:7:65:18 | call to max |
| strings.go:8:12:8:12 | SSA def(s) | strings.go:9:24:9:24 | s |
| strings.go:8:12:8:12 | argument corresponding to s | strings.go:8:12:8:12 | SSA def(s) |
| strings.go:9:2:9:3 | SSA def(s2) | strings.go:11:20:11:21 | s2 |
| strings.go:9:8:9:38 | call to Replace | strings.go:9:2:9:3 | SSA def(s2) |
| strings.go:8:29:12:1 | SSA def(s) | strings.go:9:24:9:24 | s |
| strings.go:8:29:12:1 | arg:0 block statement | strings.go:8:29:12:1 | SSA def(s) |
| strings.go:9:2:9:38 | SSA def(s2) | strings.go:11:20:11:21 | s2 |
| strings.go:9:8:9:38 | call to Replace | strings.go:9:2:9:38 | SSA def(s2) |
| strings.go:9:24:9:24 | s | strings.go:10:27:10:27 | s |
| strings.go:10:2:10:3 | SSA def(s3) | strings.go:11:24:11:25 | s3 |
| strings.go:10:8:10:42 | call to ReplaceAll | strings.go:10:2:10:3 | SSA def(s3) |
| strings.go:10:2:10:42 | SSA def(s3) | strings.go:11:24:11:25 | s3 |
| strings.go:10:8:10:42 | call to ReplaceAll | strings.go:10:2:10:42 | SSA def(s3) |
| strings.go:11:20:11:21 | s2 | strings.go:11:48:11:49 | s2 |
| strings.go:11:24:11:25 | s3 | strings.go:11:67:11:68 | s3 |
| url.go:8:12:8:12 | SSA def(b) | url.go:11:5:11:5 | b |
| url.go:8:12:8:12 | argument corresponding to b | url.go:8:12:8:12 | SSA def(b) |
| url.go:8:20:8:20 | SSA def(s) | url.go:12:46:12:46 | s |
| url.go:8:20:8:20 | SSA def(s) | url.go:14:48:14:48 | s |
| url.go:8:20:8:20 | argument corresponding to s | url.go:8:20:8:20 | SSA def(s) |
| url.go:12:3:12:5 | SSA def(res) | url.go:19:9:19:11 | res |
| url.go:12:3:12:48 | ... = ...[0] | url.go:12:3:12:5 | SSA def(res) |
| url.go:12:3:12:48 | ... = ...[1] | url.go:12:8:12:10 | SSA def(err) |
| url.go:12:8:12:10 | SSA def(err) | url.go:16:5:16:7 | err |
| url.go:14:3:14:5 | SSA def(res) | url.go:19:9:19:11 | res |
| url.go:14:3:14:50 | ... = ...[0] | url.go:14:3:14:5 | SSA def(res) |
| url.go:14:3:14:50 | ... = ...[1] | url.go:14:8:14:10 | SSA def(err) |
| url.go:14:8:14:10 | SSA def(err) | url.go:16:5:16:7 | err |
| url.go:22:12:22:12 | SSA def(i) | url.go:24:5:24:5 | i |
| url.go:22:12:22:12 | argument corresponding to i | url.go:22:12:22:12 | SSA def(i) |
| url.go:22:19:22:19 | SSA def(s) | url.go:23:20:23:20 | s |
| url.go:22:19:22:19 | argument corresponding to s | url.go:22:19:22:19 | SSA def(s) |
| url.go:23:2:23:2 | SSA def(u) | url.go:25:10:25:10 | u |
| url.go:23:2:23:21 | ... := ...[0] | url.go:23:2:23:2 | SSA def(u) |
| url.go:8:37:20:1 | SSA def(b) | url.go:11:5:11:5 | b |
| url.go:8:37:20:1 | SSA def(s) | url.go:12:46:12:46 | s |
| url.go:8:37:20:1 | SSA def(s) | url.go:14:48:14:48 | s |
| url.go:8:37:20:1 | arg:0 block statement | url.go:8:37:20:1 | SSA def(b) |
| url.go:8:37:20:1 | arg:1 block statement | url.go:8:37:20:1 | SSA def(s) |
| url.go:12:3:12:48 | SSA def(err) | url.go:16:5:16:7 | err |
| url.go:12:3:12:48 | SSA def(res) | url.go:19:9:19:11 | res |
| url.go:12:3:12:48 | extract:0 ... = ... | url.go:12:3:12:48 | SSA def(res) |
| url.go:12:3:12:48 | extract:1 ... = ... | url.go:12:3:12:48 | SSA def(err) |
| url.go:14:3:14:50 | SSA def(err) | url.go:16:5:16:7 | err |
| url.go:14:3:14:50 | SSA def(res) | url.go:19:9:19:11 | res |
| url.go:14:3:14:50 | extract:0 ... = ... | url.go:14:3:14:50 | SSA def(res) |
| url.go:14:3:14:50 | extract:1 ... = ... | url.go:14:3:14:50 | SSA def(err) |
| url.go:22:38:38:1 | SSA def(i) | url.go:24:5:24:5 | i |
| url.go:22:38:38:1 | SSA def(s) | url.go:23:20:23:20 | s |
| url.go:22:38:38:1 | arg:0 block statement | url.go:22:38:38:1 | SSA def(i) |
| url.go:22:38:38:1 | arg:1 block statement | url.go:22:38:38:1 | SSA def(s) |
| url.go:23:2:23:21 | SSA def(u) | url.go:25:10:25:10 | u |
| url.go:23:2:23:21 | extract:0 ... := ... | url.go:23:2:23:21 | SSA def(u) |
| url.go:23:20:23:20 | s | url.go:27:29:27:29 | s |
| url.go:27:2:27:2 | SSA def(u) | url.go:28:14:28:14 | u |
| url.go:27:2:27:30 | ... = ...[0] | url.go:27:2:27:2 | SSA def(u) |
| url.go:27:2:27:30 | SSA def(u) | url.go:28:14:28:14 | u |
| url.go:27:2:27:30 | extract:0 ... = ... | url.go:27:2:27:30 | SSA def(u) |
| url.go:28:14:28:14 | u | url.go:29:14:29:14 | u |
| url.go:28:14:28:14 | u [postupdate] | url.go:29:14:29:14 | u |
| url.go:29:14:29:14 | u | url.go:30:11:30:11 | u |
| url.go:29:14:29:14 | u [postupdate] | url.go:30:11:30:11 | u |
| url.go:30:2:30:3 | SSA def(bs) | url.go:31:14:31:15 | bs |
| url.go:30:2:30:27 | ... := ...[0] | url.go:30:2:30:3 | SSA def(bs) |
| url.go:30:2:30:27 | SSA def(bs) | url.go:31:14:31:15 | bs |
| url.go:30:2:30:27 | extract:0 ... := ... | url.go:30:2:30:27 | SSA def(bs) |
| url.go:30:11:30:11 | u | url.go:32:9:32:9 | u |
| url.go:30:11:30:11 | u [postupdate] | url.go:32:9:32:9 | u |
| url.go:32:2:32:2 | SSA def(u) | url.go:33:14:33:14 | u |
| url.go:32:2:32:23 | ... = ...[0] | url.go:32:2:32:2 | SSA def(u) |
| url.go:32:2:32:23 | SSA def(u) | url.go:33:14:33:14 | u |
| url.go:32:2:32:23 | extract:0 ... = ... | url.go:32:2:32:23 | SSA def(u) |
| url.go:33:14:33:14 | u | url.go:34:14:34:14 | u |
| url.go:33:14:33:14 | u [postupdate] | url.go:34:14:34:14 | u |
| url.go:34:14:34:14 | u | url.go:35:14:35:14 | u |
| url.go:34:14:34:14 | u [postupdate] | url.go:35:14:35:14 | u |
| url.go:35:14:35:14 | u | url.go:36:6:36:6 | u |
| url.go:35:14:35:14 | u [postupdate] | url.go:36:6:36:6 | u |
| url.go:36:2:36:2 | SSA def(u) | url.go:37:9:37:9 | u |
| url.go:36:2:36:26 | SSA def(u) | url.go:37:9:37:9 | u |
| url.go:36:6:36:6 | u | url.go:36:25:36:25 | u |
| url.go:36:6:36:6 | u [postupdate] | url.go:36:25:36:25 | u |
| url.go:36:6:36:26 | call to ResolveReference | url.go:36:2:36:2 | SSA def(u) |
| url.go:42:2:42:3 | SSA def(ui) | url.go:43:11:43:12 | ui |
| url.go:42:7:42:38 | call to UserPassword | url.go:42:2:42:3 | SSA def(ui) |
| url.go:43:2:43:3 | SSA def(pw) | url.go:44:14:44:15 | pw |
| url.go:43:2:43:23 | ... := ...[0] | url.go:43:2:43:3 | SSA def(pw) |
| url.go:36:6:36:26 | call to ResolveReference | url.go:36:2:36:26 | SSA def(u) |
| url.go:42:2:42:38 | SSA def(ui) | url.go:43:11:43:12 | ui |
| url.go:42:7:42:38 | call to UserPassword | url.go:42:2:42:38 | SSA def(ui) |
| url.go:43:2:43:23 | SSA def(pw) | url.go:44:14:44:15 | pw |
| url.go:43:2:43:23 | extract:0 ... := ... | url.go:43:2:43:23 | SSA def(pw) |
| url.go:43:11:43:12 | ui | url.go:45:14:45:15 | ui |
| url.go:43:11:43:12 | ui [postupdate] | url.go:45:14:45:15 | ui |
| url.go:45:14:45:15 | ui | url.go:46:9:46:10 | ui |
| url.go:45:14:45:15 | ui [postupdate] | url.go:46:9:46:10 | ui |
| url.go:49:12:49:12 | SSA def(q) | url.go:50:25:50:25 | q |
| url.go:49:12:49:12 | argument corresponding to q | url.go:49:12:49:12 | SSA def(q) |
| url.go:50:2:50:2 | SSA def(v) | url.go:51:14:51:14 | v |
| url.go:50:2:50:26 | ... := ...[0] | url.go:50:2:50:2 | SSA def(v) |
| url.go:49:33:54:1 | SSA def(q) | url.go:50:25:50:25 | q |
| url.go:49:33:54:1 | arg:0 block statement | url.go:49:33:54:1 | SSA def(q) |
| url.go:50:2:50:26 | SSA def(v) | url.go:51:14:51:14 | v |
| url.go:50:2:50:26 | extract:0 ... := ... | url.go:50:2:50:26 | SSA def(v) |
| url.go:51:14:51:14 | v | url.go:52:14:52:14 | v |
| url.go:51:14:51:14 | v [postupdate] | url.go:52:14:52:14 | v |
| url.go:52:14:52:14 | v | url.go:53:9:53:9 | v |
| url.go:52:14:52:14 | v [postupdate] | url.go:53:9:53:9 | v |
| url.go:56:12:56:12 | SSA def(q) | url.go:57:29:57:29 | q |
| url.go:56:12:56:12 | argument corresponding to q | url.go:56:12:56:12 | SSA def(q) |
| url.go:57:2:57:8 | SSA def(joined1) | url.go:58:38:58:44 | joined1 |
| url.go:57:2:57:39 | ... := ...[0] | url.go:57:2:57:8 | SSA def(joined1) |
| url.go:58:2:58:8 | SSA def(joined2) | url.go:59:24:59:30 | joined2 |
| url.go:58:2:58:45 | ... := ...[0] | url.go:58:2:58:8 | SSA def(joined2) |
| url.go:59:2:59:6 | SSA def(asUrl) | url.go:60:15:60:19 | asUrl |
| url.go:59:2:59:31 | ... := ...[0] | url.go:59:2:59:6 | SSA def(asUrl) |
| url.go:60:2:60:10 | SSA def(joinedUrl) | url.go:61:9:61:17 | joinedUrl |
| url.go:60:15:60:37 | call to JoinPath | url.go:60:2:60:10 | SSA def(joinedUrl) |
| url.go:64:13:64:13 | SSA def(q) | url.go:66:27:66:27 | q |
| url.go:64:13:64:13 | argument corresponding to q | url.go:64:13:64:13 | SSA def(q) |
| url.go:65:2:65:9 | SSA def(cleanUrl) | url.go:66:9:66:16 | cleanUrl |
| url.go:65:2:65:48 | ... := ...[0] | url.go:65:2:65:9 | SSA def(cleanUrl) |
| url.go:56:31:62:1 | SSA def(q) | url.go:57:29:57:29 | q |
| url.go:56:31:62:1 | arg:0 block statement | url.go:56:31:62:1 | SSA def(q) |
| url.go:57:2:57:39 | SSA def(joined1) | url.go:58:38:58:44 | joined1 |
| url.go:57:2:57:39 | extract:0 ... := ... | url.go:57:2:57:39 | SSA def(joined1) |
| url.go:58:2:58:45 | SSA def(joined2) | url.go:59:24:59:30 | joined2 |
| url.go:58:2:58:45 | extract:0 ... := ... | url.go:58:2:58:45 | SSA def(joined2) |
| url.go:59:2:59:31 | SSA def(asUrl) | url.go:60:15:60:19 | asUrl |
| url.go:59:2:59:31 | extract:0 ... := ... | url.go:59:2:59:31 | SSA def(asUrl) |
| url.go:60:2:60:37 | SSA def(joinedUrl) | url.go:61:9:61:17 | joinedUrl |
| url.go:60:15:60:37 | call to JoinPath | url.go:60:2:60:37 | SSA def(joinedUrl) |
| url.go:64:32:67:1 | SSA def(q) | url.go:66:27:66:27 | q |
| url.go:64:32:67:1 | arg:0 block statement | url.go:64:32:67:1 | SSA def(q) |
| url.go:65:2:65:48 | SSA def(cleanUrl) | url.go:66:9:66:16 | cleanUrl |
| url.go:65:2:65:48 | extract:0 ... := ... | url.go:65:2:65:48 | SSA def(cleanUrl) |

View File

@@ -1,5 +1,5 @@
| main.go:26:11:26:17 | type assertion | main.go:26:2:26:17 | ... := ...[0] |
| main.go:26:11:26:17 | type assertion | main.go:26:2:26:17 | ... := ...[1] |
| main.go:26:11:26:17 | type assertion | main.go:26:2:26:17 | extract:0 ... := ... |
| main.go:26:11:26:17 | type assertion | main.go:26:2:26:17 | extract:1 ... := ... |
| main.go:38:13:38:13 | 1 | main.go:38:7:38:20 | slice literal |
| main.go:38:16:38:16 | 2 | main.go:38:7:38:20 | slice literal |
| main.go:38:19:38:19 | 3 | main.go:38:7:38:20 | slice literal |
@@ -8,9 +8,9 @@
| main.go:40:15:40:15 | s | main.go:40:8:40:23 | call to append |
| main.go:40:18:40:19 | s1 | main.go:40:8:40:23 | call to append |
| main.go:42:10:42:11 | s4 | main.go:42:7:42:7 | s [postupdate] |
| main.go:47:20:47:21 | next key-value pair in range | main.go:47:2:50:2 | range statement[0] |
| main.go:47:20:47:21 | next key-value pair in range | main.go:47:2:50:2 | range statement[1] |
| main.go:47:20:47:21 | xs | main.go:47:2:50:2 | range statement[1] |
| main.go:47:2:50:2 | next range element | main.go:47:2:50:2 | extract:0 range element |
| main.go:47:2:50:2 | next range element | main.go:47:2:50:2 | extract:1 range element |
| main.go:47:20:47:21 | xs | main.go:47:2:50:2 | extract:1 range element |
| strings.go:9:24:9:24 | s | strings.go:9:8:9:38 | call to Replace |
| strings.go:9:32:9:34 | "_" | strings.go:9:8:9:38 | call to Replace |
| strings.go:10:27:10:27 | s | strings.go:10:8:10:42 | call to ReplaceAll |
@@ -24,29 +24,29 @@
| strings.go:11:48:11:49 | s2 | strings.go:11:30:11:50 | call to Sprintf |
| strings.go:11:54:11:69 | call to Sprintln | strings.go:11:9:11:69 | ...+... |
| strings.go:11:67:11:68 | s3 | strings.go:11:54:11:69 | call to Sprintln |
| url.go:12:14:12:48 | call to PathUnescape | url.go:12:3:12:48 | ... = ...[0] |
| url.go:12:14:12:48 | call to PathUnescape | url.go:12:3:12:48 | ... = ...[1] |
| url.go:12:31:12:47 | call to PathEscape | url.go:12:3:12:48 | ... = ...[0] |
| url.go:12:14:12:48 | call to PathUnescape | url.go:12:3:12:48 | extract:0 ... = ... |
| url.go:12:14:12:48 | call to PathUnescape | url.go:12:3:12:48 | extract:1 ... = ... |
| url.go:12:31:12:47 | call to PathEscape | url.go:12:3:12:48 | extract:0 ... = ... |
| url.go:12:46:12:46 | s | url.go:12:31:12:47 | call to PathEscape |
| url.go:14:14:14:50 | call to QueryUnescape | url.go:14:3:14:50 | ... = ...[0] |
| url.go:14:14:14:50 | call to QueryUnescape | url.go:14:3:14:50 | ... = ...[1] |
| url.go:14:32:14:49 | call to QueryEscape | url.go:14:3:14:50 | ... = ...[0] |
| url.go:14:14:14:50 | call to QueryUnescape | url.go:14:3:14:50 | extract:0 ... = ... |
| url.go:14:14:14:50 | call to QueryUnescape | url.go:14:3:14:50 | extract:1 ... = ... |
| url.go:14:32:14:49 | call to QueryEscape | url.go:14:3:14:50 | extract:0 ... = ... |
| url.go:14:48:14:48 | s | url.go:14:32:14:49 | call to QueryEscape |
| url.go:23:10:23:21 | call to Parse | url.go:23:2:23:21 | ... := ...[0] |
| url.go:23:10:23:21 | call to Parse | url.go:23:2:23:21 | ... := ...[1] |
| url.go:23:20:23:20 | s | url.go:23:2:23:21 | ... := ...[0] |
| url.go:27:9:27:30 | call to ParseRequestURI | url.go:27:2:27:30 | ... = ...[0] |
| url.go:27:9:27:30 | call to ParseRequestURI | url.go:27:2:27:30 | ... = ...[1] |
| url.go:27:29:27:29 | s | url.go:27:2:27:30 | ... = ...[0] |
| url.go:23:10:23:21 | call to Parse | url.go:23:2:23:21 | extract:0 ... := ... |
| url.go:23:10:23:21 | call to Parse | url.go:23:2:23:21 | extract:1 ... := ... |
| url.go:23:20:23:20 | s | url.go:23:2:23:21 | extract:0 ... := ... |
| url.go:27:9:27:30 | call to ParseRequestURI | url.go:27:2:27:30 | extract:0 ... = ... |
| url.go:27:9:27:30 | call to ParseRequestURI | url.go:27:2:27:30 | extract:1 ... = ... |
| url.go:27:29:27:29 | s | url.go:27:2:27:30 | extract:0 ... = ... |
| url.go:28:14:28:14 | u | url.go:28:14:28:28 | call to EscapedPath |
| url.go:29:14:29:14 | u | url.go:29:14:29:25 | call to Hostname |
| url.go:30:11:30:11 | u | url.go:30:2:30:27 | ... := ...[0] |
| url.go:30:11:30:27 | call to MarshalBinary | url.go:30:2:30:27 | ... := ...[0] |
| url.go:30:11:30:27 | call to MarshalBinary | url.go:30:2:30:27 | ... := ...[1] |
| url.go:32:9:32:9 | u | url.go:32:2:32:23 | ... = ...[0] |
| url.go:32:9:32:23 | call to Parse | url.go:32:2:32:23 | ... = ...[0] |
| url.go:32:9:32:23 | call to Parse | url.go:32:2:32:23 | ... = ...[1] |
| url.go:32:17:32:22 | "/foo" | url.go:32:2:32:23 | ... = ...[0] |
| url.go:30:11:30:11 | u | url.go:30:2:30:27 | extract:0 ... := ... |
| url.go:30:11:30:27 | call to MarshalBinary | url.go:30:2:30:27 | extract:0 ... := ... |
| url.go:30:11:30:27 | call to MarshalBinary | url.go:30:2:30:27 | extract:1 ... := ... |
| url.go:32:9:32:9 | u | url.go:32:2:32:23 | extract:0 ... = ... |
| url.go:32:9:32:23 | call to Parse | url.go:32:2:32:23 | extract:0 ... = ... |
| url.go:32:9:32:23 | call to Parse | url.go:32:2:32:23 | extract:1 ... = ... |
| url.go:32:17:32:22 | "/foo" | url.go:32:2:32:23 | extract:0 ... = ... |
| url.go:33:14:33:14 | u | url.go:33:14:33:21 | call to Port |
| url.go:34:14:34:14 | u | url.go:34:14:34:22 | call to Query |
| url.go:35:14:35:14 | u | url.go:35:14:35:27 | call to RequestURI |
@@ -55,30 +55,30 @@
| url.go:41:17:41:20 | "me" | url.go:41:8:41:21 | call to User |
| url.go:42:24:42:27 | "me" | url.go:42:7:42:38 | call to UserPassword |
| url.go:42:30:42:37 | "secret" | url.go:42:7:42:38 | call to UserPassword |
| url.go:43:11:43:12 | ui | url.go:43:2:43:23 | ... := ...[0] |
| url.go:43:11:43:23 | call to Password | url.go:43:2:43:23 | ... := ...[0] |
| url.go:43:11:43:23 | call to Password | url.go:43:2:43:23 | ... := ...[1] |
| url.go:43:11:43:12 | ui | url.go:43:2:43:23 | extract:0 ... := ... |
| url.go:43:11:43:23 | call to Password | url.go:43:2:43:23 | extract:0 ... := ... |
| url.go:43:11:43:23 | call to Password | url.go:43:2:43:23 | extract:1 ... := ... |
| url.go:45:14:45:15 | ui | url.go:45:14:45:26 | call to Username |
| url.go:50:10:50:26 | call to ParseQuery | url.go:50:2:50:26 | ... := ...[0] |
| url.go:50:10:50:26 | call to ParseQuery | url.go:50:2:50:26 | ... := ...[1] |
| url.go:50:25:50:25 | q | url.go:50:2:50:26 | ... := ...[0] |
| url.go:50:10:50:26 | call to ParseQuery | url.go:50:2:50:26 | extract:0 ... := ... |
| url.go:50:10:50:26 | call to ParseQuery | url.go:50:2:50:26 | extract:1 ... := ... |
| url.go:50:25:50:25 | q | url.go:50:2:50:26 | extract:0 ... := ... |
| url.go:51:14:51:14 | v | url.go:51:14:51:23 | call to Encode |
| url.go:52:14:52:14 | v | url.go:52:14:52:26 | call to Get |
| url.go:57:16:57:39 | call to JoinPath | url.go:57:2:57:39 | ... := ...[0] |
| url.go:57:16:57:39 | call to JoinPath | url.go:57:2:57:39 | ... := ...[1] |
| url.go:57:29:57:29 | q | url.go:57:2:57:39 | ... := ...[0] |
| url.go:57:32:57:38 | "clean" | url.go:57:2:57:39 | ... := ...[0] |
| url.go:58:16:58:45 | call to JoinPath | url.go:58:2:58:45 | ... := ...[0] |
| url.go:58:16:58:45 | call to JoinPath | url.go:58:2:58:45 | ... := ...[1] |
| url.go:58:29:58:35 | "clean" | url.go:58:2:58:45 | ... := ...[0] |
| url.go:58:38:58:44 | joined1 | url.go:58:2:58:45 | ... := ...[0] |
| url.go:59:14:59:31 | call to Parse | url.go:59:2:59:31 | ... := ...[0] |
| url.go:59:14:59:31 | call to Parse | url.go:59:2:59:31 | ... := ...[1] |
| url.go:59:24:59:30 | joined2 | url.go:59:2:59:31 | ... := ...[0] |
| url.go:57:16:57:39 | call to JoinPath | url.go:57:2:57:39 | extract:0 ... := ... |
| url.go:57:16:57:39 | call to JoinPath | url.go:57:2:57:39 | extract:1 ... := ... |
| url.go:57:29:57:29 | q | url.go:57:2:57:39 | extract:0 ... := ... |
| url.go:57:32:57:38 | "clean" | url.go:57:2:57:39 | extract:0 ... := ... |
| url.go:58:16:58:45 | call to JoinPath | url.go:58:2:58:45 | extract:0 ... := ... |
| url.go:58:16:58:45 | call to JoinPath | url.go:58:2:58:45 | extract:1 ... := ... |
| url.go:58:29:58:35 | "clean" | url.go:58:2:58:45 | extract:0 ... := ... |
| url.go:58:38:58:44 | joined1 | url.go:58:2:58:45 | extract:0 ... := ... |
| url.go:59:14:59:31 | call to Parse | url.go:59:2:59:31 | extract:0 ... := ... |
| url.go:59:14:59:31 | call to Parse | url.go:59:2:59:31 | extract:1 ... := ... |
| url.go:59:24:59:30 | joined2 | url.go:59:2:59:31 | extract:0 ... := ... |
| url.go:60:15:60:19 | asUrl | url.go:60:15:60:37 | call to JoinPath |
| url.go:60:30:60:36 | "clean" | url.go:60:15:60:37 | call to JoinPath |
| url.go:65:17:65:48 | call to Parse | url.go:65:2:65:48 | ... := ...[0] |
| url.go:65:17:65:48 | call to Parse | url.go:65:2:65:48 | ... := ...[1] |
| url.go:65:27:65:47 | "http://harmless.org" | url.go:65:2:65:48 | ... := ...[0] |
| url.go:65:17:65:48 | call to Parse | url.go:65:2:65:48 | extract:0 ... := ... |
| url.go:65:17:65:48 | call to Parse | url.go:65:2:65:48 | extract:1 ... := ... |
| url.go:65:27:65:47 | "http://harmless.org" | url.go:65:2:65:48 | extract:0 ... := ... |
| url.go:66:9:66:16 | cleanUrl | url.go:66:9:66:28 | call to JoinPath |
| url.go:66:27:66:27 | q | url.go:66:9:66:28 | call to JoinPath |

View File

@@ -1,8 +1,8 @@
#select
| UnsafeUnzipSymlinkGood.go:72:3:72:25 | extract:0 ... := ... | UnsafeUnzipSymlinkGood.go:72:3:72:25 | extract:0 ... := ... | UnsafeUnzipSymlinkGood.go:61:31:61:62 | call to Join | Unsanitized archive entry, which may contain '..', is used in a $@. | UnsafeUnzipSymlinkGood.go:61:31:61:62 | call to Join | file system operation |
| ZipSlip.go:11:2:15:2 | extract:1 range statement | ZipSlip.go:11:2:15:2 | extract:1 range statement | ZipSlip.go:14:20:14:20 | p | Unsanitized archive entry, which may contain '..', is used in a $@. | ZipSlip.go:14:20:14:20 | p | file system operation |
| ZipSlip.go:11:2:15:2 | extract:1 range element | ZipSlip.go:11:2:15:2 | extract:1 range element | ZipSlip.go:14:20:14:20 | p | Unsanitized archive entry, which may contain '..', is used in a $@. | ZipSlip.go:14:20:14:20 | p | file system operation |
| tarslip.go:15:2:15:30 | extract:0 ... := ... | tarslip.go:15:2:15:30 | extract:0 ... := ... | tarslip.go:16:14:16:34 | call to Dir | Unsanitized archive entry, which may contain '..', is used in a $@. | tarslip.go:16:14:16:34 | call to Dir | file system operation |
| tst.go:23:2:43:2 | extract:1 range statement | tst.go:23:2:43:2 | extract:1 range statement | tst.go:29:20:29:23 | path | Unsanitized archive entry, which may contain '..', is used in a $@. | tst.go:29:20:29:23 | path | file system operation |
| tst.go:23:2:43:2 | extract:1 range element | tst.go:23:2:43:2 | extract:1 range element | tst.go:29:20:29:23 | path | Unsanitized archive entry, which may contain '..', is used in a $@. | tst.go:29:20:29:23 | path | file system operation |
edges
| UnsafeUnzipSymlinkGood.go:52:55:67:1 | SSA def(candidate) | UnsafeUnzipSymlinkGood.go:61:53:61:61 | candidate | provenance | |
| UnsafeUnzipSymlinkGood.go:61:53:61:61 | candidate | UnsafeUnzipSymlinkGood.go:61:31:61:62 | call to Join | provenance | FunctionModel Sink:MaD:3 |
@@ -10,12 +10,12 @@ edges
| UnsafeUnzipSymlinkGood.go:72:3:72:25 | extract:0 ... := ... | UnsafeUnzipSymlinkGood.go:76:70:76:80 | selection of Name | provenance | |
| UnsafeUnzipSymlinkGood.go:76:24:76:38 | selection of Linkname | UnsafeUnzipSymlinkGood.go:52:55:67:1 | SSA def(candidate) | provenance | |
| UnsafeUnzipSymlinkGood.go:76:70:76:80 | selection of Name | UnsafeUnzipSymlinkGood.go:52:55:67:1 | SSA def(candidate) | provenance | |
| ZipSlip.go:11:2:15:2 | extract:1 range statement | ZipSlip.go:12:24:12:29 | selection of Name | provenance | |
| ZipSlip.go:11:2:15:2 | extract:1 range element | ZipSlip.go:12:24:12:29 | selection of Name | provenance | |
| ZipSlip.go:12:3:12:30 | extract:0 ... := ... | ZipSlip.go:14:20:14:20 | p | provenance | Sink:MaD:1 |
| ZipSlip.go:12:24:12:29 | selection of Name | ZipSlip.go:12:3:12:30 | extract:0 ... := ... | provenance | MaD:4 |
| tarslip.go:15:2:15:30 | extract:0 ... := ... | tarslip.go:16:23:16:33 | selection of Name | provenance | |
| tarslip.go:16:23:16:33 | selection of Name | tarslip.go:16:14:16:34 | call to Dir | provenance | MaD:5 Sink:MaD:2 |
| tst.go:23:2:43:2 | extract:1 range statement | tst.go:29:20:29:23 | path | provenance | Sink:MaD:1 |
| tst.go:23:2:43:2 | extract:1 range element | tst.go:29:20:29:23 | path | provenance | Sink:MaD:1 |
models
| 1 | Sink: io/ioutil; ; false; WriteFile; ; ; Argument[0]; path-injection; manual |
| 2 | Sink: os; ; false; MkdirAll; ; ; Argument[0]; path-injection; manual |
@@ -29,13 +29,13 @@ nodes
| UnsafeUnzipSymlinkGood.go:72:3:72:25 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
| UnsafeUnzipSymlinkGood.go:76:24:76:38 | selection of Linkname | semmle.label | selection of Linkname |
| UnsafeUnzipSymlinkGood.go:76:70:76:80 | selection of Name | semmle.label | selection of Name |
| ZipSlip.go:11:2:15:2 | extract:1 range statement | semmle.label | extract:1 range statement |
| ZipSlip.go:11:2:15:2 | extract:1 range element | semmle.label | extract:1 range element |
| ZipSlip.go:12:3:12:30 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
| ZipSlip.go:12:24:12:29 | selection of Name | semmle.label | selection of Name |
| ZipSlip.go:14:20:14:20 | p | semmle.label | p |
| tarslip.go:15:2:15:30 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
| tarslip.go:16:14:16:34 | call to Dir | semmle.label | call to Dir |
| tarslip.go:16:23:16:33 | selection of Name | semmle.label | selection of Name |
| tst.go:23:2:43:2 | extract:1 range statement | semmle.label | extract:1 range statement |
| tst.go:23:2:43:2 | extract:1 range element | semmle.label | extract:1 range element |
| tst.go:29:20:29:23 | path | semmle.label | path |
subpaths

View File

@@ -60,10 +60,10 @@
| protobuf.go:14:14:14:35 | call to GetDescription | protobuf.go:9:2:9:23 | SSA def(password) | protobuf.go:14:14:14:35 | call to GetDescription | $@ flows to a logging call. | protobuf.go:9:2:9:23 | SSA def(password) | Sensitive data returned by an access to password |
| server1.go:19:15:19:19 | user3 | server1.go:17:4:17:63 | key-value pair | server1.go:19:15:19:19 | user3 | $@ flows to a logging call. | server1.go:17:4:17:63 | key-value pair | Sensitive data returned by an access to password |
edges
| klog.go:21:3:26:3 | extract:1 range statement | klog.go:22:27:22:33 | headers | provenance | |
| klog.go:21:30:21:37 | selection of Header | klog.go:21:3:26:3 | extract:1 range statement | provenance | Src:MaD:11 Config |
| klog.go:22:4:25:4 | extract:1 range statement | klog.go:23:15:23:20 | header | provenance | |
| klog.go:22:27:22:33 | headers | klog.go:22:4:25:4 | extract:1 range statement | provenance | Config |
| klog.go:21:3:26:3 | extract:1 range element | klog.go:22:27:22:33 | headers | provenance | |
| klog.go:21:30:21:37 | selection of Header | klog.go:21:3:26:3 | extract:1 range element | provenance | Src:MaD:11 Config |
| klog.go:22:4:25:4 | extract:1 range element | klog.go:23:15:23:20 | header | provenance | |
| klog.go:22:27:22:33 | headers | klog.go:22:4:25:4 | extract:1 range element | provenance | Config |
| klog.go:29:13:29:20 | selection of Header | klog.go:29:13:29:41 | call to Get | provenance | Src:MaD:11 Config |
| main.go:17:2:17:23 | SSA def(password) | main.go:19:12:19:19 | password | provenance | |
| main.go:17:2:17:23 | SSA def(password) | main.go:20:19:20:26 | password | provenance | |
@@ -175,9 +175,9 @@ models
| 10 | Sink: log; Logger; true; Printf; ; ; Argument[0..1]; log-injection; manual |
| 11 | Source: net/http; Request; true; Header; ; ; ; remote; manual |
nodes
| klog.go:21:3:26:3 | extract:1 range statement | semmle.label | extract:1 range statement |
| klog.go:21:3:26:3 | extract:1 range element | semmle.label | extract:1 range element |
| klog.go:21:30:21:37 | selection of Header | semmle.label | selection of Header |
| klog.go:22:4:25:4 | extract:1 range statement | semmle.label | extract:1 range statement |
| klog.go:22:4:25:4 | extract:1 range element | semmle.label | extract:1 range element |
| klog.go:22:27:22:33 | headers | semmle.label | headers |
| klog.go:23:15:23:20 | header | semmle.label | header |
| klog.go:29:13:29:20 | selection of Header | semmle.label | selection of Header |