Merge branch 'github:main' into main

This commit is contained in:
cokeBeer 2022-05-13 20:23:24 +08:00 коммит произвёл GitHub
Родитель ebcb040050 211580e608
Коммит 252b19063e
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
68 изменённых файлов: 5239 добавлений и 194 удалений

12
.github/workflows/codeqltest.yml поставляемый
Просмотреть файл

@ -7,10 +7,10 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Set up Go 1.17 - name: Set up Go 1.18.1
uses: actions/setup-go@v1 uses: actions/setup-go@v1
with: with:
go-version: 1.17 go-version: 1.18.1
id: go id: go
- name: Set up CodeQL CLI - name: Set up CodeQL CLI
@ -59,10 +59,10 @@ jobs:
name: Test MacOS name: Test MacOS
runs-on: macOS-latest runs-on: macOS-latest
steps: steps:
- name: Set up Go 1.17 - name: Set up Go 1.18.1
uses: actions/setup-go@v1 uses: actions/setup-go@v1
with: with:
go-version: 1.17 go-version: 1.18.1
id: go id: go
- name: Set up CodeQL CLI - name: Set up CodeQL CLI
@ -99,10 +99,10 @@ jobs:
name: Test Windows name: Test Windows
runs-on: windows-2019 runs-on: windows-2019
steps: steps:
- name: Set up Go 1.17 - name: Set up Go 1.18.1
uses: actions/setup-go@v1 uses: actions/setup-go@v1
with: with:
go-version: 1.17 go-version: 1.18.1
id: go id: go
- name: Set up CodeQL CLI - name: Set up CodeQL CLI

Просмотреть файл

@ -0,0 +1,41 @@
class Expr_ extends @expr {
string toString() { result = "Expr" }
}
class ExprParent_ extends @exprparent {
string toString() { result = "ExprParent" }
}
/**
* Two new kinds have been inserted such that `@sliceexpr` which used to have
* index 13 now has index 15. Another new kind has been inserted such that
* `@plusexpr` which used to have index 23 now has index 26. Entries with
* indices lower than 13 are unchanged.
*/
bindingset[new_index]
int old_index(int new_index) {
if new_index < 13
then result = new_index
else
if new_index = [13, 14]
then result = 0 // badexpr
else
if new_index < 23
then result + (15 - 13) = new_index
else
if new_index = 23
then result = 0 // badexpr
else result + (26 - 23) = new_index
}
// The schema for exprs is:
//
// exprs(unique int id: @expr,
// int kind: int ref,
// int parent: @exprparent ref,
// int idx: int ref);
from Expr_ expr, int new_kind, ExprParent_ parent, int idx, int old_kind
where
exprs(expr, new_kind, parent, idx) and
old_kind = old_index(new_kind)
select expr, old_kind, parent, idx

Просмотреть файл

@ -0,0 +1,531 @@
/** Auto-generated dbscheme; do not edit. */
/** 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);
/*
* 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);
#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: @namedtype 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 named: @namedtype 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);
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);
@container = @file | @folder;
@locatable = @xmllocatable | @node | @localscope;
@node = @documentable | @exprparent | @modexprparent | @fieldparent | @stmtparent | @declparent | @scopenode
| @comment_group | @comment;
@documentable = @file | @field | @spec | @gendecl | @funcdecl | @modexpr;
@exprparent = @funcdef | @file | @expr | @field | @stmt | @decl | @spec;
@modexprparent = @file | @modexpr;
@fieldparent = @decl | @structtypeexpr | @functypeexpr | @interfacetypeexpr;
@stmtparent = @funcdef | @stmt | @decl;
@declparent = @file | @declstmt;
@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 = @sliceexpr
| 14 = @typeassertexpr
| 15 = @callorconversionexpr
| 16 = @starexpr
| 17 = @keyvalueexpr
| 18 = @arraytypeexpr
| 19 = @structtypeexpr
| 20 = @functypeexpr
| 21 = @interfacetypeexpr
| 22 = @maptypeexpr
| 23 = @plusexpr
| 24 = @minusexpr
| 25 = @notexpr
| 26 = @complementexpr
| 27 = @derefexpr
| 28 = @addressexpr
| 29 = @arrowexpr
| 30 = @lorexpr
| 31 = @landexpr
| 32 = @eqlexpr
| 33 = @neqexpr
| 34 = @lssexpr
| 35 = @leqexpr
| 36 = @gtrexpr
| 37 = @geqexpr
| 38 = @addexpr
| 39 = @subexpr
| 40 = @orexpr
| 41 = @xorexpr
| 42 = @mulexpr
| 43 = @quoexpr
| 44 = @remexpr
| 45 = @shlexpr
| 46 = @shrexpr
| 47 = @andexpr
| 48 = @andnotexpr
| 49 = @sendchantypeexpr
| 50 = @recvchantypeexpr
| 51 = @sendrcvchantypeexpr
| 52 = @errorexpr;
@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;
@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 = @arraytype
| 27 = @slicetype
| 28 = @structtype
| 29 = @pointertype
| 30 = @interfacetype
| 31 = @tupletype
| 32 = @signaturetype
| 33 = @maptype
| 34 = @sendchantype
| 35 = @recvchantype
| 36 = @sendrcvchantype
| 37 = @namedtype;
@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 = @containertype | @structtype | @pointertype | @interfacetype | @tupletype | @signaturetype | @namedtype;
@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;

Просмотреть файл

@ -0,0 +1,547 @@
/** Auto-generated dbscheme; do not edit. */
/** 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);
/*
* 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: @namedtype 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 named: @namedtype 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);
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 = @errorexpr;
@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 = @namedtype
| 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 | @namedtype | @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;

Просмотреть файл

@ -0,0 +1,31 @@
class Type_ extends @type {
string toString() { result = "Type" }
}
/**
* A new kind has been inserted such that `@arraytype` which used to have index
* 26 now has index 27. Another new kind has been inserted at 39, which is the
* end of the list. Entries with lower indices are unchanged.
*/
bindingset[new_index]
int old_index(int new_index) {
if new_index < 26
then result = new_index
else
if new_index = 26
then result = 0 // invalidtype
else
if new_index < 39
then result + (27 - 26) = new_index
else result = 0 // invalidtype
}
// The schema for types is:
//
// types(unique int id: @type,
// int kind: int ref);
from Type_ type, int new_kind, int old_kind
where
types(type, new_kind) and
old_kind = old_index(new_kind)
select type, old_kind

Просмотреть файл

@ -0,0 +1,6 @@
description: Add generic instantiation expressions and type parameter types
compatibility: full
exprs.rel: run exprs.qlo
types.rel: run types.qlo
typeparamdecls.rel: delete
typeparam.rel: delete

Просмотреть файл

@ -0,0 +1,531 @@
/** Auto-generated dbscheme; do not edit. */
/** 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);
/*
* 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);
#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: @namedtype 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 named: @namedtype 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);
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);
@container = @file | @folder;
@locatable = @xmllocatable | @node | @localscope;
@node = @documentable | @exprparent | @modexprparent | @fieldparent | @stmtparent | @declparent | @scopenode
| @comment_group | @comment;
@documentable = @file | @field | @spec | @gendecl | @funcdecl | @modexpr;
@exprparent = @funcdef | @file | @expr | @field | @stmt | @decl | @spec;
@modexprparent = @file | @modexpr;
@fieldparent = @decl | @structtypeexpr | @functypeexpr | @interfacetypeexpr;
@stmtparent = @funcdef | @stmt | @decl;
@declparent = @file | @declstmt;
@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 = @sliceexpr
| 14 = @typeassertexpr
| 15 = @callorconversionexpr
| 16 = @starexpr
| 17 = @keyvalueexpr
| 18 = @arraytypeexpr
| 19 = @structtypeexpr
| 20 = @functypeexpr
| 21 = @interfacetypeexpr
| 22 = @maptypeexpr
| 23 = @plusexpr
| 24 = @minusexpr
| 25 = @notexpr
| 26 = @complementexpr
| 27 = @derefexpr
| 28 = @addressexpr
| 29 = @arrowexpr
| 30 = @lorexpr
| 31 = @landexpr
| 32 = @eqlexpr
| 33 = @neqexpr
| 34 = @lssexpr
| 35 = @leqexpr
| 36 = @gtrexpr
| 37 = @geqexpr
| 38 = @addexpr
| 39 = @subexpr
| 40 = @orexpr
| 41 = @xorexpr
| 42 = @mulexpr
| 43 = @quoexpr
| 44 = @remexpr
| 45 = @shlexpr
| 46 = @shrexpr
| 47 = @andexpr
| 48 = @andnotexpr
| 49 = @sendchantypeexpr
| 50 = @recvchantypeexpr
| 51 = @sendrcvchantypeexpr
| 52 = @errorexpr;
@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;
@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 = @arraytype
| 27 = @slicetype
| 28 = @structtype
| 29 = @pointertype
| 30 = @interfacetype
| 31 = @tupletype
| 32 = @signaturetype
| 33 = @maptype
| 34 = @sendchantype
| 35 = @recvchantype
| 36 = @sendrcvchantype
| 37 = @namedtype;
@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 = @containertype | @structtype | @pointertype | @interfacetype | @tupletype | @signaturetype | @namedtype;
@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;

4
downgrades/qlpack.yml Normal file
Просмотреть файл

@ -0,0 +1,4 @@
name: codeql/go-downgrades
groups: go
downgrades: .
library: true

Просмотреть файл

@ -4,6 +4,7 @@ import (
"go/ast" "go/ast"
"go/token" "go/token"
gotypes "go/types" gotypes "go/types"
"golang.org/x/tools/go/packages" "golang.org/x/tools/go/packages"
) )
@ -274,6 +275,9 @@ var StmtParentType = NewUnionType("@stmtparent", NodeType)
// DeclParentType is the type of AST nodes that can have declarations as children // DeclParentType is the type of AST nodes that can have declarations as children
var DeclParentType = NewUnionType("@declparent", NodeType) var DeclParentType = NewUnionType("@declparent", NodeType)
// TypeParamDeclParentType is the type of AST nodes that can have type parameter declarations as children
var TypeParamDeclParentType = NewUnionType("@typeparamdeclparent", NodeType)
// FuncDefType is the type of AST nodes that define functions, that is, function // FuncDefType is the type of AST nodes that define functions, that is, function
// declarations and function literals // declarations and function literals
var FuncDefType = NewUnionType("@funcdef", StmtParentType, ExprParentType) var FuncDefType = NewUnionType("@funcdef", StmtParentType, ExprParentType)
@ -308,6 +312,9 @@ var StmtType = NewPrimaryKeyType("@stmt", ExprParentType, StmtParentType)
// DeclType is the type of declaration AST nodes // DeclType is the type of declaration AST nodes
var DeclType = NewPrimaryKeyType("@decl", ExprParentType, StmtParentType, FieldParentType) var DeclType = NewPrimaryKeyType("@decl", ExprParentType, StmtParentType, FieldParentType)
// TypeParamDeclType is the type of type parameter declaration AST nodes
var TypeParamDeclType = NewPrimaryKeyType("@typeparamdecl", DocumentableType, ExprParentType)
// SpecType is the type of spec AST nodes // SpecType is the type of spec AST nodes
var SpecType = NewPrimaryKeyType("@spec", ExprParentType, DocumentableType) var SpecType = NewPrimaryKeyType("@spec", ExprParentType, DocumentableType)
@ -371,9 +378,23 @@ var ParenExpr = ExprKind.NewBranch("@parenexpr")
// SelectorExpr is the type of selector expression AST nodes // SelectorExpr is the type of selector expression AST nodes
var SelectorExpr = ExprKind.NewBranch("@selectorexpr") var SelectorExpr = ExprKind.NewBranch("@selectorexpr")
// IndexExpr is the type of index expression AST nodes // IndexExpr is the type of AST nodes for index expressions and generic type
// instantiation expressions with one type argument. Note that syntactically
// unambiguous generic instantiations will be extracted as
// `GenericTypeInstantiationExpr`.
var IndexExpr = ExprKind.NewBranch("@indexexpr") var IndexExpr = ExprKind.NewBranch("@indexexpr")
// GenericFunctionInstantiationExpr is the type of AST nodes that represent an instantiation
// of a generic type. These correspond to some index expression AST nodes and all index
// list expression AST nodes.
var GenericFunctionInstantiationExpr = ExprKind.NewBranch("@genericfunctioninstantiationexpr")
// GenericTypeInstantiationExpr is the type of AST nodes that represent an instantiation
// of a generic type. These correspond to some index expression AST nodes and all index
// list expression AST nodes. Note some syntactically ambiguous instantations are
// extracted as an `IndexExpr` to be disambiguated in QL later.
var GenericTypeInstantiationExpr = ExprKind.NewBranch("@generictypeinstantiationexpr")
// SliceExpr is the type of slice expression AST nodes // SliceExpr is the type of slice expression AST nodes
var SliceExpr = ExprKind.NewBranch("@sliceexpr") var SliceExpr = ExprKind.NewBranch("@sliceexpr")
@ -453,6 +474,9 @@ var InterfaceTypeExpr = ExprKind.NewBranch("@interfacetypeexpr", FieldParentType
// MapTypeExpr is the type of map type AST nodes // MapTypeExpr is the type of map type AST nodes
var MapTypeExpr = ExprKind.NewBranch("@maptypeexpr") var MapTypeExpr = ExprKind.NewBranch("@maptypeexpr")
// TypeSetLiteralExpr is the type of type set literal type AST nodes
var TypeSetLiteralExpr = ExprKind.NewBranch("@typesetliteralexpr")
// ChanTypeExpr is the type of channel type AST nodes // ChanTypeExpr is the type of channel type AST nodes
var ChanTypeExpr = NewUnionType("@chantypeexpr") var ChanTypeExpr = NewUnionType("@chantypeexpr")
@ -635,7 +659,7 @@ var TypeDeclType = DeclKind.NewBranch("@typedecl", GenDeclType)
var VarDeclType = DeclKind.NewBranch("@vardecl", GenDeclType) var VarDeclType = DeclKind.NewBranch("@vardecl", GenDeclType)
// FuncDeclType is the type of function declaration AST nodes // FuncDeclType is the type of function declaration AST nodes
var FuncDeclType = DeclKind.NewBranch("@funcdecl", DocumentableType, FuncDefType) var FuncDeclType = DeclKind.NewBranch("@funcdecl", DocumentableType, FuncDefType, TypeParamDeclParentType)
// SpecKind is a case type for distinguishing different kinds of declaration specification nodes // SpecKind is a case type for distinguishing different kinds of declaration specification nodes
var SpecKind = NewCaseType(SpecType, "kind") var SpecKind = NewCaseType(SpecType, "kind")
@ -647,7 +671,7 @@ var ImportSpecType = SpecKind.NewBranch("@importspec")
var ValueSpecType = SpecKind.NewBranch("@valuespec") var ValueSpecType = SpecKind.NewBranch("@valuespec")
// TypeSpecType is the type of type declaration specification nodes // TypeSpecType is the type of type declaration specification nodes
var TypeSpecType = NewUnionType("@typespec") var TypeSpecType = NewUnionType("@typespec", TypeParamDeclParentType)
// TypeDefSpecType is the type of type declaration specification nodes corresponding to type definitions // TypeDefSpecType is the type of type declaration specification nodes corresponding to type definitions
var TypeDefSpecType = SpecKind.NewBranch("@typedefspec", TypeSpecType) var TypeDefSpecType = SpecKind.NewBranch("@typedefspec", TypeSpecType)
@ -661,6 +685,9 @@ var ObjectType = NewPrimaryKeyType("@object")
// ObjectKind is a case type for distinguishing different kinds of built-in and declared objects // ObjectKind is a case type for distinguishing different kinds of built-in and declared objects
var ObjectKind = NewCaseType(ObjectType, "kind") var ObjectKind = NewCaseType(ObjectType, "kind")
// TypeParamParentObjectType is the type of objects that can have type parameters as children
var TypeParamParentObjectType = NewUnionType("@typeparamparentobject")
// DeclObjectType is the type of declared objects // DeclObjectType is the type of declared objects
var DeclObjectType = NewUnionType("@declobject") var DeclObjectType = NewUnionType("@declobject")
@ -674,7 +701,7 @@ var PkgObjectType = ObjectKind.NewBranch("@pkgobject")
var TypeObjectType = NewUnionType("@typeobject") var TypeObjectType = NewUnionType("@typeobject")
// DeclTypeObjectType is the type of declared named types // DeclTypeObjectType is the type of declared named types
var DeclTypeObjectType = ObjectKind.NewBranch("@decltypeobject", TypeObjectType, DeclObjectType) var DeclTypeObjectType = ObjectKind.NewBranch("@decltypeobject", TypeObjectType, DeclObjectType, TypeParamParentObjectType)
// BuiltinTypeObjectType is the type of built-in named types // BuiltinTypeObjectType is the type of built-in named types
var BuiltinTypeObjectType = ObjectKind.NewBranch("@builtintypeobject", TypeObjectType, BuiltinObjectType) var BuiltinTypeObjectType = ObjectKind.NewBranch("@builtintypeobject", TypeObjectType, BuiltinObjectType)
@ -701,7 +728,7 @@ var DeclVarObjectType = ObjectKind.NewBranch("@declvarobject", VarObjectType, De
var FunctionObjectType = NewUnionType("@functionobject", ValueObjectType) var FunctionObjectType = NewUnionType("@functionobject", ValueObjectType)
// DeclFuncObjectType is the type of declared functions, including (abstract and concrete) methods // DeclFuncObjectType is the type of declared functions, including (abstract and concrete) methods
var DeclFuncObjectType = ObjectKind.NewBranch("@declfunctionobject", FunctionObjectType, DeclObjectType) var DeclFuncObjectType = ObjectKind.NewBranch("@declfunctionobject", FunctionObjectType, DeclObjectType, TypeParamParentObjectType)
// BuiltinFuncObjectType is the type of built-in functions // BuiltinFuncObjectType is the type of built-in functions
var BuiltinFuncObjectType = ObjectKind.NewBranch("@builtinfunctionobject", FunctionObjectType, BuiltinObjectType) var BuiltinFuncObjectType = ObjectKind.NewBranch("@builtinfunctionobject", FunctionObjectType, BuiltinObjectType)
@ -790,6 +817,9 @@ var BasicTypes = map[gotypes.BasicKind]*BranchType{
// CompositeType is the type of all composite (that is, non-basic) types // CompositeType is the type of all composite (that is, non-basic) types
var CompositeType = NewUnionType("@compositetype") var CompositeType = NewUnionType("@compositetype")
// TypeParamType is the type of type parameter types
var TypeParamType = TypeKind.NewBranch("@typeparamtype", CompositeType)
// ElementContainerType is the type of types that have elements, such as arrays // ElementContainerType is the type of types that have elements, such as arrays
// and channels // and channels
var ElementContainerType = NewUnionType("@containertype", CompositeType) var ElementContainerType = NewUnionType("@containertype", CompositeType)
@ -831,6 +861,9 @@ var ChanTypes = map[gotypes.ChanDir]*BranchType{
// NamedType is the type of named types // NamedType is the type of named types
var NamedType = TypeKind.NewBranch("@namedtype", CompositeType) var NamedType = TypeKind.NewBranch("@namedtype", CompositeType)
// TypeSetLiteral is the type of type set literals
var TypeSetLiteral = TypeKind.NewBranch("@typesetliteraltype", CompositeType)
// PackageType is the type of packages // PackageType is the type of packages
var PackageType = NewPrimaryKeyType("@package") var PackageType = NewPrimaryKeyType("@package")
@ -970,6 +1003,13 @@ var FieldsTable = NewTable("fields",
IntColumn("idx"), IntColumn("idx"),
) )
// TypeParamDeclsTable is the table defining type param declaration AST nodes
var TypeParamDeclsTable = NewTable("typeparamdecls",
EntityColumn(TypeParamDeclType, "id").Key(),
EntityColumn(TypeParamDeclParentType, "parent"),
IntColumn("idx"),
)
// StmtsTable is the table defining statement AST nodes // StmtsTable is the table defining statement AST nodes
var StmtsTable = NewTable("stmts", var StmtsTable = NewTable("stmts",
EntityColumn(StmtType, "id").Key(), EntityColumn(StmtType, "id").Key(),
@ -1171,3 +1211,12 @@ var HasEllipsisTable = NewTable("has_ellipsis",
var VariadicTable = NewTable("variadic", var VariadicTable = NewTable("variadic",
EntityColumn(SignatureType, "id"), EntityColumn(SignatureType, "id"),
) )
// TypeParamTable is the table describing type parameter types
var TypeParamTable = NewTable("typeparam",
EntityColumn(TypeParamType, "tp").Unique(),
StringColumn("name"),
EntityColumn(CompositeType, "bound"),
EntityColumn(TypeParamParentObjectType, "parent"),
IntColumn("idx"),
).KeySet("parent", "idx")

Просмотреть файл

@ -29,6 +29,7 @@ import (
) )
var MaxGoRoutines int var MaxGoRoutines int
var typeParamParent map[*types.TypeParam]types.Object = make(map[*types.TypeParam]types.Object)
func init() { func init() {
// this sets the number of threads that the Go runtime will spawn; this is separate // this sets the number of threads that the Go runtime will spawn; this is separate
@ -109,9 +110,7 @@ func ExtractWithFlags(buildFlags []string, patterns []string) error {
// root directories of packages that we want to extract // root directories of packages that we want to extract
wantedRoots := make(map[string]bool) wantedRoots := make(map[string]bool)
// recursively visit all packages in depth-first order; // Do a post-order traversal and extract the package scope of each package
// on the way down, associate each package scope with its corresponding package,
// and on the way up extract the package's scope
packages.Visit(pkgs, func(pkg *packages.Package) bool { packages.Visit(pkgs, func(pkg *packages.Package) bool {
return true return true
}, func(pkg *packages.Package) { }, func(pkg *packages.Package) {
@ -138,7 +137,7 @@ func ExtractWithFlags(buildFlags []string, patterns []string) error {
defer tw.Close() defer tw.Close()
scope := extractPackageScope(tw, pkg) scope := extractPackageScope(tw, pkg)
tw.ForEachObject(extractObjectType) extractObjectTypes(tw)
lbl := tw.Labeler.GlobalID(util.EscapeTrapSpecialChars(pkg.PkgPath) + ";pkg") lbl := tw.Labeler.GlobalID(util.EscapeTrapSpecialChars(pkg.PkgPath) + ";pkg")
dbscheme.PackagesTable.Emit(tw, lbl, pkg.Name, pkg.PkgPath, scope) dbscheme.PackagesTable.Emit(tw, lbl, pkg.Name, pkg.PkgPath, scope)
@ -361,8 +360,23 @@ func extractUniverseScope() {
func extractObjects(tw *trap.Writer, scope *types.Scope, scopeLabel trap.Label) { func extractObjects(tw *trap.Writer, scope *types.Scope, scopeLabel trap.Label) {
for _, name := range scope.Names() { for _, name := range scope.Names() {
obj := scope.Lookup(name) obj := scope.Lookup(name)
lbl, exists := tw.Labeler.ScopedObjectID(obj, extractType(tw, obj.Type())) lbl, exists := tw.Labeler.ScopedObjectID(obj, func() trap.Label { return extractType(tw, obj.Type()) })
if !exists { if !exists {
// Populate type parameter parents for functions. Note that methods
// do not appear as objects in any scope, so they have to be dealt
// with separately in extractMethods.
if funcObj, ok := obj.(*types.Func); ok {
populateTypeParamParents(tw, funcObj.Type().(*types.Signature).TypeParams(), obj)
populateTypeParamParents(tw, funcObj.Type().(*types.Signature).RecvTypeParams(), obj)
}
// Populate type parameter parents for named types. Note that we
// skip type aliases as the original type should be the parent
// of any type parameters.
if typeNameObj, ok := obj.(*types.TypeName); ok && !typeNameObj.IsAlias() {
if tp, ok := typeNameObj.Type().(*types.Named); ok {
populateTypeParamParents(tw, tp.TypeParams(), obj)
}
}
extractObject(tw, obj, lbl) extractObject(tw, obj, lbl)
} }
@ -378,10 +392,16 @@ func extractObjects(tw *trap.Writer, scope *types.Scope, scopeLabel trap.Label)
func extractMethod(tw *trap.Writer, meth *types.Func) trap.Label { func extractMethod(tw *trap.Writer, meth *types.Func) trap.Label {
// get the receiver type of the method // get the receiver type of the method
recvtyp := meth.Type().(*types.Signature).Recv().Type() recvtyp := meth.Type().(*types.Signature).Recv().Type()
recvlbl := extractType(tw, recvtyp) // ensure receiver type has been extracted // ensure receiver type has been extracted
recvtyplbl := extractType(tw, recvtyp)
// if the method label does not exist, extract it // if the method label does not exist, extract it
methlbl, exists := tw.Labeler.MethodID(meth, recvlbl) methlbl, exists := tw.Labeler.MethodID(meth, recvtyplbl)
if !exists { if !exists {
// Populate type parameter parents for methods. They do not appear as
// objects in any scope, so they have to be dealt with separately here.
populateTypeParamParents(tw, meth.Type().(*types.Signature).TypeParams(), meth)
populateTypeParamParents(tw, meth.Type().(*types.Signature).RecvTypeParams(), meth)
extractObject(tw, meth, methlbl) extractObject(tw, meth, methlbl)
} }
@ -435,8 +455,30 @@ func extractObject(tw *trap.Writer, obj types.Object, lbl trap.Label) {
} }
} }
// extractObjectTypes extracts type and receiver information for all objects
func extractObjectTypes(tw *trap.Writer) {
// calling `extractType` on a named type will extract all methods defined
// on it, which will add new objects. Therefore we need to do this first
// before we loops over all objects and emit them.
changed := true
for changed {
changed = tw.ForEachObject(extractObjectType)
}
changed = tw.ForEachObject(emitObjectType)
if changed {
log.Printf("Warning: more objects were labeled while emitted object types")
}
}
// extractObjectType extracts type and receiver information for a given object // extractObjectType extracts type and receiver information for a given object
func extractObjectType(tw *trap.Writer, obj types.Object, lbl trap.Label) { func extractObjectType(tw *trap.Writer, obj types.Object, lbl trap.Label) {
if tp := obj.Type(); tp != nil {
extractType(tw, tp)
}
}
// emitObjectType emits the type information for a given object
func emitObjectType(tw *trap.Writer, obj types.Object, lbl trap.Label) {
if tp := obj.Type(); tp != nil { if tp := obj.Type(); tp != nil {
dbscheme.ObjectTypesTable.Emit(tw, lbl, extractType(tw, tp)) dbscheme.ObjectTypesTable.Emit(tw, lbl, extractType(tw, tp))
} }
@ -583,7 +625,7 @@ func (extraction *Extraction) extractFile(ast *ast.File, pkg *packages.Package)
extractFileNode(tw, ast) extractFileNode(tw, ast)
tw.ForEachObject(extractObjectType) extractObjectTypes(tw)
extractNumLines(tw, path, ast) extractNumLines(tw, path, ast)
@ -685,7 +727,8 @@ func extractScopeLocation(tw *trap.Writer, scope *types.Scope, lbl trap.Label) {
} }
// extractScopes extracts symbol table information for the package scope and all local scopes // extractScopes extracts symbol table information for the package scope and all local scopes
// of the given package // of the given package. Note that this will not encounter methods or struct fields as
// they do not have a parent scope.
func extractScopes(tw *trap.Writer, nd *ast.File, pkg *packages.Package) { func extractScopes(tw *trap.Writer, nd *ast.File, pkg *packages.Package) {
pkgScopeLabel := extractPackageScope(tw, pkg) pkgScopeLabel := extractPackageScope(tw, pkg)
fileScope := pkg.TypesInfo.Scopes[nd] fileScope := pkg.TypesInfo.Scopes[nd]
@ -801,7 +844,7 @@ func extractExpr(tw *trap.Writer, expr ast.Expr, parent trap.Label, idx int) {
dbscheme.DefsTable.Emit(tw, lbl, objlbl) dbscheme.DefsTable.Emit(tw, lbl, objlbl)
} }
} }
use := tw.Package.TypesInfo.Uses[expr] use := getObjectBeingUsed(tw, expr)
if use != nil { if use != nil {
useTyp := extractType(tw, use.Type()) useTyp := extractType(tw, use.Type())
objlbl, exists := tw.Labeler.LookupObjectID(use, useTyp) objlbl, exists := tw.Labeler.LookupObjectID(use, useTyp)
@ -877,9 +920,43 @@ func extractExpr(tw *trap.Writer, expr ast.Expr, parent trap.Label, idx int) {
if expr == nil { if expr == nil {
return return
} }
kind = dbscheme.IndexExpr.Index() typeofx := typeOf(tw, expr.X)
if typeofx == nil {
// We are missing type information for `expr.X`, so we cannot
// determine whether this is a generic function instantiation
// or not.
kind = dbscheme.IndexExpr.Index()
} else {
if _, ok := typeofx.Underlying().(*types.Signature); ok {
kind = dbscheme.GenericFunctionInstantiationExpr.Index()
} else {
// Can't distinguish between actual index expressions (into a
// map, array, slice, string or pointer to array) and generic
// type specialization expression, so we do it later in QL.
kind = dbscheme.IndexExpr.Index()
}
}
extractExpr(tw, expr.X, lbl, 0) extractExpr(tw, expr.X, lbl, 0)
extractExpr(tw, expr.Index, lbl, 1) extractExpr(tw, expr.Index, lbl, 1)
case *ast.IndexListExpr:
if expr == nil {
return
}
typeofx := typeOf(tw, expr.X)
if typeofx == nil {
// We are missing type information for `expr.X`, so we cannot
// determine whether this is a generic function instantiation
// or not.
kind = dbscheme.GenericTypeInstantiationExpr.Index()
} else {
if _, ok := typeofx.Underlying().(*types.Signature); ok {
kind = dbscheme.GenericFunctionInstantiationExpr.Index()
} else {
kind = dbscheme.GenericTypeInstantiationExpr.Index()
}
}
extractExpr(tw, expr.X, lbl, 0)
extractExprs(tw, expr.Indices, lbl, 1, 1)
case *ast.SliceExpr: case *ast.SliceExpr:
if expr == nil { if expr == nil {
return return
@ -923,23 +1000,33 @@ func extractExpr(tw *trap.Writer, expr ast.Expr, parent trap.Label, idx int) {
if expr == nil { if expr == nil {
return return
} }
tp := dbscheme.UnaryExprs[expr.Op] if expr.Op == token.TILDE {
if tp == nil { kind = dbscheme.TypeSetLiteralExpr.Index()
log.Fatalf("unsupported unary operator %s", expr.Op) } else {
tp := dbscheme.UnaryExprs[expr.Op]
if tp == nil {
log.Fatalf("unsupported unary operator %s", expr.Op)
}
kind = tp.Index()
} }
kind = tp.Index()
extractExpr(tw, expr.X, lbl, 0) extractExpr(tw, expr.X, lbl, 0)
case *ast.BinaryExpr: case *ast.BinaryExpr:
if expr == nil { if expr == nil {
return return
} }
tp := dbscheme.BinaryExprs[expr.Op] _, isUnionType := typeOf(tw, expr).(*types.Union)
if tp == nil { if expr.Op == token.OR && isUnionType {
log.Fatalf("unsupported binary operator %s", expr.Op) kind = dbscheme.TypeSetLiteralExpr.Index()
flattenBinaryExprTree(tw, expr, lbl, 0)
} else {
tp := dbscheme.BinaryExprs[expr.Op]
if tp == nil {
log.Fatalf("unsupported binary operator %s", expr.Op)
}
kind = tp.Index()
extractExpr(tw, expr.X, lbl, 0)
extractExpr(tw, expr.Y, lbl, 1)
} }
kind = tp.Index()
extractExpr(tw, expr.X, lbl, 0)
extractExpr(tw, expr.Y, lbl, 1)
case *ast.ArrayType: case *ast.ArrayType:
if expr == nil { if expr == nil {
return return
@ -966,6 +1053,9 @@ func extractExpr(tw *trap.Writer, expr ast.Expr, parent trap.Label, idx int) {
return return
} }
kind = dbscheme.InterfaceTypeExpr.Index() kind = dbscheme.InterfaceTypeExpr.Index()
// expr.Methods contains methods, embedded interfaces and type set
// literals.
makeTypeSetLiteralsUnionTyped(tw, expr.Methods)
extractFields(tw, expr.Methods, lbl, 0, 1) extractFields(tw, expr.Methods, lbl, 0, 1)
case *ast.MapType: case *ast.MapType:
if expr == nil { if expr == nil {
@ -1009,7 +1099,7 @@ func extractExprs(tw *trap.Writer, exprs []ast.Expr, parent trap.Label, idx int,
// extractTypeOf looks up the type of `expr`, extracts it if it hasn't previously been // extractTypeOf looks up the type of `expr`, extracts it if it hasn't previously been
// extracted, and associates it with `expr` in the `type_of` table // extracted, and associates it with `expr` in the `type_of` table
func extractTypeOf(tw *trap.Writer, expr ast.Expr, lbl trap.Label) { func extractTypeOf(tw *trap.Writer, expr ast.Expr, lbl trap.Label) {
tp := tw.Package.TypesInfo.TypeOf(expr) tp := typeOf(tw, expr)
if tp != nil { if tp != nil {
tplbl := extractType(tw, tp) tplbl := extractType(tw, tp)
dbscheme.TypeOfTable.Emit(tw, lbl, tplbl) dbscheme.TypeOfTable.Emit(tw, lbl, tplbl)
@ -1304,6 +1394,12 @@ func extractDecl(tw *trap.Writer, decl ast.Decl, parent trap.Label, idx int) {
extractExpr(tw, decl.Type, lbl, 1) extractExpr(tw, decl.Type, lbl, 1)
extractStmt(tw, decl.Body, lbl, 2) extractStmt(tw, decl.Body, lbl, 2)
extractDoc(tw, decl.Doc, lbl) extractDoc(tw, decl.Doc, lbl)
extractTypeParamDecls(tw, decl.Type.TypeParams, lbl)
// Note that we currently don't extract any kind of declaration for
// receiver type parameters. There isn't an explicit declaration, but
// we could consider the index/indices of an IndexExpr/IndexListExpr
// receiver as declarations.
default: default:
log.Fatalf("unknown declaration of type %T", decl) log.Fatalf("unknown declaration of type %T", decl)
} }
@ -1345,6 +1441,7 @@ func extractSpec(tw *trap.Writer, spec ast.Spec, parent trap.Label, idx int) {
kind = dbscheme.TypeDefSpecType.Index() kind = dbscheme.TypeDefSpecType.Index()
} }
extractExpr(tw, spec.Name, lbl, 0) extractExpr(tw, spec.Name, lbl, 0)
extractTypeParamDecls(tw, spec.TypeParams, lbl)
extractExpr(tw, spec.Type, lbl, 1) extractExpr(tw, spec.Type, lbl, 1)
extractDoc(tw, spec.Doc, lbl) extractDoc(tw, spec.Doc, lbl)
} }
@ -1377,7 +1474,9 @@ func extractType(tw *trap.Writer, tp types.Type) trap.Label {
for i := 0; i < tp.NumFields(); i++ { for i := 0; i < tp.NumFields(); i++ {
field := tp.Field(i) field := tp.Field(i)
// ensure the field is associated with a label // ensure the field is associated with a label - note that
// struct fields do not have a parent scope, so they are not
// dealt with by `extractScopes`
fieldlbl, exists := tw.Labeler.FieldID(field, i, lbl) fieldlbl, exists := tw.Labeler.FieldID(field, i, lbl)
if !exists { if !exists {
extractObject(tw, field, fieldlbl) extractObject(tw, field, fieldlbl)
@ -1399,10 +1498,19 @@ func extractType(tw *trap.Writer, tp types.Type) trap.Label {
for i := 0; i < tp.NumMethods(); i++ { for i := 0; i < tp.NumMethods(); i++ {
meth := tp.Method(i) meth := tp.Method(i)
// Note that methods do not have a parent scope, so they are
// not dealt with by `extractScopes`
extractMethod(tw, meth) extractMethod(tw, meth)
extractComponentType(tw, lbl, i, meth.Name(), meth.Type()) extractComponentType(tw, lbl, i, meth.Name(), meth.Type())
} }
for i := 0; i < tp.NumEmbeddeds(); i++ {
component := tp.EmbeddedType(i)
if isNonUnionTypeSetLiteral(component) {
component = createUnionFromType(component)
}
extractComponentType(tw, lbl, -(i + 1), "", component)
}
case *types.Tuple: case *types.Tuple:
kind = dbscheme.TupleType.Index() kind = dbscheme.TupleType.Index()
for i := 0; i < tp.Len(); i++ { for i := 0; i < tp.Len(); i++ {
@ -1410,11 +1518,11 @@ func extractType(tw *trap.Writer, tp types.Type) trap.Label {
} }
case *types.Signature: case *types.Signature:
kind = dbscheme.SignatureType.Index() kind = dbscheme.SignatureType.Index()
parms, results := tp.Params(), tp.Results() params, results := tp.Params(), tp.Results()
if parms != nil { if params != nil {
for i := 0; i < parms.Len(); i++ { for i := 0; i < params.Len(); i++ {
parm := parms.At(i) param := params.At(i)
extractComponentType(tw, lbl, i+1, "", parm.Type()) extractComponentType(tw, lbl, i+1, "", param.Type())
} }
} }
if results != nil { if results != nil {
@ -1434,24 +1542,27 @@ func extractType(tw *trap.Writer, tp types.Type) trap.Label {
kind = dbscheme.ChanTypes[tp.Dir()].Index() kind = dbscheme.ChanTypes[tp.Dir()].Index()
extractElementType(tw, lbl, tp.Elem()) extractElementType(tw, lbl, tp.Elem())
case *types.Named: case *types.Named:
origintp := tp.Origin()
kind = dbscheme.NamedType.Index() kind = dbscheme.NamedType.Index()
dbscheme.TypeNameTable.Emit(tw, lbl, tp.Obj().Name()) dbscheme.TypeNameTable.Emit(tw, lbl, origintp.Obj().Name())
underlying := tp.Underlying() underlying := origintp.Underlying()
extractUnderlyingType(tw, lbl, underlying) extractUnderlyingType(tw, lbl, underlying)
trackInstantiatedStructFields(tw, tp, origintp)
entitylbl, exists := tw.Labeler.LookupObjectID(tp.Obj(), lbl) entitylbl, exists := tw.Labeler.LookupObjectID(origintp.Obj(), lbl)
if entitylbl == trap.InvalidLabel { if entitylbl == trap.InvalidLabel {
log.Printf("Omitting type-object binding for unknown object %v.\n", tp.Obj()) log.Printf("Omitting type-object binding for unknown object %v.\n", origintp.Obj())
} else { } else {
if !exists { if !exists {
extractObject(tw, tp.Obj(), entitylbl) extractObject(tw, origintp.Obj(), entitylbl)
} }
dbscheme.TypeObjectTable.Emit(tw, lbl, entitylbl) dbscheme.TypeObjectTable.Emit(tw, lbl, entitylbl)
} }
// ensure all methods have labels // ensure all methods have labels - note that methods do not have a
for i := 0; i < tp.NumMethods(); i++ { // parent scope, so they are not dealt with by `extractScopes`
meth := tp.Method(i) for i := 0; i < origintp.NumMethods(); i++ {
meth := origintp.Method(i)
extractMethod(tw, meth) extractMethod(tw, meth)
} }
@ -1463,6 +1574,21 @@ func extractType(tw *trap.Writer, tp types.Type) trap.Label {
dbscheme.MethodHostsTable.Emit(tw, methlbl, lbl) dbscheme.MethodHostsTable.Emit(tw, methlbl, lbl)
} }
} }
case *types.TypeParam:
kind = dbscheme.TypeParamType.Index()
parentlbl := getTypeParamParentLabel(tw, tp)
constraintLabel := extractType(tw, tp.Constraint())
dbscheme.TypeParamTable.Emit(tw, lbl, tp.Obj().Name(), constraintLabel, parentlbl, tp.Index())
case *types.Union:
kind = dbscheme.TypeSetLiteral.Index()
for i := 0; i < tp.Len(); i++ {
term := tp.Term(i)
tildeStr := ""
if term.Tilde() {
tildeStr = "~"
}
extractComponentType(tw, lbl, i, tildeStr, term.Type())
}
default: default:
log.Fatalf("unexpected type %T", tp) log.Fatalf("unexpected type %T", tp)
} }
@ -1522,6 +1648,19 @@ func getTypeLabel(tw *trap.Writer, tp types.Type) (trap.Label, bool) {
} }
fmt.Fprintf(&b, "%s,{%s}", meth.Id(), methLbl) fmt.Fprintf(&b, "%s,{%s}", meth.Id(), methLbl)
} }
b.WriteString(";")
for i := 0; i < tp.NumEmbeddeds(); i++ {
if i > 0 {
b.WriteString(",")
}
fmt.Fprintf(&b, "{%s}", extractType(tw, tp.EmbeddedType(i)))
}
// We note whether the interface is comparable so that we can
// distinguish the underlying type of `comparable` from an
// empty interface.
if tp.IsComparable() {
b.WriteString(";comparable")
}
lbl = tw.Labeler.GlobalID(fmt.Sprintf("%s;interfacetype", b.String())) lbl = tw.Labeler.GlobalID(fmt.Sprintf("%s;interfacetype", b.String()))
case *types.Tuple: case *types.Tuple:
var b strings.Builder var b strings.Builder
@ -1535,14 +1674,14 @@ func getTypeLabel(tw *trap.Writer, tp types.Type) (trap.Label, bool) {
lbl = tw.Labeler.GlobalID(fmt.Sprintf("%s;tupletype", b.String())) lbl = tw.Labeler.GlobalID(fmt.Sprintf("%s;tupletype", b.String()))
case *types.Signature: case *types.Signature:
var b strings.Builder var b strings.Builder
parms, results := tp.Params(), tp.Results() params, results := tp.Params(), tp.Results()
if parms != nil { if params != nil {
for i := 0; i < parms.Len(); i++ { for i := 0; i < params.Len(); i++ {
parmLbl := extractType(tw, parms.At(i).Type()) paramLbl := extractType(tw, params.At(i).Type())
if i > 0 { if i > 0 {
b.WriteString(",") b.WriteString(",")
} }
fmt.Fprintf(&b, "{%s}", parmLbl) fmt.Fprintf(&b, "{%s}", paramLbl)
} }
} }
b.WriteString(";") b.WriteString(";")
@ -1568,14 +1707,33 @@ func getTypeLabel(tw *trap.Writer, tp types.Type) (trap.Label, bool) {
elem := extractType(tw, tp.Elem()) elem := extractType(tw, tp.Elem())
lbl = tw.Labeler.GlobalID(fmt.Sprintf("%v,{%s};chantype", dir, elem)) lbl = tw.Labeler.GlobalID(fmt.Sprintf("%v,{%s};chantype", dir, elem))
case *types.Named: case *types.Named:
entitylbl, exists := tw.Labeler.LookupObjectID(tp.Obj(), lbl) origintp := tp.Origin()
entitylbl, exists := tw.Labeler.LookupObjectID(origintp.Obj(), lbl)
if entitylbl == trap.InvalidLabel { if entitylbl == trap.InvalidLabel {
panic(fmt.Sprintf("Cannot construct label for named type %v (underlying object is %v).\n", tp, tp.Obj())) panic(fmt.Sprintf("Cannot construct label for named type %v (underlying object is %v).\n", origintp, origintp.Obj()))
} }
if !exists { if !exists {
extractObject(tw, tp.Obj(), entitylbl) extractObject(tw, origintp.Obj(), entitylbl)
} }
lbl = tw.Labeler.GlobalID(fmt.Sprintf("{%s};namedtype", entitylbl)) lbl = tw.Labeler.GlobalID(fmt.Sprintf("{%s};namedtype", entitylbl))
case *types.TypeParam:
parentlbl := getTypeParamParentLabel(tw, tp)
lbl = tw.Labeler.GlobalID(fmt.Sprintf("{%v},%s;typeparamtype", parentlbl, tp.Obj().Name()))
case *types.Union:
var b strings.Builder
for i := 0; i < tp.Len(); i++ {
compLbl := extractType(tw, tp.Term(i).Type())
if i > 0 {
b.WriteString("|")
}
if tp.Term(i).Tilde() {
b.WriteString("~")
}
fmt.Fprintf(&b, "{%s}", compLbl)
}
lbl = tw.Labeler.GlobalID(fmt.Sprintf("%s;typesetliteraltype", b.String()))
default:
log.Fatalf("(getTypeLabel) unexpected type %T", tp)
} }
tw.Labeler.TypeLabels[tp] = lbl tw.Labeler.TypeLabels[tp] = lbl
} }
@ -1658,3 +1816,206 @@ func extractNumLines(tw *trap.Writer, fileName string, ast *ast.File) {
dbscheme.NumlinesTable.Emit(tw, tw.Labeler.FileLabel(), lineCount, linesOfCode, linesOfComments) dbscheme.NumlinesTable.Emit(tw, tw.Labeler.FileLabel(), lineCount, linesOfCode, linesOfComments)
} }
// For a type `t` which is the type of a field of an interface type, return
// whether `t` a type set literal which is not a union type. Note that a field
// of an interface must be a method signature, an embedded interface type or a
// type set literal.
func isNonUnionTypeSetLiteral(t types.Type) bool {
if t == nil {
return false
}
switch t.Underlying().(type) {
case *types.Interface, *types.Union, *types.Signature:
return false
default:
return true
}
}
// Given a type `t`, return a union with a single term that is `t` without a
// tilde.
func createUnionFromType(t types.Type) *types.Union {
return types.NewUnion([]*types.Term{types.NewTerm(false, t)})
}
// Go through a `FieldList` and update the types of all type set literals which
// are not already union types to be union types. We do this by changing the
// types stored in `tw.Package.TypesInfo.Types`. Type set literals can only
// occur in two places: a type parameter declaration or a type in an interface.
func makeTypeSetLiteralsUnionTyped(tw *trap.Writer, fields *ast.FieldList) {
if fields == nil || fields.List == nil {
return
}
for i := 0; i < len(fields.List); i++ {
x := fields.List[i].Type
if _, alreadyOverridden := tw.TypesOverride[x]; !alreadyOverridden {
xtp := typeOf(tw, x)
if isNonUnionTypeSetLiteral(xtp) {
tw.TypesOverride[x] = createUnionFromType(xtp)
}
}
}
}
func typeOf(tw *trap.Writer, e ast.Expr) types.Type {
if val, ok := tw.TypesOverride[e]; ok {
return val
}
return tw.Package.TypesInfo.TypeOf(e)
}
func flattenBinaryExprTree(tw *trap.Writer, e ast.Expr, parent trap.Label, idx int) int {
binaryexpr, ok := e.(*ast.BinaryExpr)
if ok {
idx = flattenBinaryExprTree(tw, binaryexpr.X, parent, idx)
idx = flattenBinaryExprTree(tw, binaryexpr.Y, parent, idx)
} else {
extractExpr(tw, e, parent, idx)
idx = idx + 1
}
return idx
}
func extractTypeParamDecls(tw *trap.Writer, fields *ast.FieldList, parent trap.Label) {
if fields == nil || fields.List == nil {
return
}
// Type set literals can occur as the type in a type parameter declaration,
// so we ensure that they are union typed.
makeTypeSetLiteralsUnionTyped(tw, fields)
idx := 0
for _, field := range fields.List {
lbl := tw.Labeler.LocalID(field)
dbscheme.TypeParamDeclsTable.Emit(tw, lbl, parent, idx)
extractNodeLocation(tw, field, lbl)
if field.Names != nil {
for i, name := range field.Names {
extractExpr(tw, name, lbl, i+1)
}
}
extractExpr(tw, field.Type, lbl, 0)
extractDoc(tw, field.Doc, lbl)
idx += 1
}
}
// populateTypeParamParents sets `parent` as the parent of the elements of `typeparams`
func populateTypeParamParents(tw *trap.Writer, typeparams *types.TypeParamList, parent types.Object) {
if typeparams != nil {
for idx := 0; idx < typeparams.Len(); idx++ {
setTypeParamParent(typeparams.At(idx), parent)
}
}
}
// getobjectBeingUsed looks up `ident` in `tw.Package.TypesInfo.Uses` and makes
// some changes to the object to avoid returning objects relating to instantiated
// types.
func getObjectBeingUsed(tw *trap.Writer, ident *ast.Ident) types.Object {
obj := tw.Package.TypesInfo.Uses[ident]
if obj == nil {
return nil
}
if override, ok := tw.ObjectsOverride[obj]; ok {
return override
}
if funcObj, ok := obj.(*types.Func); ok {
sig := funcObj.Type().(*types.Signature)
if recv := sig.Recv(); recv != nil {
recvType := recv.Type()
originType, isSame := tryGetGenericType(recvType)
if originType == nil {
if pointerType, ok := recvType.(*types.Pointer); ok {
originType, isSame = tryGetGenericType(pointerType.Elem())
}
}
if originType == nil || isSame {
return obj
}
for i := 0; i < originType.NumMethods(); i++ {
meth := originType.Method(i)
if meth.Name() == funcObj.Name() {
return meth
}
}
if interfaceType, ok := originType.Underlying().(*types.Interface); ok {
for i := 0; i < interfaceType.NumMethods(); i++ {
meth := interfaceType.Method(i)
if meth.Name() == funcObj.Name() {
return meth
}
}
}
log.Fatalf("Could not find method %s on type %s", funcObj.Name(), originType)
}
}
return obj
}
// tryGetGenericType returns the generic type of `tp`, and a boolean indicating
// whether it is the same as `tp`.
func tryGetGenericType(tp types.Type) (*types.Named, bool) {
if namedType, ok := tp.(*types.Named); ok {
originType := namedType.Origin()
return originType, namedType == originType
}
return nil, false
}
// trackInstantiatedStructFields tries to give the fields of an instantiated
// struct type underlying `tp` the same labels as the corresponding fields of
// the generic struct type. This is so that when we come across the
// instantiated field in `tw.Package.TypesInfo.Uses` we will get the label for
// the generic field instead.
func trackInstantiatedStructFields(tw *trap.Writer, tp, origintp *types.Named) {
if tp == origintp {
return
}
if instantiatedStruct, ok := tp.Underlying().(*types.Struct); ok {
genericStruct, ok2 := origintp.Underlying().(*types.Struct)
if !ok2 {
log.Fatalf(
"Error: underlying type of instantiated type is a struct but underlying type of generic type is %s",
origintp.Underlying())
}
if instantiatedStruct.NumFields() != genericStruct.NumFields() {
log.Fatalf(
"Error: instantiated struct %s has different number of fields than the generic version %s (%d != %d)",
instantiatedStruct, genericStruct, instantiatedStruct.NumFields(), genericStruct.NumFields())
}
for i := 0; i < instantiatedStruct.NumFields(); i++ {
tw.ObjectsOverride[instantiatedStruct.Field(i)] = genericStruct.Field(i)
}
}
}
func getTypeParamParentLabel(tw *trap.Writer, tp *types.TypeParam) trap.Label {
parent, exists := typeParamParent[tp]
if !exists {
log.Fatalf("Parent of type parameter does not exist: %s %s", tp.String(), tp.Constraint().String())
}
parentlbl, _ := tw.Labeler.ScopedObjectID(parent, func() trap.Label {
log.Fatalf("getTypeLabel() called for parent of type parameter %s", tp.String())
return trap.InvalidLabel
})
return parentlbl
}
func setTypeParamParent(tp *types.TypeParam, newobj types.Object) {
obj, exists := typeParamParent[tp]
if !exists {
typeParamParent[tp] = newobj
} else if newobj != obj {
log.Fatalf("Parent of type parameter '%s %s' being set to a different value: '%s' vs '%s'", tp.String(), tp.Constraint().String(), obj, newobj)
}
}

Просмотреть файл

@ -129,7 +129,7 @@ func (l *Labeler) LookupObjectID(object types.Object, typelbl Label) (Label, boo
} }
label = InvalidLabel label = InvalidLabel
} else { } else {
label, exists = l.ScopedObjectID(object, typelbl) label, exists = l.ScopedObjectID(object, func() Label { return typelbl })
} }
} }
return label, exists return label, exists
@ -144,7 +144,7 @@ func (l *Labeler) LookupObjectID(object types.Object, typelbl Label) (Label, boo
// detected, we must construct a special label, as the variable can be reached // detected, we must construct a special label, as the variable can be reached
// from several files via the method. As the type label is required to construct // from several files via the method. As the type label is required to construct
// the receiver object id, it is also required here. // the receiver object id, it is also required here.
func (l *Labeler) ScopedObjectID(object types.Object, typelbl Label) (Label, bool) { func (l *Labeler) ScopedObjectID(object types.Object, getTypeLabel func() Label) (Label, bool) {
label, exists := l.objectLabels[object] label, exists := l.objectLabels[object]
if !exists { if !exists {
scope := object.Parent() scope := object.Parent()
@ -154,19 +154,17 @@ func (l *Labeler) ScopedObjectID(object types.Object, typelbl Label) (Label, boo
} else { } else {
// associate method receiver objects to special keys, because those can be // associate method receiver objects to special keys, because those can be
// referenced from other files via their method // referenced from other files via their method
isRecv := false meth := findMethodWithGivenReceiver(object.Type(), object)
if namedType, ok := object.Type().(*types.Named); ok { if meth == nil {
for i := 0; i < namedType.NumMethods(); i++ { if pointerType, ok := object.Type().(*types.Pointer); ok {
meth := namedType.Method(i) meth = findMethodWithGivenReceiver(pointerType.Elem(), object)
if object == meth.Type().(*types.Signature).Recv() {
isRecv = true
methlbl, _ := l.MethodID(meth, typelbl)
label, _ = l.ReceiverObjectID(object, methlbl)
}
} }
} }
if !isRecv { if meth != nil {
methlbl, _ := l.MethodID(meth, getTypeLabel())
label, _ = l.ReceiverObjectID(object, methlbl)
} else {
scopeLbl := l.ScopeID(scope, object.Pkg()) scopeLbl := l.ScopeID(scope, object.Pkg())
label = l.GlobalID(fmt.Sprintf("{%v},%s;object", scopeLbl, object.Name())) label = l.GlobalID(fmt.Sprintf("{%v},%s;object", scopeLbl, object.Name()))
} }
@ -176,6 +174,18 @@ func (l *Labeler) ScopedObjectID(object types.Object, typelbl Label) (Label, boo
return label, exists return label, exists
} }
func findMethodWithGivenReceiver(tp types.Type, object types.Object) *types.Func {
if namedType, ok := tp.(*types.Named); ok {
for i := 0; i < namedType.NumMethods(); i++ {
meth := namedType.Method(i)
if object == meth.Type().(*types.Signature).Recv() {
return meth
}
}
}
return nil
}
// ReceiverObjectID associates a label with the given object and returns it, together with a flag indicating whether // ReceiverObjectID associates a label with the given object and returns it, together with a flag indicating whether
// the object already had a label associated with it; the object must be the receiver of `methlbl`, since that label // the object already had a label associated with it; the object must be the receiver of `methlbl`, since that label
// is used to construct the label of the object // is used to construct the label of the object
@ -210,12 +220,12 @@ func (l *Labeler) FieldID(field *types.Var, idx int, structlbl Label) (Label, bo
} }
// MethodID associates a label with the given method and returns it, together with a flag indicating whether // MethodID associates a label with the given method and returns it, together with a flag indicating whether
// the method already had a label associated with it; the method must belong to `recvlbl`, since that label // the method already had a label associated with it; the method must belong to `recvtyplbl`, since that label
// is used to construct the label of the method // is used to construct the label of the method
func (l *Labeler) MethodID(method types.Object, recvlbl Label) (Label, bool) { func (l *Labeler) MethodID(method types.Object, recvtyplbl Label) (Label, bool) {
label, exists := l.objectLabels[method] label, exists := l.objectLabels[method]
if !exists { if !exists {
label = l.GlobalID(fmt.Sprintf("{%v},%s;method", recvlbl, method.Name())) label = l.GlobalID(fmt.Sprintf("{%v},%s;method", recvtyplbl, method.Name()))
l.objectLabels[method] = label l.objectLabels[method] = label
} }
return label, exists return label, exists

Просмотреть файл

@ -5,6 +5,7 @@ import (
"compress/gzip" "compress/gzip"
"errors" "errors"
"fmt" "fmt"
"go/ast"
"go/types" "go/types"
"io/ioutil" "io/ioutil"
"os" "os"
@ -17,13 +18,15 @@ import (
// A Writer provides methods for writing data to a TRAP file // A Writer provides methods for writing data to a TRAP file
type Writer struct { type Writer struct {
zip *gzip.Writer zip *gzip.Writer
w *bufio.Writer w *bufio.Writer
file *os.File file *os.File
Labeler *Labeler Labeler *Labeler
path string path string
trapFilePath string trapFilePath string
Package *packages.Package Package *packages.Package
TypesOverride map[ast.Expr]types.Type
ObjectsOverride map[types.Object]types.Object
} }
func FileFor(path string) (string, error) { func FileFor(path string) (string, error) {
@ -61,6 +64,8 @@ func NewWriter(path string, pkg *packages.Package) (*Writer, error) {
path, path,
trapFilePath, trapFilePath,
pkg, pkg,
make(map[ast.Expr]types.Type),
make(map[types.Object]types.Object),
} }
tw.Labeler = newLabeler(tw) tw.Labeler = newLabeler(tw)
return tw, nil return tw, nil
@ -104,11 +109,22 @@ func (tw *Writer) Close() error {
// ForEachObject iterates over all objects labeled by this labeler, and invokes // ForEachObject iterates over all objects labeled by this labeler, and invokes
// the provided callback with a writer for the trap file, the object, and its // the provided callback with a writer for the trap file, the object, and its
// label. // label. It returns true if any extra objects were labeled and false otherwise.
func (tw *Writer) ForEachObject(cb func(*Writer, types.Object, Label)) { func (tw *Writer) ForEachObject(cb func(*Writer, types.Object, Label)) bool {
for object, lbl := range tw.Labeler.objectLabels { // copy the objects into an array so that our behaviour is deterministic even
cb(tw, object, lbl) // if `cb` adds any new objects
i := 0
objects := make([]types.Object, len(tw.Labeler.objectLabels))
for k := range tw.Labeler.objectLabels {
objects[i] = k
i++
} }
for _, object := range objects {
cb(tw, object, tw.Labeler.objectLabels[object])
}
return len(tw.Labeler.objectLabels) != len(objects)
} }
const max_strlen = 1024 * 1024 const max_strlen = 1024 * 1024

2
go.mod
Просмотреть файл

@ -1,6 +1,6 @@
module github.com/github/codeql-go module github.com/github/codeql-go
go 1.17 go 1.18
require ( require (
golang.org/x/mod v0.5.0 golang.org/x/mod v0.5.0

Просмотреть файл

@ -0,0 +1,4 @@
---
category: feature
---
* Go 1.18 generics are now extracted and can be explored using the new CodeQL classes `TypeParamDecl`, `GenericFunctionInstantiationExpr`, `GenericTypeInstantiationExpr`, `TypeSetTerm`, and `TypeSetLiteralType`, as well as using new predicates defined on the existing `InterfaceType`. Class- and predicate-level documentation can be found in the [Go CodeQL library reference](https://codeql.github.com/codeql-standard-libraries/go/).

Просмотреть файл

@ -157,6 +157,8 @@ constvalues(unique int expr: @expr ref, string value: string ref, string exact:
fields(unique int id: @field, int parent: @fieldparent ref, int idx: int 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] #keyset[parent, idx]
stmts(unique int id: @stmt, int kind: int ref, int parent: @stmtparent ref, int idx: int ref); stmts(unique int id: @stmt, int kind: int ref, int parent: @stmtparent ref, int idx: int ref);
@ -225,16 +227,20 @@ has_ellipsis(int id: @callorconversionexpr ref);
variadic(int id: @signaturetype 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; @container = @file | @folder;
@locatable = @xmllocatable | @node | @localscope; @locatable = @xmllocatable | @node | @localscope;
@node = @documentable | @exprparent | @modexprparent | @fieldparent | @stmtparent | @declparent | @scopenode @node = @documentable | @exprparent | @modexprparent | @fieldparent | @stmtparent | @declparent | @typeparamdeclparent
| @comment_group | @comment; | @scopenode | @comment_group | @comment;
@documentable = @file | @field | @spec | @gendecl | @funcdecl | @modexpr; @documentable = @file | @field | @typeparamdecl | @spec | @gendecl | @funcdecl | @modexpr;
@exprparent = @funcdef | @file | @expr | @field | @stmt | @decl | @spec; @exprparent = @funcdef | @file | @expr | @field | @stmt | @decl | @typeparamdecl | @spec;
@modexprparent = @file | @modexpr; @modexprparent = @file | @modexpr;
@ -244,6 +250,8 @@ variadic(int id: @signaturetype ref);
@declparent = @file | @declstmt; @declparent = @file | @declstmt;
@typeparamdeclparent = @funcdecl | @typespec;
@funcdef = @funclit | @funcdecl; @funcdef = @funclit | @funcdecl;
@scopenode = @file | @functypeexpr | @blockstmt | @ifstmt | @caseclause | @switchstmt | @commclause | @loopstmt; @scopenode = @file | @functypeexpr | @blockstmt | @ifstmt | @caseclause | @switchstmt | @commclause | @loopstmt;
@ -270,46 +278,49 @@ case @expr.kind of
| 10 = @parenexpr | 10 = @parenexpr
| 11 = @selectorexpr | 11 = @selectorexpr
| 12 = @indexexpr | 12 = @indexexpr
| 13 = @sliceexpr | 13 = @genericfunctioninstantiationexpr
| 14 = @typeassertexpr | 14 = @generictypeinstantiationexpr
| 15 = @callorconversionexpr | 15 = @sliceexpr
| 16 = @starexpr | 16 = @typeassertexpr
| 17 = @keyvalueexpr | 17 = @callorconversionexpr
| 18 = @arraytypeexpr | 18 = @starexpr
| 19 = @structtypeexpr | 19 = @keyvalueexpr
| 20 = @functypeexpr | 20 = @arraytypeexpr
| 21 = @interfacetypeexpr | 21 = @structtypeexpr
| 22 = @maptypeexpr | 22 = @functypeexpr
| 23 = @plusexpr | 23 = @interfacetypeexpr
| 24 = @minusexpr | 24 = @maptypeexpr
| 25 = @notexpr | 25 = @typesetliteralexpr
| 26 = @complementexpr | 26 = @plusexpr
| 27 = @derefexpr | 27 = @minusexpr
| 28 = @addressexpr | 28 = @notexpr
| 29 = @arrowexpr | 29 = @complementexpr
| 30 = @lorexpr | 30 = @derefexpr
| 31 = @landexpr | 31 = @addressexpr
| 32 = @eqlexpr | 32 = @arrowexpr
| 33 = @neqexpr | 33 = @lorexpr
| 34 = @lssexpr | 34 = @landexpr
| 35 = @leqexpr | 35 = @eqlexpr
| 36 = @gtrexpr | 36 = @neqexpr
| 37 = @geqexpr | 37 = @lssexpr
| 38 = @addexpr | 38 = @leqexpr
| 39 = @subexpr | 39 = @gtrexpr
| 40 = @orexpr | 40 = @geqexpr
| 41 = @xorexpr | 41 = @addexpr
| 42 = @mulexpr | 42 = @subexpr
| 43 = @quoexpr | 43 = @orexpr
| 44 = @remexpr | 44 = @xorexpr
| 45 = @shlexpr | 45 = @mulexpr
| 46 = @shrexpr | 46 = @quoexpr
| 47 = @andexpr | 47 = @remexpr
| 48 = @andnotexpr | 48 = @shlexpr
| 49 = @sendchantypeexpr | 49 = @shrexpr
| 50 = @recvchantypeexpr | 50 = @andexpr
| 51 = @sendrcvchantypeexpr | 51 = @andnotexpr
| 52 = @errorexpr; | 52 = @sendchantypeexpr
| 53 = @recvchantypeexpr
| 54 = @sendrcvchantypeexpr
| 55 = @errorexpr;
@basiclit = @intlit | @floatlit | @imaglit | @charlit | @stringlit; @basiclit = @intlit | @floatlit | @imaglit | @charlit | @stringlit;
@ -430,6 +441,8 @@ case @object.kind of
| 7 = @builtinfunctionobject | 7 = @builtinfunctionobject
| 8 = @labelobject; | 8 = @labelobject;
@typeparamparentobject = @decltypeobject | @declfunctionobject;
@declobject = @decltypeobject | @declconstobject | @declvarobject | @declfunctionobject; @declobject = @decltypeobject | @declconstobject | @declvarobject | @declfunctionobject;
@builtinobject = @builtintypeobject | @builtinconstobject | @builtinfunctionobject; @builtinobject = @builtintypeobject | @builtinconstobject | @builtinfunctionobject;
@ -476,18 +489,20 @@ case @type.kind of
| 23 = @complexliteraltype | 23 = @complexliteraltype
| 24 = @stringliteraltype | 24 = @stringliteraltype
| 25 = @nilliteraltype | 25 = @nilliteraltype
| 26 = @arraytype | 26 = @typeparamtype
| 27 = @slicetype | 27 = @arraytype
| 28 = @structtype | 28 = @slicetype
| 29 = @pointertype | 29 = @structtype
| 30 = @interfacetype | 30 = @pointertype
| 31 = @tupletype | 31 = @interfacetype
| 32 = @signaturetype | 32 = @tupletype
| 33 = @maptype | 33 = @signaturetype
| 34 = @sendchantype | 34 = @maptype
| 35 = @recvchantype | 35 = @sendchantype
| 36 = @sendrcvchantype | 36 = @recvchantype
| 37 = @namedtype; | 37 = @sendrcvchantype
| 38 = @namedtype
| 39 = @typesetliteraltype;
@basictype = @booltype | @numerictype | @stringtype | @literaltype | @invalidtype | @unsafepointertype; @basictype = @booltype | @numerictype | @stringtype | @literaltype | @invalidtype | @unsafepointertype;
@ -510,7 +525,8 @@ case @type.kind of
@literaltype = @boolliteraltype | @intliteraltype | @runeliteraltype | @floatliteraltype | @complexliteraltype @literaltype = @boolliteraltype | @intliteraltype | @runeliteraltype | @floatliteraltype | @complexliteraltype
| @stringliteraltype | @nilliteraltype; | @stringliteraltype | @nilliteraltype;
@compositetype = @containertype | @structtype | @pointertype | @interfacetype | @tupletype | @signaturetype | @namedtype; @compositetype = @typeparamtype | @containertype | @structtype | @pointertype | @interfacetype | @tupletype
| @signaturetype | @namedtype | @typesetliteraltype;
@containertype = @arraytype | @slicetype | @maptype | @chantype; @containertype = @arraytype | @slicetype | @maptype | @chantype;

Просмотреть файл

@ -216,6 +216,24 @@ class FieldParent extends @fieldparent, AstNode {
int getNumFields() { result = count(getAField()) } int getNumFields() { result = count(getAField()) }
} }
/**
* An AST node whose children include type parameter declarations.
*/
class TypeParamDeclParent extends @typeparamdeclparent, AstNode {
/**
* Gets the `i`th type parameter declaration of this node.
*
* Note that the precise indices of type parameters are considered an implementation detail
* and are subject to change without notice.
*/
TypeParamDecl getTypeParameterDecl(int i) { typeparamdecls(result, this, i) }
/**
* Gets a child field of this node in the AST.
*/
TypeParamDecl getATypeParameterDecl() { result = this.getTypeParameterDecl(_) }
}
/** /**
* An AST node which may induce a scope. * An AST node which may induce a scope.
* *

Просмотреть файл

@ -146,7 +146,7 @@ class FuncDef extends @funcdef, StmtParent, ExprParent {
/** /**
* A function declaration. * A function declaration.
*/ */
class FuncDecl extends @funcdecl, Decl, Documentable, FuncDef { class FuncDecl extends @funcdecl, Decl, Documentable, FuncDef, TypeParamDeclParent {
/** Gets the identifier denoting the name of this function. */ /** Gets the identifier denoting the name of this function. */
Ident getNameExpr() { result = this.getChildExpr(0) } Ident getNameExpr() { result = this.getChildExpr(0) }
@ -376,7 +376,7 @@ class ValueSpec extends @valuespec, Spec {
* ) * )
* ``` * ```
*/ */
class TypeSpec extends @typespec, Spec { class TypeSpec extends @typespec, Spec, TypeParamDeclParent {
/** Gets the identifier denoting the name of the declared type. */ /** Gets the identifier denoting the name of the declared type. */
Ident getNameExpr() { result = this.getChildExpr(0) } Ident getNameExpr() { result = this.getChildExpr(0) }
@ -562,6 +562,57 @@ class ResultVariableDecl extends ParameterOrResultDecl {
override string getAPrimaryQlClass() { result = "ResultVariableDecl" } override string getAPrimaryQlClass() { result = "ResultVariableDecl" }
} }
/**
* A type parameter declaration in a type specification.
*/
class TypeParamDecl extends @typeparamdecl, Documentable, ExprParent {
TypeParamDecl() { typeparamdecls(this, _, _) }
/**
* Gets the expression representing the type constraint of the type
* parameters in this declaration.
*
* If you want the type constraint type itself then use `getTypeConstraint`,
* as that wraps type set literals with implicit interface types.
*/
Expr getTypeConstraintExpr() { result = this.getChildExpr(0) }
/**
* Gets the type constraint of the type parameters in this declaration.
*
* If the type constraint is a type set literal then it will be wrapped
* with an implicit interface type.
*/
Type getTypeConstraint() {
exists(Type t | t = this.getTypeConstraintExpr().getType() |
if t instanceof TypeSetLiteralType
then result = t.(TypeSetLiteralType).getInterfaceType()
else result = t
)
}
/**
* Gets the expression representing the name of the `i`th type parameter
* in this declaration (0-based).
*/
Expr getNameExpr(int i) {
i >= 0 and
result = this.getChildExpr(i + 1)
}
/**
* Gets the `i`th type parameter type in this declaration (0-based).
*/
TypeParamType getTypeParamType(int i) {
i >= 0 and
result = this.getNameExpr(i).getType()
}
override string toString() { result = "type parameter declaration" }
override string getAPrimaryQlClass() { result = "TypeParamDecl" }
}
/** /**
* A method or embedding specification in an interface type expression. * A method or embedding specification in an interface type expression.
*/ */

Просмотреть файл

@ -626,14 +626,21 @@ class PromotedSelector extends SelectorExpr {
/** /**
* An index expression, that is, a base expression followed by an index. * An index expression, that is, a base expression followed by an index.
* Expressions which represent generic type instantiations have been
* excluded.
* *
* Examples: * Examples:
* *
* ```go * ```go
* a[i] * array[i]
* arrayptr[i]
* slice[i]
* map[key]
* ``` * ```
*/ */
class IndexExpr extends @indexexpr, Expr { class IndexExpr extends @indexexpr, Expr {
IndexExpr() { not isTypeExprBottomUp(this.getChildExpr(0)) }
/** Gets the base of this index expression. */ /** Gets the base of this index expression. */
Expr getBase() { result = this.getChildExpr(0) } Expr getBase() { result = this.getChildExpr(0) }
@ -647,6 +654,68 @@ class IndexExpr extends @indexexpr, Expr {
override string getAPrimaryQlClass() { result = "IndexExpr" } override string getAPrimaryQlClass() { result = "IndexExpr" }
} }
/**
* A generic function instantiation, that is, a base expression that represents
* a generic function, followed by a list of type arguments.
*
* Examples:
*
* ```go
* genericfunction[type]
* genericfunction[type1, type2]
* ```
*/
class GenericFunctionInstantiationExpr extends @genericfunctioninstantiationexpr, Expr {
/** Gets the generic function expression. */
Expr getBase() { result = this.getChildExpr(0) }
/** Gets the `i`th type argument. */
Expr getTypeArgument(int i) {
i >= 0 and
result = this.getChildExpr(i + 1)
}
override predicate mayHaveOwnSideEffects() { any() }
override string toString() { result = "generic function instantiation expression" }
override string getAPrimaryQlClass() { result = "GenericFunctionInstantiationExpr" }
}
/**
* A generic type instantiation, that is, a base expression that is a generic
* type followed by a list of type arguments.
*
* Examples:
*
* ```go
* generictype[type]
* generictype[type1, type2]
* ```
*/
class GenericTypeInstantiationExpr extends Expr {
GenericTypeInstantiationExpr() {
this instanceof @generictypeinstantiationexpr
or
this instanceof @indexexpr and isTypeExprBottomUp(this.getChildExpr(0))
}
/** Gets the generic type expression. */
Expr getBase() { result = this.getChildExpr(0) }
/** Gets the `i`th type argument. */
Expr getTypeArgument(int i) {
i >= 0 and
result = this.getChildExpr(i + 1)
}
override predicate mayHaveOwnSideEffects() { any() }
override string toString() { result = "generic type instantiation expression" }
override string getAPrimaryQlClass() { result = "GenericTypeInstantiationExpr" }
}
/** /**
* A slice expression, that is, a base expression followed by slice indices. * A slice expression, that is, a base expression followed by slice indices.
* *
@ -770,7 +839,11 @@ class CallExpr extends CallOrConversionExpr {
} }
/** Gets the expression representing the function being called. */ /** Gets the expression representing the function being called. */
Expr getCalleeExpr() { result = this.getChildExpr(0) } Expr getCalleeExpr() {
if this.getChildExpr(0) instanceof GenericFunctionInstantiationExpr
then result = this.getChildExpr(0).(GenericFunctionInstantiationExpr).getBase()
else result = this.getChildExpr(0)
}
/** Gets the `i`th argument expression of this call (0-based). */ /** Gets the `i`th argument expression of this call (0-based). */
Expr getArgument(int i) { Expr getArgument(int i) {
@ -995,6 +1068,22 @@ class MapTypeExpr extends @maptypeexpr, TypeExpr {
override string getAPrimaryQlClass() { result = "MapTypeExpr" } override string getAPrimaryQlClass() { result = "MapTypeExpr" }
} }
/**
* An expression representing a type set literal.
*
* Examples:
*
* ```go
* ~string
* int64 | float64
* ```
*/
class TypeSetLiteralExpr extends @typesetliteralexpr, TypeExpr {
override string toString() { result = "type set literal" }
override string getAPrimaryQlClass() { result = "TypeSetLiteralExpr" }
}
/** /**
* An expression with a (unary or binary) operator. * An expression with a (unary or binary) operator.
* *
@ -1956,15 +2045,30 @@ class LabelName extends Name {
* a bottom-up analysis. In such cases, `isTypeExprTopDown` below is useful. * a bottom-up analysis. In such cases, `isTypeExprTopDown` below is useful.
*/ */
private predicate isTypeExprBottomUp(Expr e) { private predicate isTypeExprBottomUp(Expr e) {
e instanceof TypeName or e instanceof TypeName
e instanceof @arraytypeexpr or or
e instanceof @structtypeexpr or e instanceof @arraytypeexpr
e instanceof @functypeexpr or or
e instanceof @interfacetypeexpr or e instanceof @structtypeexpr
e instanceof @maptypeexpr or or
e instanceof @chantypeexpr or e instanceof @functypeexpr
isTypeExprBottomUp(e.(ParenExpr).getExpr()) or or
isTypeExprBottomUp(e.(StarExpr).getBase()) or e instanceof @interfacetypeexpr
or
e instanceof @maptypeexpr
or
e instanceof @chantypeexpr
or
e instanceof @typesetliteralexpr
or
e instanceof @generictypeinstantiationexpr
or
e instanceof @indexexpr and isTypeExprBottomUp(e.getChildExpr(0))
or
isTypeExprBottomUp(e.(ParenExpr).getExpr())
or
isTypeExprBottomUp(e.(StarExpr).getBase())
or
isTypeExprBottomUp(e.(Ellipsis).getOperand()) isTypeExprBottomUp(e.(Ellipsis).getOperand())
} }
@ -1989,6 +2093,10 @@ private predicate isTypeExprTopDown(Expr e) {
or or
e = any(ParameterDecl pd).getTypeExpr() e = any(ParameterDecl pd).getTypeExpr()
or or
e = any(TypeParamDecl tpd).getTypeConstraintExpr()
or
e = any(TypeParamDecl tpd).getNameExpr(_)
or
e = any(ReceiverDecl rd).getTypeExpr() e = any(ReceiverDecl rd).getTypeExpr()
or or
e = any(ResultVariableDecl rvd).getTypeExpr() e = any(ResultVariableDecl rvd).getTypeExpr()
@ -2005,6 +2113,10 @@ private predicate isTypeExprTopDown(Expr e) {
or or
e = any(TypeSpec s).getTypeExpr() e = any(TypeSpec s).getTypeExpr()
or or
e = any(GenericTypeInstantiationExpr gtie).getBase()
or
e = any(GenericTypeInstantiationExpr gtie).getTypeArgument(_)
or
e = any(TypeSwitchStmt s).getACase().getExpr(_) and e = any(TypeSwitchStmt s).getACase().getExpr(_) and
// special case: `nil` is allowed in a type case but isn't a type // special case: `nil` is allowed in a type case but isn't a type
not e = Builtin::nil().getAReference() not e = Builtin::nil().getAReference()

Просмотреть файл

@ -66,18 +66,75 @@ class Type extends @type {
/** /**
* Holds if this type implements interface `i`, that is, the method set of `i` * Holds if this type implements interface `i`, that is, the method set of `i`
* is contained in the method set of this type. * is contained in the method set of this type and any type restrictions are
* satisfied.
*/ */
predicate implements(InterfaceType i) { predicate implements(InterfaceType i) {
isEmptyInterface(i) if i = any(ComparableType comparable).getUnderlyingType()
or then this.implementsComparable()
this.hasMethod(getExampleMethodName(i), _) and else this.implementsNotComparable(i)
forall(string m, SignatureType t | i.hasMethod(m, t) | this.hasMethod(m, t)) }
/**
* Holds if this type implements interface `i`, which is not the underlying
* type of `comparable`. This predicate is needed to avoid non-monotonic
* recursion.
*/
private predicate implementsNotComparable(InterfaceType i) {
(
forall(TypeSetLiteralType tslit | tslit = i.getAnEmbeddedTypeSetLiteral() |
tslit.includesType(this)
) and
(
hasNoMethods(i)
or
this.hasMethod(getExampleMethodName(i), _) and
forall(string m, SignatureType t | i.hasMethod(m, t) | this.hasMethod(m, t))
)
)
}
/**
* Holds if this type implements `comparable`. This includes being
* `comparable` itself, or the underlying type of `comparable`.
*/
predicate implementsComparable() {
exists(Type u | u = this.getUnderlyingType() |
// Note that BasicType includes Invalidtype
u instanceof BasicType
or
u instanceof PointerType
or
u instanceof ChanType
or
u instanceof StructType and
forall(Type fieldtp | u.(StructType).hasField(_, fieldtp) | fieldtp.implementsComparable())
or
u instanceof ArrayType and u.(ArrayType).getElementType().implementsComparable()
or
exists(InterfaceType uif | uif = u |
not uif instanceof BasicInterfaceType and
if exists(uif.getAnEmbeddedTypeSetLiteral())
then
// All types in the intersection of all the embedded type set
// literals must implement comparable.
forall(Type intersectionType |
intersectionType = uif.getAnEmbeddedTypeSetLiteral().getATerm().getType() and
forall(TypeSetLiteralType tslit | tslit = uif.getAnEmbeddedTypeSetLiteral() |
intersectionType = tslit.getATerm().getType()
)
|
intersectionType.implementsComparable()
)
else uif.isOrEmbedsComparable()
)
)
} }
/** /**
* Holds if this type implements an interface that has the qualified name `pkg.name`, * Holds if this type implements an interface that has the qualified name `pkg.name`,
* that is, the method set of `pkg.name` is contained in the method set of this type. * that is, the method set of `pkg.name` is contained in the method set of this type
* and any type restrictions are satisfied.
*/ */
predicate implements(string pkg, string name) { predicate implements(string pkg, string name) {
exists(Type t | t.hasQualifiedName(pkg, name) | this.implements(t.getUnderlyingType())) exists(Type t | t.hasQualifiedName(pkg, name) | this.implements(t.getUnderlyingType()))
@ -306,6 +363,26 @@ class NilLiteralType extends @nilliteraltype, LiteralType {
/** A composite type, that is, not a basic type. */ /** A composite type, that is, not a basic type. */
class CompositeType extends @compositetype, Type { } class CompositeType extends @compositetype, Type { }
/** A type that comes from a type parameter. */
class TypeParamType extends @typeparamtype, CompositeType {
/** Gets the name of this type parameter type. */
string getParamName() { typeparam(this, result, _, _, _) }
/** Gets the constraint of this type parameter type. */
Type getConstraint() { typeparam(this, _, result, _, _) }
override InterfaceType getUnderlyingType() { result = this.getConstraint().getUnderlyingType() }
override string pp() { result = this.getParamName() }
/**
* Gets a pretty-printed representation of this type including its constraint.
*/
string ppWithConstraint() { result = this.getParamName() + " " + this.getConstraint().pp() }
override string toString() { result = "type parameter type" }
}
/** An array type. */ /** An array type. */
class ArrayType extends @arraytype, CompositeType { class ArrayType extends @arraytype, CompositeType {
/** Gets the element type of this array type. */ /** Gets the element type of this array type. */
@ -532,33 +609,269 @@ class PointerType extends @pointertype, CompositeType {
override string toString() { result = "pointer type" } override string toString() { result = "pointer type" }
} }
/** An interface type. */ private newtype TTypeSetTerm =
class InterfaceType extends @interfacetype, CompositeType { MkTypeSetTerm(TypeSetLiteralType tslit, int index) { component_types(tslit, index, _, _) }
/** Gets the type of method `name` of this interface type. */
Type getMethodType(string name) { component_types(this, _, name, result) }
override predicate hasMethod(string m, SignatureType t) { t = this.getMethodType(m) } /**
* A term in a type set literal.
*
* Examples:
* ```go
* int
* ~string
* ```
*/
class TypeSetTerm extends TTypeSetTerm {
boolean tilde;
Type tp;
TypeSetTerm() {
exists(TypeSetLiteralType tslit, int index |
this = MkTypeSetTerm(tslit, index) and
(
component_types(tslit, index, "", tp) and
tilde = false
or
component_types(tslit, index, "~", tp) and
tilde = true
)
)
}
/**
* Holds if this term has a tilde in front of it.
*
* A tilde is used to indicate that the term refers to all types with a given
* underlying type.
*/
predicate hasTilde() { tilde = true }
/** Gets the type of this term. */
Type getType() { result = tp }
/** Holds if `t` is in the type set of this term. */
predicate includesType(Type t) { if tilde = false then t = tp else t.getUnderlyingType() = tp }
/** Gets a pretty-printed representation of this term. */
string pp() {
exists(string tildeStr | if tilde = true then tildeStr = "~" else tildeStr = "" |
result = tildeStr + tp.pp()
)
}
/** Gets a textual representation of this element. */
string toString() { result = "type set term" }
}
private TypeSetTerm getIntersection(TypeSetTerm term1, TypeSetTerm term2) {
term1.getType() = term2.getType() and
if term1.hasTilde() then result = term2 else result = term1
}
/**
* Gets a term in the intersection of type-set literals `a` and `b`.
*/
TypeSetTerm getTermInIntersection(TypeSetLiteralType a, TypeSetLiteralType b) {
result = getIntersection(a.getATerm(), b.getATerm())
}
/**
* A type set literal type, used when declaring a non-basic interface. May be a
* single term, consisting of either a type or a tilde followed by a type, or a
* union of terms.
*
*
* Examples:
*
* ```go
* int
* ~string
* int | ~string
* ```
*/
class TypeSetLiteralType extends @typesetliteraltype, CompositeType {
/** Gets the `i`th term in this type set literal. */
TypeSetTerm getTerm(int i) { result = MkTypeSetTerm(this, i) }
/** Gets a term in this type set literal. */
TypeSetTerm getATerm() { result = this.getTerm(_) }
/** Holds if `t` is in the type set of this type set literal. */
predicate includesType(Type t) { this.getATerm().includesType(t) }
/**
* Gets the interface type of which this type-set literal is the only
* element, if it exists.
*
* It exists if it has been explicitly defined, as in
* `interface { int64 | uint64 }`, or if it has been implicitly created by
* using the type set literal directly as the bound in a type parameter
* declaration, as in `[T int64 | uint64]`.
*/
InterfaceType getInterfaceType() {
this = result.getDirectlyEmbeddedTypeSetLiteral(0) and
not exists(result.getDirectlyEmbeddedTypeSetLiteral(1)) and
hasNoMethods(result) and
not exists(result.getADirectlyEmbeddedInterface())
}
language[monotonicAggregates] language[monotonicAggregates]
override string pp() { override string pp() {
exists(string meth | result = concat(TypeSetTerm t, int i | t = this.getTerm(i) | t.pp(), " | " order by i)
}
override string toString() { result = "type set literal type" }
}
/** An interface type. */
class InterfaceType extends @interfacetype, CompositeType {
/** Gets the type of method `name` of this interface type. */
Type getMethodType(string name) {
// Note that negative indices correspond to embedded interfaces and type
// set literals.
exists(int i | i >= 0 | component_types(this, i, name, result))
}
override predicate hasMethod(string m, SignatureType t) { t = this.getMethodType(m) }
/**
* Holds if `tp` is a directly embedded type with index `index`.
*
* `tp` (or its underlying type) is either a type set literal type or an
* interface type.
*/
private predicate hasDirectlyEmbeddedType(int index, Type tp) {
index >= 0 and component_types(this, -(index + 1), _, tp)
}
/**
* Gets a type whose underlying type is an interface that is directly
* embedded into this interface.
*
* Note that the methods of the embedded interface are already considered
* as part of the method set of this interface.
*/
Type getADirectlyEmbeddedInterface() {
this.hasDirectlyEmbeddedType(_, result) and result.getUnderlyingType() instanceof InterfaceType
}
/**
* Gets a type whose underlying type is an interface that is embedded into
* this interface.
*
* Note that the methods of the embedded interface are already considered
* as part of the method set of this interface.
*/
Type getAnEmbeddedInterface() {
result = this.getADirectlyEmbeddedInterface() or
result =
this.getADirectlyEmbeddedInterface()
.getUnderlyingType()
.(InterfaceType)
.getAnEmbeddedInterface()
}
/**
* Holds if this interface type is (the underlying type of) `comparable`, or
* it embeds `comparable`.
*/
predicate isOrEmbedsComparable() {
this.getAnEmbeddedInterface() instanceof ComparableType or
this = any(ComparableType comparable).getUnderlyingType()
}
/**
* Gets the type set literal with index `index` from the definition of this
* interface type.
*
* Note that the indexes are not contiguous.
*/
TypeSetLiteralType getDirectlyEmbeddedTypeSetLiteral(int index) {
hasDirectlyEmbeddedType(index, result)
}
/**
* Gets a type set literal of this interface type.
*
* This includes type set literals of embedded interfaces.
*/
TypeSetLiteralType getAnEmbeddedTypeSetLiteral() {
result = this.getDirectlyEmbeddedTypeSetLiteral(_) or
result =
getADirectlyEmbeddedInterface()
.getUnderlyingType()
.(InterfaceType)
.getAnEmbeddedTypeSetLiteral()
}
language[monotonicAggregates]
override string pp() {
exists(string comp, string sep1, string ts, string sep2, string meth |
// Note that the interface type underlying `comparable` will be printed
// as `interface { comparable }`, which is not entirely accurate, but
// also better than anything else I can think of.
(if this.isOrEmbedsComparable() then comp = " comparable" else comp = "") and
ts =
concat(TypeSetLiteralType tslit |
tslit = this.getAnEmbeddedTypeSetLiteral()
|
" " + tslit.pp(), ";"
) and
meth = meth =
concat(string name, Type tp | concat(string name, Type tp |
tp = this.getMethodType(name) tp = this.getMethodType(name)
| |
" " + name + " " + tp.pp(), ";" order by name " " + name + " " + tp.pp(), ";" order by name
) ) and
(if comp != "" and ts != "" then sep1 = ";" else sep1 = "") and
if
(comp != "" or ts != "") and
meth != ""
then sep2 = ";"
else sep2 = ""
| |
result = "interface {" + meth + " }" result = "interface {" + comp + sep1 + ts + sep2 + meth + " }"
) )
} }
override string toString() { result = "interface type" } override string toString() { result = "interface type" }
} }
/** An empty interface type. */ // This predicate is needed for performance reasons.
class EmptyInterfaceType extends InterfaceType { pragma[noinline]
EmptyInterfaceType() { not this.hasMethod(_, _) } private predicate hasNoMethods(InterfaceType i) { not i.hasMethod(_, _) }
/**
* A basic interface type.
*
* A basic interface is an interface that does not specify any type set
* literals, and which does not embed any non-basic interfaces. The special
* interface `comparable` is not a basic interface.
*/
class BasicInterfaceType extends InterfaceType {
BasicInterfaceType() {
not exists(this.getAnEmbeddedTypeSetLiteral()) and
not this.isOrEmbedsComparable()
}
override string toString() { result = "basic interface type" }
}
/**
* An empty interface type.
*
* Note that by we have to be careful to exclude the underlying type of
* `comparable`. This is done by extending `BasicInterfaceType`.
*/
class EmptyInterfaceType extends BasicInterfaceType {
EmptyInterfaceType() { hasNoMethods(this) }
}
/**
* The predeclared `comparable` type.
*/
class ComparableType extends NamedType {
ComparableType() { this.getName() = "comparable" }
} }
/** A tuple type. */ /** A tuple type. */
@ -693,12 +1006,6 @@ class ErrorType extends Type {
ErrorType() { this.implements(Builtin::error().getType().getUnderlyingType()) } ErrorType() { this.implements(Builtin::error().getType().getUnderlyingType()) }
} }
/**
* Holds if `i` is the empty interface type, which is implemented by every type with a method set.
*/
pragma[noinline]
private predicate isEmptyInterface(InterfaceType i) { not i.hasMethod(_, _) }
/** /**
* Gets the name of a method in the method set of `i`. * Gets the name of a method in the method set of `i`.
* *

Просмотреть файл

@ -698,6 +698,10 @@ module CFG {
not this.(SelectorExpr).getBase() instanceof ValueExpr and not this.(SelectorExpr).getBase() instanceof ValueExpr and
nd = mkExprOrSkipNode(this) and nd = mkExprOrSkipNode(this) and
cmpl = Done() cmpl = Done()
or
this instanceof GenericFunctionInstantiationExpr and
nd = MkExprNode(this) and
cmpl = Done()
} }
override predicate firstNode(ControlFlow::Node first) { first = nd } override predicate firstNode(ControlFlow::Node first) { first = nd }

Просмотреть файл

@ -443,7 +443,8 @@ module Public {
*/ */
private DataFlow::Node getACalleeSource(DataFlow::CallNode cn) { private DataFlow::Node getACalleeSource(DataFlow::CallNode cn) {
result = cn.getCalleeNode() or result = cn.getCalleeNode() or
basicLocalFlowStep(result, getACalleeSource(cn)) basicLocalFlowStep(result, getACalleeSource(cn)) or
result.asExpr() = getACalleeSource(cn).asExpr().(GenericFunctionInstantiationExpr).getBase()
} }
/** A data flow node that represents a call. */ /** A data flow node that represents a call. */

Просмотреть файл

@ -0,0 +1,33 @@
class Expr_ extends @expr {
string toString() { result = "Expr" }
}
class ExprParent_ extends @exprparent {
string toString() { result = "ExprParent" }
}
/**
* Two new kinds have been inserted such that `@sliceexpr` which used to have
* index 13 now has index 15. Another new kind has been inserted such that
* `@plusexpr` which used to have index 23 now has index 26. Entries with
* indices lower than 13 are unchanged.
*/
bindingset[old_index]
int new_index(int old_index) {
if old_index < 13
then result = old_index
else
if old_index < 23
then result = (15 - 13) + old_index
else result = (26 - 23) + old_index
}
// The schema for exprs is:
//
// exprs(unique int id: @expr,
// int kind: int ref,
// int parent: @exprparent ref,
// int idx: int ref);
from Expr_ expr, int new_kind, ExprParent_ parent, int idx, int old_kind
where exprs(expr, old_kind, parent, idx) and new_kind = new_index(old_kind)
select expr, new_kind, parent, idx

Просмотреть файл

@ -0,0 +1,547 @@
/** Auto-generated dbscheme; do not edit. */
/** 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);
/*
* 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: @namedtype 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 named: @namedtype 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);
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 = @errorexpr;
@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 = @namedtype
| 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 | @namedtype | @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;

Просмотреть файл

@ -0,0 +1,531 @@
/** Auto-generated dbscheme; do not edit. */
/** 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);
/*
* 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);
#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: @namedtype 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 named: @namedtype 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);
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);
@container = @file | @folder;
@locatable = @xmllocatable | @node | @localscope;
@node = @documentable | @exprparent | @modexprparent | @fieldparent | @stmtparent | @declparent | @scopenode
| @comment_group | @comment;
@documentable = @file | @field | @spec | @gendecl | @funcdecl | @modexpr;
@exprparent = @funcdef | @file | @expr | @field | @stmt | @decl | @spec;
@modexprparent = @file | @modexpr;
@fieldparent = @decl | @structtypeexpr | @functypeexpr | @interfacetypeexpr;
@stmtparent = @funcdef | @stmt | @decl;
@declparent = @file | @declstmt;
@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 = @sliceexpr
| 14 = @typeassertexpr
| 15 = @callorconversionexpr
| 16 = @starexpr
| 17 = @keyvalueexpr
| 18 = @arraytypeexpr
| 19 = @structtypeexpr
| 20 = @functypeexpr
| 21 = @interfacetypeexpr
| 22 = @maptypeexpr
| 23 = @plusexpr
| 24 = @minusexpr
| 25 = @notexpr
| 26 = @complementexpr
| 27 = @derefexpr
| 28 = @addressexpr
| 29 = @arrowexpr
| 30 = @lorexpr
| 31 = @landexpr
| 32 = @eqlexpr
| 33 = @neqexpr
| 34 = @lssexpr
| 35 = @leqexpr
| 36 = @gtrexpr
| 37 = @geqexpr
| 38 = @addexpr
| 39 = @subexpr
| 40 = @orexpr
| 41 = @xorexpr
| 42 = @mulexpr
| 43 = @quoexpr
| 44 = @remexpr
| 45 = @shlexpr
| 46 = @shrexpr
| 47 = @andexpr
| 48 = @andnotexpr
| 49 = @sendchantypeexpr
| 50 = @recvchantypeexpr
| 51 = @sendrcvchantypeexpr
| 52 = @errorexpr;
@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;
@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 = @arraytype
| 27 = @slicetype
| 28 = @structtype
| 29 = @pointertype
| 30 = @interfacetype
| 31 = @tupletype
| 32 = @signaturetype
| 33 = @maptype
| 34 = @sendchantype
| 35 = @recvchantype
| 36 = @sendrcvchantype
| 37 = @namedtype;
@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 = @containertype | @structtype | @pointertype | @interfacetype | @tupletype | @signaturetype | @namedtype;
@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;

Просмотреть файл

@ -0,0 +1,21 @@
class Type_ extends @type {
string toString() { result = "Type" }
}
/**
* A new kind has been inserted such that `@arraytype` which used to have index
* 26 now has index 27. Another new kind has been inserted at 39, which is the
* end of the list. Entries with lower indices are unchanged.
*/
bindingset[old_index]
int new_index(int old_index) {
if old_index < 26 then result = old_index else result = (27 - 26) + old_index
}
// The schema for types is:
//
// types(unique int id: @type,
// int kind: int ref);
from Type_ type, int new_kind, int old_kind
where types(type, old_kind) and new_kind = new_index(old_kind)
select type, new_kind

Просмотреть файл

@ -0,0 +1,4 @@
description: Add generic instantiation expressions and type parameter types
compatibility: backwards
exprs.rel: run exprs.qlo
types.rel: run types.qlo

Просмотреть файл

@ -51,16 +51,12 @@ numlines(
files( files(
unique int id: @file, unique int id: @file,
string name: string ref, string name: string ref
string simple: string ref,
string ext: string ref,
int fromSource: int ref // deprecated
); );
folders( folders(
unique int id: @folder, unique int id: @folder,
string name: string ref, string name: string ref
string simple: string ref
); );
@container = @folder | @file @container = @folder | @file

Просмотреть файл

@ -0,0 +1,8 @@
| genericFunctions.go:25:2:25:33 | generic function instantiation expression | genericFunctions.go:25:2:25:28 | GenericFunctionOneTypeParam | 0 | genericFunctions.go:25:30:25:32 | int |
| genericFunctions.go:26:2:26:36 | generic function instantiation expression | genericFunctions.go:26:2:26:28 | GenericFunctionOneTypeParam | 0 | genericFunctions.go:26:30:26:35 | string |
| genericFunctions.go:44:6:44:48 | generic function instantiation expression | genericFunctions.go:44:6:44:33 | GenericFunctionTwoTypeParams | 0 | genericFunctions.go:44:35:44:40 | string |
| genericFunctions.go:44:6:44:48 | generic function instantiation expression | genericFunctions.go:44:6:44:33 | GenericFunctionTwoTypeParams | 1 | genericFunctions.go:44:43:44:47 | int64 |
| genericFunctions.go:45:6:45:50 | generic function instantiation expression | genericFunctions.go:45:6:45:33 | GenericFunctionTwoTypeParams | 0 | genericFunctions.go:45:35:45:40 | string |
| genericFunctions.go:45:6:45:50 | generic function instantiation expression | genericFunctions.go:45:6:45:33 | GenericFunctionTwoTypeParams | 1 | genericFunctions.go:45:43:45:49 | float64 |
| genericFunctions.go:141:6:141:41 | generic function instantiation expression | genericFunctions.go:141:6:141:33 | GenericFunctionInAnotherFile | 0 | genericFunctions.go:141:35:141:40 | string |
| genericFunctions.go:146:6:146:55 | generic function instantiation expression | genericFunctions.go:146:6:146:47 | selection of GenericFunctionInAnotherPackage | 0 | genericFunctions.go:146:49:146:54 | string |

Просмотреть файл

@ -0,0 +1,4 @@
import go
from GenericFunctionInstantiationExpr e, int i
select e, e.getBase(), i, e.getTypeArgument(i)

Просмотреть файл

@ -0,0 +1,15 @@
| Edge | EdgeConstraint |
| Edge | interface { } |
| K | comparable |
| Node | NodeConstraint |
| Node | interface { } |
| S | interface { } |
| SF2 | interface { } |
| SG2 | interface { } |
| T | interface { } |
| TF1 | interface { } |
| TF2 | interface { } |
| TG1 | interface { } |
| TG2 | interface { } |
| U | interface { } |
| V | interface { int64 \| float64 } |

Просмотреть файл

@ -0,0 +1,4 @@
import go
from TypeParamType tpt
select tpt.getParamName(), tpt.getConstraint().pp()

Просмотреть файл

@ -0,0 +1,148 @@
package main
import "github.com/anotherpkg"
type T1 map[string][]string
type T2 T1
// A generic function with one type parameter
func GenericFunctionOneTypeParam[T any](t T) T {
var r T
return r
}
// A generic function with two type parameter
func GenericFunctionTwoTypeParams[K comparable, V int64 | float64](m map[K]V) V {
var s V
for _, v := range m {
s += v
}
return s
}
func generic_functions() {
// Call the generic function with one type parameter, specifying the type
GenericFunctionOneTypeParam[int](1)
GenericFunctionOneTypeParam[string]("hello")
// Call the generic function with one type parameter, without specifying the type
GenericFunctionOneTypeParam(1)
GenericFunctionOneTypeParam("hello")
// Initialize a map for the integer values
ints := map[string]int64{
"first": 34,
"second": 12,
}
// Initialize a map for the float values
floats := map[string]float64{
"first": 35.98,
"second": 26.99,
}
_ = GenericFunctionTwoTypeParams[string, int64](ints)
_ = GenericFunctionTwoTypeParams[string, float64](floats)
_ = GenericFunctionTwoTypeParams(ints)
_ = GenericFunctionTwoTypeParams(floats)
// Map read
_ = floats["first"]
// Map write
floats["first"] = -1.0
arrayVar := [5]int{1, 2, 3, 4, 5}
// Array read
_ = arrayVar[0]
// Array write
arrayVar[0] = -1
arrayPtr := &arrayVar
// Array read through pointer
_ = arrayPtr[0]
// Array write through pointer
arrayPtr[0] = -1
sliceVar := make([]int, 0, 5) // $ isVariadic
// Slice read
_ = sliceVar[0]
// Slice write
sliceVar[0] = -1
// Access a map through two type aliases
aliasedMap := T2{"key": []string{"value"}}
// Map read
_ = aliasedMap["key"]
// Map write
aliasedMap["key"][0] = "new value"
}
type GenericStruct1[T any] struct {
}
type GenericStruct2[S, T any] struct {
}
func (x GenericStruct1[TF1]) f1() TF1 {
var r TF1
return r
}
func (x *GenericStruct1[TG1]) g1() {
}
func (x GenericStruct2[SF2, TF2]) f2() {
}
func (x *GenericStruct2[SG2, TG2]) g2() {
}
func call_methods_with_generic_receiver() {
x1 := GenericStruct1[int]{}
x1.f1()
x1.g1()
x2 := GenericStruct2[string, int]{}
x2.f2()
x2.g2()
}
type Element[S any] struct {
list *List[S]
}
type List[T any] struct {
root Element[T]
}
// Len is the number of elements in the list.
func (l *List[U]) MyLen() int {
return 0
}
type NodeConstraint[Edge any] interface {
Edges() []Edge
}
type EdgeConstraint[Node any] interface {
Nodes() (from, to Node)
}
type Graph[Node NodeConstraint[Edge], Edge EdgeConstraint[Node]] struct{}
func New[Node NodeConstraint[Edge], Edge EdgeConstraint[Node]](nodes []Node) *Graph[Node, Edge] {
return nil
}
func (g *Graph[Node, Edge]) ShortestPath(from, to Node) []Edge { return []Edge{} }
func callFunctionsInAnotherFile() {
_ = GenericFunctionInAnotherFile[string]("world")
_ = GenericFunctionInAnotherFile("world")
}
func callFunctionsInAnotherPackage() {
_ = anotherpkg.GenericFunctionInAnotherPackage[string]("world")
_ = anotherpkg.GenericFunctionInAnotherPackage("world")
}

Просмотреть файл

@ -0,0 +1,6 @@
package main
func GenericFunctionInAnotherFile[T any](t T) T {
var r T
return r
}

Просмотреть файл

@ -1,3 +1,15 @@
| genericFunctions2.go:3:6:3:33 | GenericFunctionInAnotherFile | 0 | genericFunctions2.go:3:42:3:42 | t |
| genericFunctions.go:9:6:9:32 | GenericFunctionOneTypeParam | 0 | genericFunctions.go:9:41:9:41 | t |
| genericFunctions.go:15:6:15:33 | GenericFunctionTwoTypeParams | 0 | genericFunctions.go:15:68:15:68 | m |
| genericFunctions.go:87:30:87:31 | f1 | -1 | genericFunctions.go:87:7:87:7 | x |
| genericFunctions.go:92:31:92:32 | g1 | -1 | genericFunctions.go:92:7:92:7 | x |
| genericFunctions.go:95:35:95:36 | f2 | -1 | genericFunctions.go:95:7:95:7 | x |
| genericFunctions.go:98:36:98:37 | g2 | -1 | genericFunctions.go:98:7:98:7 | x |
| genericFunctions.go:120:19:120:23 | MyLen | -1 | genericFunctions.go:120:7:120:7 | l |
| genericFunctions.go:134:6:134:8 | New | 0 | genericFunctions.go:134:64:134:68 | nodes |
| genericFunctions.go:138:29:138:40 | ShortestPath | 0 | genericFunctions.go:138:42:138:45 | from |
| genericFunctions.go:138:29:138:40 | ShortestPath | 1 | genericFunctions.go:138:48:138:49 | to |
| genericFunctions.go:138:29:138:40 | ShortestPath | -1 | genericFunctions.go:138:7:138:7 | g |
| main.go:7:6:7:7 | f1 | 0 | main.go:7:9:7:9 | x | | main.go:7:6:7:7 | f1 | 0 | main.go:7:9:7:9 | x |
| main.go:9:12:9:13 | f2 | 0 | main.go:9:15:9:15 | x | | main.go:9:12:9:13 | f2 | 0 | main.go:9:15:9:15 | x |
| main.go:9:12:9:13 | f2 | 1 | main.go:9:18:9:18 | y | | main.go:9:12:9:13 | f2 | 1 | main.go:9:18:9:18 | y |

Просмотреть файл

@ -0,0 +1,15 @@
| genericFunctions2.go:3:1:6:1 | function declaration | FuncDecl | 0 | genericFunctions2.go:3:35:3:39 | type parameter declaration | 0 | genericFunctions2.go:3:35:3:35 | T | genericFunctions2.go:3:37:3:39 | any | interface { } |
| genericFunctions.go:9:1:12:1 | function declaration | FuncDecl | 0 | genericFunctions.go:9:34:9:38 | type parameter declaration | 0 | genericFunctions.go:9:34:9:34 | T | genericFunctions.go:9:36:9:38 | any | interface { } |
| genericFunctions.go:15:1:21:1 | function declaration | FuncDecl | 0 | genericFunctions.go:15:35:15:46 | type parameter declaration | 0 | genericFunctions.go:15:35:15:35 | K | genericFunctions.go:15:37:15:46 | comparable | comparable |
| genericFunctions.go:15:1:21:1 | function declaration | FuncDecl | 1 | genericFunctions.go:15:49:15:65 | type parameter declaration | 0 | genericFunctions.go:15:49:15:49 | V | genericFunctions.go:15:51:15:65 | type set literal | interface { int64 \| float64 } |
| genericFunctions.go:81:6:82:1 | type declaration specifier | TypeSpec | 0 | genericFunctions.go:81:21:81:25 | type parameter declaration | 0 | genericFunctions.go:81:21:81:21 | T | genericFunctions.go:81:23:81:25 | any | interface { } |
| genericFunctions.go:84:6:85:1 | type declaration specifier | TypeSpec | 0 | genericFunctions.go:84:21:84:28 | type parameter declaration | 0 | genericFunctions.go:84:21:84:21 | S | genericFunctions.go:84:26:84:28 | any | interface { } |
| genericFunctions.go:84:6:85:1 | type declaration specifier | TypeSpec | 0 | genericFunctions.go:84:21:84:28 | type parameter declaration | 1 | genericFunctions.go:84:24:84:24 | T | genericFunctions.go:84:26:84:28 | any | interface { } |
| genericFunctions.go:111:6:113:1 | type declaration specifier | TypeSpec | 0 | genericFunctions.go:111:14:111:18 | type parameter declaration | 0 | genericFunctions.go:111:14:111:14 | S | genericFunctions.go:111:16:111:18 | any | interface { } |
| genericFunctions.go:115:6:117:1 | type declaration specifier | TypeSpec | 0 | genericFunctions.go:115:11:115:15 | type parameter declaration | 0 | genericFunctions.go:115:11:115:11 | T | genericFunctions.go:115:13:115:15 | any | interface { } |
| genericFunctions.go:124:6:126:1 | type declaration specifier | TypeSpec | 0 | genericFunctions.go:124:21:124:28 | type parameter declaration | 0 | genericFunctions.go:124:21:124:24 | Edge | genericFunctions.go:124:26:124:28 | any | interface { } |
| genericFunctions.go:128:6:130:1 | type declaration specifier | TypeSpec | 0 | genericFunctions.go:128:21:128:28 | type parameter declaration | 0 | genericFunctions.go:128:21:128:24 | Node | genericFunctions.go:128:26:128:28 | any | interface { } |
| genericFunctions.go:132:6:132:73 | type declaration specifier | TypeSpec | 0 | genericFunctions.go:132:12:132:36 | type parameter declaration | 0 | genericFunctions.go:132:12:132:15 | Node | genericFunctions.go:132:17:132:36 | generic type instantiation expression | NodeConstraint |
| genericFunctions.go:132:6:132:73 | type declaration specifier | TypeSpec | 1 | genericFunctions.go:132:39:132:63 | type parameter declaration | 0 | genericFunctions.go:132:39:132:42 | Edge | genericFunctions.go:132:44:132:63 | generic type instantiation expression | EdgeConstraint |
| genericFunctions.go:134:1:136:1 | function declaration | FuncDecl | 0 | genericFunctions.go:134:10:134:34 | type parameter declaration | 0 | genericFunctions.go:134:10:134:13 | Node | genericFunctions.go:134:15:134:34 | generic type instantiation expression | NodeConstraint |
| genericFunctions.go:134:1:136:1 | function declaration | FuncDecl | 1 | genericFunctions.go:134:37:134:61 | type parameter declaration | 0 | genericFunctions.go:134:37:134:40 | Edge | genericFunctions.go:134:42:134:61 | generic type instantiation expression | EdgeConstraint |

Просмотреть файл

@ -0,0 +1,6 @@
import go
from TypeParamDeclParent x, int i, TypeParamDecl tpd, int j
where tpd = x.getTypeParameterDecl(i)
select x, x.getPrimaryQlClasses(), i, tpd, j, tpd.getNameExpr(j), tpd.getTypeConstraintExpr(),
tpd.getTypeConstraint().pp()

Просмотреть файл

@ -0,0 +1,6 @@
module codeql-go-tests/function
go 1.18
require github.com/anotherpkg v0.0.0-20200203000000-0000000000000

1
ql/test/library-tests/semmle/go/Function/vendor/github.com/anotherpkg/README.md сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
This is a simple stub package, strictly for use in query testing.

6
ql/test/library-tests/semmle/go/Function/vendor/github.com/anotherpkg/anotherpkg.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,6 @@
package anotherpkg
func GenericFunctionInAnotherPackage[T any](t T) T {
var r T
return r
}

3
ql/test/library-tests/semmle/go/Function/vendor/modules.txt поставляемый Normal file
Просмотреть файл

@ -0,0 +1,3 @@
# github.com/anotherpkg v0.0.0-20200203000000-0000000000000
## explicit; go 1.18
github.com/anotherpkg

Просмотреть файл

@ -12,6 +12,17 @@
| embedded.go:8:3:8:5 | Baz | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | | embedded.go:8:3:8:5 | Baz | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types |
| embedded.go:13:2:13:4 | Qux | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | | embedded.go:13:2:13:4 | Qux | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types |
| embedded.go:14:2:14:4 | Baz | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | | embedded.go:14:2:14:4 | Baz | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types |
| generic.go:4:2:4:11 | valueField | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types |
| generic.go:5:2:5:13 | pointerField | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types |
| generic.go:6:2:6:11 | arrayField | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types |
| generic.go:7:2:7:11 | sliceField | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types |
| generic.go:8:2:8:9 | mapField | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types |
| generic.go:12:2:12:13 | pointerField | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types |
| generic.go:16:2:16:5 | root | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types |
| generic.go:20:2:20:12 | structField | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types |
| generic.go:21:2:21:9 | mapField | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types |
| generic.go:25:2:25:12 | structField | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types |
| generic.go:29:2:29:13 | pointerField | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types |
| pkg1/embedding.go:19:23:19:26 | base | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | | pkg1/embedding.go:19:23:19:26 | base | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 |
| pkg1/embedding.go:22:27:22:30 | base | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | | pkg1/embedding.go:22:27:22:30 | base | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 |
| pkg1/embedding.go:25:24:25:31 | embedder | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | | pkg1/embedding.go:25:24:25:31 | embedder | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 |

Просмотреть файл

@ -19,6 +19,17 @@
| embedded.go:8:3:8:5 | Baz | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.Qux | Baz | | embedded.go:8:3:8:5 | Baz | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.Qux | Baz |
| embedded.go:13:2:13:4 | Qux | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.EmbedsBaz | Qux | | embedded.go:13:2:13:4 | Qux | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.EmbedsBaz | Qux |
| embedded.go:14:2:14:4 | Baz | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.EmbedsBaz | Baz | | embedded.go:14:2:14:4 | Baz | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.EmbedsBaz | Baz |
| generic.go:4:2:4:11 | valueField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.GenericStruct1 | valueField |
| generic.go:5:2:5:13 | pointerField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.GenericStruct1 | pointerField |
| generic.go:6:2:6:11 | arrayField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.GenericStruct1 | arrayField |
| generic.go:7:2:7:11 | sliceField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.GenericStruct1 | sliceField |
| generic.go:8:2:8:9 | mapField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.GenericStruct1 | mapField |
| generic.go:12:2:12:13 | pointerField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.CircularGenericStruct1 | pointerField |
| generic.go:16:2:16:5 | root | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.UsesCircularGenericStruct1 | root |
| generic.go:20:2:20:12 | structField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.GenericStruct2 | structField |
| generic.go:21:2:21:9 | mapField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.GenericStruct2 | mapField |
| generic.go:25:2:25:12 | structField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.GenericStruct2b | structField |
| generic.go:29:2:29:13 | pointerField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.CircularGenericStruct2 | pointerField |
| pkg1/embedding.go:19:23:19:26 | base | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder | base | | pkg1/embedding.go:19:23:19:26 | base | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder | base |
| pkg1/embedding.go:19:23:19:26 | base | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder2 | base | | pkg1/embedding.go:19:23:19:26 | base | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder2 | base |
| pkg1/embedding.go:19:23:19:26 | base | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder3 | base | | pkg1/embedding.go:19:23:19:26 | base | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder3 | base |

Просмотреть файл

@ -19,6 +19,17 @@
| embedded.go:8:3:8:5 | Baz | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | Qux | Baz | | embedded.go:8:3:8:5 | Baz | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | Qux | Baz |
| embedded.go:13:2:13:4 | Qux | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | EmbedsBaz | Qux | | embedded.go:13:2:13:4 | Qux | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | EmbedsBaz | Qux |
| embedded.go:14:2:14:4 | Baz | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | EmbedsBaz | Baz | | embedded.go:14:2:14:4 | Baz | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | EmbedsBaz | Baz |
| generic.go:4:2:4:11 | valueField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | GenericStruct1 | valueField |
| generic.go:5:2:5:13 | pointerField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | GenericStruct1 | pointerField |
| generic.go:6:2:6:11 | arrayField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | GenericStruct1 | arrayField |
| generic.go:7:2:7:11 | sliceField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | GenericStruct1 | sliceField |
| generic.go:8:2:8:9 | mapField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | GenericStruct1 | mapField |
| generic.go:12:2:12:13 | pointerField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | CircularGenericStruct1 | pointerField |
| generic.go:16:2:16:5 | root | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | UsesCircularGenericStruct1 | root |
| generic.go:20:2:20:12 | structField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | GenericStruct2 | structField |
| generic.go:21:2:21:9 | mapField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | GenericStruct2 | mapField |
| generic.go:25:2:25:12 | structField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | GenericStruct2b | structField |
| generic.go:29:2:29:13 | pointerField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | CircularGenericStruct2 | pointerField |
| pkg1/embedding.go:19:23:19:26 | base | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder | base | | pkg1/embedding.go:19:23:19:26 | base | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder | base |
| pkg1/embedding.go:19:23:19:26 | base | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder2 | base | | pkg1/embedding.go:19:23:19:26 | base | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder2 | base |
| pkg1/embedding.go:19:23:19:26 | base | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder3 | base | | pkg1/embedding.go:19:23:19:26 | base | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder3 | base |

Просмотреть файл

@ -0,0 +1,19 @@
| generic.go:12:16:12:40 | generic type instantiation expression | generic.go:12:16:12:37 | CircularGenericStruct1 | 0 | generic.go:12:39:12:39 | T |
| generic.go:16:7:16:31 | generic type instantiation expression | generic.go:16:7:16:28 | CircularGenericStruct1 | 0 | generic.go:16:30:16:30 | T |
| generic.go:20:14:20:30 | generic type instantiation expression | generic.go:20:14:20:27 | GenericStruct1 | 0 | generic.go:20:29:20:29 | S |
| generic.go:25:14:25:33 | generic type instantiation expression | generic.go:25:14:25:27 | GenericStruct2 | 0 | generic.go:25:29:25:29 | S |
| generic.go:25:14:25:33 | generic type instantiation expression | generic.go:25:14:25:27 | GenericStruct2 | 1 | generic.go:25:32:25:32 | T |
| generic.go:29:16:29:43 | generic type instantiation expression | generic.go:29:16:29:37 | CircularGenericStruct2 | 0 | generic.go:29:39:29:39 | S |
| generic.go:29:16:29:43 | generic type instantiation expression | generic.go:29:16:29:37 | CircularGenericStruct2 | 1 | generic.go:29:42:29:42 | T |
| generic.go:48:10:48:23 | generic type instantiation expression | generic.go:48:10:48:20 | MyInterface | 0 | generic.go:48:22:48:22 | U |
| generic.go:56:12:56:26 | generic type instantiation expression | generic.go:56:12:56:23 | GenericArray | 0 | generic.go:56:25:56:25 | U |
| generic.go:57:12:57:28 | generic type instantiation expression | generic.go:57:12:57:25 | GenericPointer | 0 | generic.go:57:27:57:27 | U |
| generic.go:58:12:58:26 | generic type instantiation expression | generic.go:58:12:58:23 | GenericSlice | 0 | generic.go:58:25:58:25 | U |
| generic.go:59:12:59:25 | generic type instantiation expression | generic.go:59:12:59:22 | GenericMap1 | 0 | generic.go:59:24:59:24 | U |
| generic.go:60:12:60:28 | generic type instantiation expression | generic.go:60:12:60:22 | GenericMap2 | 0 | generic.go:60:24:60:24 | U |
| generic.go:60:12:60:28 | generic type instantiation expression | generic.go:60:12:60:22 | GenericMap2 | 1 | generic.go:60:27:60:27 | U |
| generic.go:61:12:61:28 | generic type instantiation expression | generic.go:61:12:61:25 | GenericChannel | 0 | generic.go:61:27:61:27 | U |
| generic.go:62:12:62:26 | generic type instantiation expression | generic.go:62:12:62:23 | GenericNamed | 0 | generic.go:62:25:62:25 | U |
| generic.go:70:42:70:64 | generic type instantiation expression | generic.go:70:42:70:57 | GenericInterface | 0 | generic.go:70:59:70:63 | int32 |
| generic.go:74:41:74:62 | generic type instantiation expression | generic.go:74:41:74:54 | GenericStruct1 | 0 | generic.go:74:56:74:61 | string |
| generic.go:82:18:82:34 | generic type instantiation expression | generic.go:82:18:82:29 | GenericArray | 0 | generic.go:82:31:82:33 | int |

Просмотреть файл

@ -0,0 +1,4 @@
import go
from GenericTypeInstantiationExpr e, int i
select e, e.getBase(), i, e.getTypeArgument(i)

Просмотреть файл

Просмотреть файл

@ -0,0 +1,21 @@
import go
import TestUtilities.InlineExpectationsTest
class ImplementsComparableTest extends InlineExpectationsTest {
ImplementsComparableTest() { this = "ImplementsComparableTest" }
override string getARelevantTag() { result = "implementsComparable" }
override predicate hasActualResult(string file, int line, string element, string tag, string value) {
// file = "interface.go" and
tag = "implementsComparable" and
exists(TypeSpec ts |
ts.getName().matches("testComparable%") and
ts.getATypeParameterDecl().getTypeConstraint().implementsComparable()
|
ts.hasLocationInfo(file, line, _, _, _) and
element = ts.getName() and
value = ""
)
}
}

Просмотреть файл

@ -13,6 +13,8 @@
| B | 2 | | B | 2 |
| C | 2 | | C | 2 |
| Foo | 1 | | Foo | 1 |
| GenericInterface | 1 |
| MyInterface | 17 |
| T | 1 | | T | 1 |
| T3 | 1 | | T3 | 1 |
| T4 | 1 | | T4 | 1 |
@ -20,4 +22,14 @@
| embedder | 1 | | embedder | 1 |
| embedder2 | 1 | | embedder2 | 1 |
| embedder3 | 1 | | embedder3 | 1 |
| i6 | 1 |
| i7 | 1 |
| i8 | 2 |
| i9 | 2 |
| i14 | 2 |
| i15 | 2 |
| i17 | 1 |
| i18 | 1 |
| i19 | 1 |
| i20 | 1 |
| ptrembedder | 2 | | ptrembedder | 2 |

Просмотреть файл

@ -10,6 +10,24 @@
| B | n | func() | | B | n | func() |
| C | n | func() | | C | n | func() |
| C | o | func() | | C | o | func() |
| GenericInterface | GetT | func() T |
| MyInterface | clone | func() MyInterface |
| MyInterface | dummy1 | func() [10]U |
| MyInterface | dummy2 | func() * U |
| MyInterface | dummy3 | func() []U |
| MyInterface | dummy4 | func() [U]U |
| MyInterface | dummy5 | func() chan<- U |
| MyInterface | dummy6 | func() MyMapType |
| MyInterface | dummy7 | func() MyFuncType2 |
| MyInterface | dummy11 | func() GenericArray |
| MyInterface | dummy12 | func() GenericPointer |
| MyInterface | dummy13 | func() GenericSlice |
| MyInterface | dummy14 | func() GenericMap1 |
| MyInterface | dummy15 | func() GenericMap2 |
| MyInterface | dummy17 | func() GenericChannel |
| MyInterface | dummy18 | func() GenericNamed |
| MyInterface | dummy19 | func() MyFuncType1 |
| MyInterface | dummy20 | func() MyFuncType2 |
| T | half | func() Foo | | T | half | func() Foo |
| T3 | half | func() Foo | | T3 | half | func() Foo |
| T4 | half | func() Foo | | T4 | half | func() Foo |
@ -17,5 +35,19 @@
| embedder2 | f | func() int | | embedder2 | f | func() int |
| embedder3 | f | func() int | | embedder3 | f | func() int |
| embedder4 | f | func() int | | embedder4 | f | func() int |
| i6 | String | func() string |
| i7 | String | func() string |
| i8 | String | func() string |
| i8 | StringA | func() string |
| i9 | String | func() string |
| i9 | StringB | func() string |
| i14 | String | func() string |
| i14 | StringA | func() string |
| i15 | String | func() string |
| i15 | StringB | func() string |
| i17 | StringA | func() string |
| i18 | StringA | func() string |
| i19 | StringB | func() string |
| i20 | StringB | func() string |
| ptrembedder | f | func() int | | ptrembedder | f | func() int |
| ptrembedder | g | func() int | | ptrembedder | g | func() int |

Просмотреть файл

@ -1,3 +1,35 @@
| generic.go:33:2:33:5 | GetT | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | GenericInterface | GetT |
| generic.go:48:2:48:6 | clone | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | clone |
| generic.go:49:2:49:7 | dummy1 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy1 |
| generic.go:50:2:50:7 | dummy2 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy2 |
| generic.go:51:2:51:7 | dummy3 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy3 |
| generic.go:52:2:52:7 | dummy4 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy4 |
| generic.go:53:2:53:7 | dummy5 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy5 |
| generic.go:54:2:54:7 | dummy6 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy6 |
| generic.go:55:2:55:7 | dummy7 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy7 |
| generic.go:56:2:56:8 | dummy11 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy11 |
| generic.go:57:2:57:8 | dummy12 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy12 |
| generic.go:58:2:58:8 | dummy13 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy13 |
| generic.go:59:2:59:8 | dummy14 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy14 |
| generic.go:60:2:60:8 | dummy15 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy15 |
| generic.go:61:2:61:8 | dummy17 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy17 |
| generic.go:62:2:62:8 | dummy18 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy18 |
| generic.go:63:2:63:8 | dummy19 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy19 |
| generic.go:64:2:64:8 | dummy20 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy20 |
| interface.go:30:2:30:7 | String | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i6 | String |
| interface.go:30:2:30:7 | String | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i8 | String |
| interface.go:30:2:30:7 | String | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i9 | String |
| interface.go:30:2:30:7 | String | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i14 | String |
| interface.go:30:2:30:7 | String | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i15 | String |
| interface.go:37:2:37:7 | String | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i7 | String |
| interface.go:43:2:43:8 | StringA | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i8 | StringA |
| interface.go:43:2:43:8 | StringA | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i14 | StringA |
| interface.go:49:2:49:8 | StringB | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i9 | StringB |
| interface.go:49:2:49:8 | StringB | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i15 | StringB |
| interface.go:92:2:92:8 | StringA | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i17 | StringA |
| interface.go:97:2:97:8 | StringA | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i18 | StringA |
| interface.go:102:2:102:8 | StringB | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i19 | StringB |
| interface.go:107:2:107:8 | StringB | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i20 | StringB |
| pkg1/embedding.go:10:13:10:13 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | base | f | | pkg1/embedding.go:10:13:10:13 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | base | f |
| pkg1/embedding.go:10:13:10:13 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder | f | | pkg1/embedding.go:10:13:10:13 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder | f |
| pkg1/embedding.go:10:13:10:13 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder2 | f | | pkg1/embedding.go:10:13:10:13 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder2 | f |

Просмотреть файл

@ -1,3 +1,35 @@
| generic.go:33:2:33:5 | GetT | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | GenericInterface | GetT |
| generic.go:48:2:48:6 | clone | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | clone |
| generic.go:49:2:49:7 | dummy1 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy1 |
| generic.go:50:2:50:7 | dummy2 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy2 |
| generic.go:51:2:51:7 | dummy3 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy3 |
| generic.go:52:2:52:7 | dummy4 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy4 |
| generic.go:53:2:53:7 | dummy5 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy5 |
| generic.go:54:2:54:7 | dummy6 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy6 |
| generic.go:55:2:55:7 | dummy7 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy7 |
| generic.go:56:2:56:8 | dummy11 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy11 |
| generic.go:57:2:57:8 | dummy12 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy12 |
| generic.go:58:2:58:8 | dummy13 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy13 |
| generic.go:59:2:59:8 | dummy14 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy14 |
| generic.go:60:2:60:8 | dummy15 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy15 |
| generic.go:61:2:61:8 | dummy17 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy17 |
| generic.go:62:2:62:8 | dummy18 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy18 |
| generic.go:63:2:63:8 | dummy19 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy19 |
| generic.go:64:2:64:8 | dummy20 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | MyInterface | dummy20 |
| interface.go:30:2:30:7 | String | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i6 | String |
| interface.go:30:2:30:7 | String | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i8 | String |
| interface.go:30:2:30:7 | String | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i9 | String |
| interface.go:30:2:30:7 | String | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i14 | String |
| interface.go:30:2:30:7 | String | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i15 | String |
| interface.go:37:2:37:7 | String | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i7 | String |
| interface.go:43:2:43:8 | StringA | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i8 | StringA |
| interface.go:43:2:43:8 | StringA | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i14 | StringA |
| interface.go:49:2:49:8 | StringB | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i9 | StringB |
| interface.go:49:2:49:8 | StringB | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i15 | StringB |
| interface.go:92:2:92:8 | StringA | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i17 | StringA |
| interface.go:97:2:97:8 | StringA | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i18 | StringA |
| interface.go:102:2:102:8 | StringB | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i19 | StringB |
| interface.go:107:2:107:8 | StringB | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | i20 | StringB |
| pkg1/embedding.go:10:13:10:13 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | base | f | | pkg1/embedding.go:10:13:10:13 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | base | f |
| pkg1/embedding.go:10:13:10:13 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder | f | | pkg1/embedding.go:10:13:10:13 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder | f |
| pkg1/embedding.go:10:13:10:13 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder2 | f | | pkg1/embedding.go:10:13:10:13 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder2 | f |

Просмотреть файл

@ -23,6 +23,24 @@
| C | n | pkg1/interfaces.go:13:2:13:2 | n | | C | n | pkg1/interfaces.go:13:2:13:2 | n |
| C | o | pkg1/interfaces.go:14:2:14:2 | o | | C | o | pkg1/interfaces.go:14:2:14:2 | o |
| Foo | half | pkg1/tst.go:33:16:33:19 | half | | Foo | half | pkg1/tst.go:33:16:33:19 | half |
| GenericInterface | GetT | generic.go:33:2:33:5 | GetT |
| MyInterface | clone | generic.go:48:2:48:6 | clone |
| MyInterface | dummy1 | generic.go:49:2:49:7 | dummy1 |
| MyInterface | dummy2 | generic.go:50:2:50:7 | dummy2 |
| MyInterface | dummy3 | generic.go:51:2:51:7 | dummy3 |
| MyInterface | dummy4 | generic.go:52:2:52:7 | dummy4 |
| MyInterface | dummy5 | generic.go:53:2:53:7 | dummy5 |
| MyInterface | dummy6 | generic.go:54:2:54:7 | dummy6 |
| MyInterface | dummy7 | generic.go:55:2:55:7 | dummy7 |
| MyInterface | dummy11 | generic.go:56:2:56:8 | dummy11 |
| MyInterface | dummy12 | generic.go:57:2:57:8 | dummy12 |
| MyInterface | dummy13 | generic.go:58:2:58:8 | dummy13 |
| MyInterface | dummy14 | generic.go:59:2:59:8 | dummy14 |
| MyInterface | dummy15 | generic.go:60:2:60:8 | dummy15 |
| MyInterface | dummy17 | generic.go:61:2:61:8 | dummy17 |
| MyInterface | dummy18 | generic.go:62:2:62:8 | dummy18 |
| MyInterface | dummy19 | generic.go:63:2:63:8 | dummy19 |
| MyInterface | dummy20 | generic.go:64:2:64:8 | dummy20 |
| T | half | pkg1/tst.go:33:16:33:19 | half | | T | half | pkg1/tst.go:33:16:33:19 | half |
| T3 | half | pkg1/tst.go:33:16:33:19 | half | | T3 | half | pkg1/tst.go:33:16:33:19 | half |
| T4 | half | pkg1/tst.go:33:16:33:19 | half | | T4 | half | pkg1/tst.go:33:16:33:19 | half |
@ -30,5 +48,19 @@
| embedder | f | pkg1/embedding.go:10:13:10:13 | f | | embedder | f | pkg1/embedding.go:10:13:10:13 | f |
| embedder2 | f | pkg1/embedding.go:10:13:10:13 | f | | embedder2 | f | pkg1/embedding.go:10:13:10:13 | f |
| embedder3 | f | pkg1/embedding.go:30:18:30:18 | f | | embedder3 | f | pkg1/embedding.go:30:18:30:18 | f |
| i6 | String | interface.go:30:2:30:7 | String |
| i7 | String | interface.go:37:2:37:7 | String |
| i8 | String | interface.go:30:2:30:7 | String |
| i8 | StringA | interface.go:43:2:43:8 | StringA |
| i9 | String | interface.go:30:2:30:7 | String |
| i9 | StringB | interface.go:49:2:49:8 | StringB |
| i14 | String | interface.go:30:2:30:7 | String |
| i14 | StringA | interface.go:43:2:43:8 | StringA |
| i15 | String | interface.go:30:2:30:7 | String |
| i15 | StringB | interface.go:49:2:49:8 | StringB |
| i17 | StringA | interface.go:92:2:92:8 | StringA |
| i18 | StringA | interface.go:97:2:97:8 | StringA |
| i19 | StringB | interface.go:102:2:102:8 | StringB |
| i20 | StringB | interface.go:107:2:107:8 | StringB |
| ptrembedder | f | pkg1/embedding.go:10:13:10:13 | f | | ptrembedder | f | pkg1/embedding.go:10:13:10:13 | f |
| ptrembedder | g | pkg1/embedding.go:14:14:14:14 | g | | ptrembedder | g | pkg1/embedding.go:14:14:14:14 | g |

Просмотреть файл

@ -7,15 +7,36 @@
| Bar | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.Bar | | Bar | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.Bar |
| Baz | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.Baz | | Baz | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.Baz |
| C | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.C | | C | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.C |
| CircularGenericStruct1 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.CircularGenericStruct1 |
| CircularGenericStruct2 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.CircularGenericStruct2 |
| EmbedsBaz | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.EmbedsBaz | | EmbedsBaz | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.EmbedsBaz |
| Foo | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.Foo | | Foo | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.Foo |
| G | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg2.G | | G | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg2.G |
| GenericArray | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.GenericArray |
| GenericChannel | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.GenericChannel |
| GenericInterface | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.GenericInterface |
| GenericMap1 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.GenericMap1 |
| GenericMap2 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.GenericMap2 |
| GenericNamed | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.GenericNamed |
| GenericPointer | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.GenericPointer |
| GenericSignature | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.GenericSignature |
| GenericSlice | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.GenericSlice |
| GenericStruct1 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.GenericStruct1 |
| GenericStruct2 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.GenericStruct2 |
| GenericStruct2b | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.GenericStruct2b |
| HasBlankTypeParam | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.HasBlankTypeParam |
| HasBlankTypeParams | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.HasBlankTypeParams |
| MyFuncType1 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.MyFuncType1 |
| MyFuncType2 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.MyFuncType2 |
| MyInterface | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.MyInterface |
| MyMapType | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.MyMapType |
| Qux | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.Qux | | Qux | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.Qux |
| T | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T | | T | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T |
| T | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg2.T | | T | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg2.T |
| T2 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T2 | | T2 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T2 |
| T3 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T3 | | T3 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T3 |
| T4 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T4 | | T4 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T4 |
| UsesCircularGenericStruct1 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.UsesCircularGenericStruct1 |
| a | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.a | | a | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.a |
| b | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.b | | b | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.b |
| base | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.base | | base | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.base |
@ -25,8 +46,54 @@
| embedder2 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder2 | | embedder2 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder2 |
| embedder3 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder3 | | embedder3 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder3 |
| embedder4 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder4 | | embedder4 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder4 |
| i0 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i0 |
| i1 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i1 |
| i2 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i2 |
| i3 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i3 |
| i4 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i4 |
| i5 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i5 |
| i6 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i6 |
| i7 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i7 |
| i8 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i8 |
| i9 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i9 |
| i10 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i10 |
| i11 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i11 |
| i12 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i12 |
| i13 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i13 |
| i14 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i14 |
| i15 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i15 |
| i16 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i16 |
| i17 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i17 |
| i18 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i18 |
| i19 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i19 |
| i20 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.i20 |
| ptrembedder | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.ptrembedder | | ptrembedder | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.ptrembedder |
| s | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.s | | s | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.s |
| t | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.t | | t | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.t |
| testComparable | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable |
| testComparable0 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable0 |
| testComparable1 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable1 |
| testComparable2 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable2 |
| testComparable3 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable3 |
| testComparable4 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable4 |
| testComparable5 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable5 |
| testComparable6 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable6 |
| testComparable7 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable7 |
| testComparable8 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable8 |
| testComparable9 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable9 |
| testComparable10 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable10 |
| testComparable11 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable11 |
| testComparable12 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable12 |
| testComparable13 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable13 |
| testComparable14 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable14 |
| testComparable15 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable15 |
| testComparable16 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable16 |
| testComparable17 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable17 |
| testComparable18 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable18 |
| testComparable19 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable19 |
| testComparable20 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable20 |
| testComparable21 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable21 |
| testComparable22 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable22 |
| testComparable23 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable23 |
| u | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.u | | u | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.u |
| v | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.v | | v | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.v |

Просмотреть файл

@ -1,4 +1,6 @@
| depth.go:22:1:25:1 | function declaration | 0 | | depth.go:22:1:25:1 | function declaration | 0 |
| generic.go:70:1:72:1 | function declaration | 1 |
| generic.go:74:1:80:1 | function declaration | 1 |
| main.go:5:1:5:30 | function declaration | 1 | | main.go:5:1:5:30 | function declaration | 1 |
| main.go:7:1:9:1 | function declaration | 2 | | main.go:7:1:9:1 | function declaration | 2 |
| main.go:11:1:11:14 | function declaration | 0 | | main.go:11:1:11:14 | function declaration | 0 |

Просмотреть файл

@ -1,4 +1,6 @@
| depth.go:22:1:25:1 | function declaration | 0 | | depth.go:22:1:25:1 | function declaration | 0 |
| generic.go:70:1:72:1 | function declaration | 1 |
| generic.go:74:1:80:1 | function declaration | 0 |
| main.go:5:1:5:30 | function declaration | 0 | | main.go:5:1:5:30 | function declaration | 0 |
| main.go:7:1:9:1 | function declaration | 2 | | main.go:7:1:9:1 | function declaration | 2 |
| main.go:11:1:11:14 | function declaration | 0 | | main.go:11:1:11:14 | function declaration | 0 |

Просмотреть файл

@ -1,11 +1,21 @@
| Bar | pkg1/tst.go:29:10:31:1 | struct type | flag | bool | | Bar | pkg1/tst.go:29:10:31:1 | struct type | flag | bool |
| Baz | embedded.go:3:10:5:1 | struct type | A | string | | Baz | embedded.go:3:10:5:1 | struct type | A | string |
| CircularGenericStruct1 | generic.go:11:38:13:1 | struct type | pointerField | * CircularGenericStruct1 |
| CircularGenericStruct2 | generic.go:28:39:30:1 | struct type | pointerField | * CircularGenericStruct2 |
| EmbedsBaz | embedded.go:12:16:15:1 | struct type | Baz | string | | EmbedsBaz | embedded.go:12:16:15:1 | struct type | Baz | string |
| EmbedsBaz | embedded.go:12:16:15:1 | struct type | Qux | Qux | | EmbedsBaz | embedded.go:12:16:15:1 | struct type | Qux | Qux |
| Foo | pkg1/tst.go:24:10:27:1 | struct type | flag | bool | | Foo | pkg1/tst.go:24:10:27:1 | struct type | flag | bool |
| Foo | pkg1/tst.go:24:10:27:1 | struct type | val | int | | Foo | pkg1/tst.go:24:10:27:1 | struct type | val | int |
| G | pkg2/tst.go:3:8:5:1 | struct type | g | int | | G | pkg2/tst.go:3:8:5:1 | struct type | g | int |
| G | pkg2/tst.go:7:8:9:1 | struct type | g | int | | G | pkg2/tst.go:7:8:9:1 | struct type | g | int |
| GenericStruct1 | generic.go:3:28:9:1 | struct type | arrayField | [10]T |
| GenericStruct1 | generic.go:3:28:9:1 | struct type | mapField | [string]T |
| GenericStruct1 | generic.go:3:28:9:1 | struct type | pointerField | * T |
| GenericStruct1 | generic.go:3:28:9:1 | struct type | sliceField | []T |
| GenericStruct1 | generic.go:3:28:9:1 | struct type | valueField | T |
| GenericStruct2 | generic.go:19:42:22:1 | struct type | mapField | [S]T |
| GenericStruct2 | generic.go:19:42:22:1 | struct type | structField | GenericStruct1 |
| GenericStruct2b | generic.go:24:39:26:1 | struct type | structField | GenericStruct2 |
| Qux | embedded.go:7:10:9:1 | struct type | A | string | | Qux | embedded.go:7:10:9:1 | struct type | A | string |
| Qux | embedded.go:7:10:9:1 | struct type | Baz | * Baz | | Qux | embedded.go:7:10:9:1 | struct type | Baz | * Baz |
| T | pkg1/tst.go:3:8:7:1 | struct type | Bar | Bar | | T | pkg1/tst.go:3:8:7:1 | struct type | Bar | Bar |
@ -24,6 +34,7 @@
| T4 | pkg1/tst.go:19:9:22:1 | struct type | Foo | * Foo | | T4 | pkg1/tst.go:19:9:22:1 | struct type | Foo | * Foo |
| T4 | pkg1/tst.go:19:9:22:1 | struct type | flag | bool | | T4 | pkg1/tst.go:19:9:22:1 | struct type | flag | bool |
| T4 | pkg1/tst.go:19:9:22:1 | struct type | val | int | | T4 | pkg1/tst.go:19:9:22:1 | struct type | val | int |
| UsesCircularGenericStruct1 | generic.go:15:42:17:1 | struct type | root | CircularGenericStruct1 |
| a | depth.go:5:8:8:1 | struct type | b | b | | a | depth.go:5:8:8:1 | struct type | b | b |
| a | depth.go:5:8:8:1 | struct type | c | c | | a | depth.go:5:8:8:1 | struct type | c | c |
| a | depth.go:5:8:8:1 | struct type | d | d | | a | depth.go:5:8:8:1 | struct type | d | d |

Просмотреть файл

@ -7,15 +7,36 @@
| Bar | Bar | | Bar | Bar |
| Baz | Baz | | Baz | Baz |
| C | C | | C | C |
| CircularGenericStruct1 | CircularGenericStruct1 |
| CircularGenericStruct2 | CircularGenericStruct2 |
| EmbedsBaz | EmbedsBaz | | EmbedsBaz | EmbedsBaz |
| Foo | Foo | | Foo | Foo |
| G | G | | G | G |
| GenericArray | GenericArray |
| GenericChannel | GenericChannel |
| GenericInterface | GenericInterface |
| GenericMap1 | GenericMap1 |
| GenericMap2 | GenericMap2 |
| GenericNamed | GenericNamed |
| GenericPointer | GenericPointer |
| GenericSignature | GenericSignature |
| GenericSlice | GenericSlice |
| GenericStruct1 | GenericStruct1 |
| GenericStruct2 | GenericStruct2 |
| GenericStruct2b | GenericStruct2b |
| HasBlankTypeParam | HasBlankTypeParam |
| HasBlankTypeParams | HasBlankTypeParams |
| MyFuncType1 | MyFuncType1 |
| MyFuncType2 | MyFuncType2 |
| MyInterface | MyInterface |
| MyMapType | MyMapType |
| Qux | Qux | | Qux | Qux |
| T | T | | T | T |
| T | T | | T | T |
| T2 | T2 | | T2 | T2 |
| T3 | T3 | | T3 | T3 |
| T4 | T4 | | T4 | T4 |
| UsesCircularGenericStruct1 | UsesCircularGenericStruct1 |
| a | a | | a | a |
| b | b | | b | b |
| base | base | | base | base |
@ -25,8 +46,54 @@
| embedder2 | embedder2 | | embedder2 | embedder2 |
| embedder3 | embedder3 | | embedder3 | embedder3 |
| embedder4 | embedder4 | | embedder4 | embedder4 |
| i0 | i0 |
| i1 | i1 |
| i2 | i2 |
| i3 | i3 |
| i4 | i4 |
| i5 | i5 |
| i6 | i6 |
| i7 | i7 |
| i8 | i8 |
| i9 | i9 |
| i10 | i10 |
| i11 | i11 |
| i12 | i12 |
| i13 | i13 |
| i14 | i14 |
| i15 | i15 |
| i16 | i16 |
| i17 | i17 |
| i18 | i18 |
| i19 | i19 |
| i20 | i20 |
| ptrembedder | ptrembedder | | ptrembedder | ptrembedder |
| s | s | | s | s |
| t | t | | t | t |
| testComparable | testComparable |
| testComparable0 | testComparable0 |
| testComparable1 | testComparable1 |
| testComparable2 | testComparable2 |
| testComparable3 | testComparable3 |
| testComparable4 | testComparable4 |
| testComparable5 | testComparable5 |
| testComparable6 | testComparable6 |
| testComparable7 | testComparable7 |
| testComparable8 | testComparable8 |
| testComparable9 | testComparable9 |
| testComparable10 | testComparable10 |
| testComparable11 | testComparable11 |
| testComparable12 | testComparable12 |
| testComparable13 | testComparable13 |
| testComparable14 | testComparable14 |
| testComparable15 | testComparable15 |
| testComparable16 | testComparable16 |
| testComparable17 | testComparable17 |
| testComparable18 | testComparable18 |
| testComparable19 | testComparable19 |
| testComparable20 | testComparable20 |
| testComparable21 | testComparable21 |
| testComparable22 | testComparable22 |
| testComparable23 | testComparable23 |
| u | u | | u | u |
| v | v | | v | v |

Просмотреть файл

@ -0,0 +1,85 @@
package main
type GenericStruct1[T any] struct {
valueField T
pointerField *T
arrayField [10]T
sliceField []T
mapField map[string]T
}
type CircularGenericStruct1[T error] struct {
pointerField *CircularGenericStruct1[T]
}
type UsesCircularGenericStruct1[T error] struct {
root CircularGenericStruct1[T]
}
type GenericStruct2[S comparable, T int] struct {
structField GenericStruct1[S]
mapField map[S]T
}
type GenericStruct2b[S string, T int] struct {
structField GenericStruct2[S, T]
}
type CircularGenericStruct2[S, T any] struct {
pointerField *CircularGenericStruct2[S, T]
}
type GenericInterface[T ~int32 | ~int64] interface {
GetT() T
}
type GenericArray[T comparable] [10]T
type GenericPointer[T any] *T
type GenericSlice[T any] []T
type GenericMap1[V any] map[string]V
type GenericMap2[K comparable, V any] map[K]V
type GenericChannel[T comparable] chan<- T
type MyMapType map[string]int
type GenericNamed[T comparable] MyMapType
type MyFuncType1[T any] func(T)
type MyFuncType2[T1 any, T2 any] func(T1) T2
type MyInterface[U comparable] interface {
clone() MyInterface[U]
dummy1() [10]U
dummy2() *U
dummy3() []U
dummy4() map[U]U
dummy5() chan<- U
dummy6() MyMapType
dummy7() MyFuncType2[int, bool]
dummy11() GenericArray[U]
dummy12() GenericPointer[U]
dummy13() GenericSlice[U]
dummy14() GenericMap1[U]
dummy15() GenericMap2[U, U]
dummy17() GenericChannel[U]
dummy18() GenericNamed[U]
dummy19() MyFuncType1[U]
dummy20() MyFuncType2[U, U]
}
type HasBlankTypeParam[_ any] struct{}
type HasBlankTypeParams[_ any, _ comparable, T ~string] struct{}
func callMethodOnInstantiatedInterface(x GenericInterface[int32]) int32 {
return x.GetT()
}
func accessFieldsOfInstantiatedStruct(x GenericStruct1[string]) {
_ = x.valueField
_ = x.pointerField
_ = x.arrayField
_ = x.sliceField
_ = x.mapField
}
type TypeAlias = GenericArray[int]
type GenericSignature[T any] func(t T) T
type GenericSignatureAlias = GenericSignature[string]

Просмотреть файл

@ -0,0 +1,134 @@
package main
type i0 comparable
type i1 interface {
int
}
type i2 interface {
~string
}
type i3 interface {
[5]int | ~string
}
// typeset: int | ~string | float32
type i4 interface {
i1 | i2 | float32
}
// typeset: []byte
type i5 interface {
int | ~[]byte
[]byte
}
type i6 interface {
~[]int | ~string
String() string
}
// typeset: ~string
type i7 interface {
i3
~string
String() string
}
// typeset: ~[]int | ~string
type i8 interface {
i6
StringA() string
}
// typeset: ~[]int | ~string
type i9 interface {
i6
StringB() string
}
type i10 interface {
comparable
}
// typeset: the empty set
type i11 interface {
[5]byte | string
int
}
// typeset: []byte | string
type i12 interface {
[]byte | string
comparable
}
// typeset: []byte | string
type i13 interface {
[]byte | string
i10
}
// typeset: string
type i14 interface {
[]byte | string
i8
}
// typeset: string
type i15 interface {
[]byte | string
i9
}
// The empty interface does not implement comparable
type i16 interface {
}
// A basic interface, so not comparable
type i17 interface {
StringA() string
}
type i18 interface {
comparable
StringA() string
}
// A basic interface, so not comparable
type i19 interface {
StringB() string
}
type i20 interface {
comparable
StringB() string
}
type testComparable[T comparable] struct{} // $ implementsComparable
type testComparable0[T0 i0] struct{} // $ implementsComparable
type testComparable1[T1 i1] struct{} // $ implementsComparable
type testComparable2[T2 i2] struct{} // $ implementsComparable
type testComparable3[T3 i3] struct{} // $ implementsComparable
type testComparable4[T4 i4] struct{} // $ implementsComparable
type testComparable5[T5 i5] struct{} // does not implement comparable
type testComparable6[T6 i6] struct{} // does not implement comparable
type testComparable7[T7 i7] struct{} // $ implementsComparable
type testComparable8[T8 i8] struct{} // does not implement comparable
type testComparable9[T9 i9] struct{} // does not implement comparable
type testComparable10[T10 i10] struct{} // $ implementsComparable
type testComparable11[T11 i11] struct{} // $ implementsComparable
type testComparable12[T12 i12] struct{} // does not implement comparable
type testComparable13[T13 i13] struct{} // does not implement comparable
type testComparable14[T14 i14] struct{} // $ implementsComparable
type testComparable15[T15 i15] struct{} // $ implementsComparable
type testComparable16[T16 i16] struct{} // does not implement comparable
type testComparable17[T17 i17] struct{} // does not implement comparable
type testComparable18[T18 i18] struct{} // $ implementsComparable
type testComparable19[T19 i19] struct{} // does not implement comparable
type testComparable20[T20 i20] struct{} // $ implementsComparable
type testComparable21[T21 ~[]byte | string] struct{} // does not implement comparable
type testComparable22[T22 any] struct{} // does not implement comparable
type testComparable23[T23 ~[5]byte | string] struct{} // $ implementsComparable

Просмотреть файл

@ -496,6 +496,111 @@ edges
| exprs.go:94:16:94:16 | (...) is false | exprs.go:94:21:94:21 | z | | exprs.go:94:16:94:16 | (...) is false | exprs.go:94:21:94:21 | z |
| exprs.go:94:16:94:16 | (...) is true | exprs.go:94:9:94:21 | ...\|\|... | | exprs.go:94:16:94:16 | (...) is true | exprs.go:94:9:94:21 | ...\|\|... |
| exprs.go:94:21:94:21 | z | exprs.go:94:9:94:21 | ...\|\|... | | exprs.go:94:21:94:21 | z | exprs.go:94:9:94:21 | ...\|\|... |
| generic.go:0:0:0:0 | entry | generic.go:3:1:5:1 | skip |
| generic.go:3:1:5:1 | skip | generic.go:7:28:7:35 | skip |
| generic.go:7:1:7:1 | entry | generic.go:7:7:7:7 | argument corresponding to g |
| generic.go:7:1:7:55 | function declaration | generic.go:9:1:12:1 | skip |
| generic.go:7:7:7:7 | argument corresponding to g | generic.go:7:7:7:7 | initialization of g |
| generic.go:7:7:7:7 | initialization of g | generic.go:7:37:7:37 | argument corresponding to u |
| generic.go:7:28:7:35 | skip | generic.go:7:1:7:55 | function declaration |
| generic.go:7:37:7:37 | argument corresponding to u | generic.go:7:37:7:37 | initialization of u |
| generic.go:7:37:7:37 | initialization of u | generic.go:7:53:7:53 | u |
| generic.go:7:46:7:53 | return statement | generic.go:7:55:7:55 | exit |
| generic.go:7:53:7:53 | u | generic.go:7:46:7:53 | return statement |
| generic.go:9:1:12:1 | skip | generic.go:14:31:14:39 | skip |
| generic.go:14:1:14:1 | entry | generic.go:14:7:14:7 | argument corresponding to g |
| generic.go:14:1:14:59 | function declaration | generic.go:16:6:16:21 | skip |
| generic.go:14:7:14:7 | argument corresponding to g | generic.go:14:7:14:7 | initialization of g |
| generic.go:14:7:14:7 | initialization of g | generic.go:14:41:14:41 | argument corresponding to u |
| generic.go:14:31:14:39 | skip | generic.go:14:1:14:59 | function declaration |
| generic.go:14:41:14:41 | argument corresponding to u | generic.go:14:41:14:41 | initialization of u |
| generic.go:14:41:14:41 | initialization of u | generic.go:14:57:14:57 | u |
| generic.go:14:50:14:57 | return statement | generic.go:14:59:14:59 | exit |
| generic.go:14:57:14:57 | u | generic.go:14:50:14:57 | return statement |
| generic.go:16:1:16:1 | entry | generic.go:16:30:16:30 | argument corresponding to t |
| generic.go:16:1:18:1 | function declaration | generic.go:20:6:20:21 | skip |
| generic.go:16:6:16:21 | skip | generic.go:16:1:18:1 | function declaration |
| generic.go:16:30:16:30 | argument corresponding to t | generic.go:16:30:16:30 | initialization of t |
| generic.go:16:30:16:30 | initialization of t | generic.go:17:9:17:9 | t |
| generic.go:17:2:17:9 | return statement | generic.go:18:1:18:1 | exit |
| generic.go:17:9:17:9 | t | generic.go:17:2:17:9 | return statement |
| generic.go:20:1:20:1 | entry | generic.go:20:33:20:33 | argument corresponding to s |
| generic.go:20:1:22:1 | function declaration | generic.go:24:6:24:12 | skip |
| generic.go:20:6:20:21 | skip | generic.go:20:1:22:1 | function declaration |
| generic.go:20:33:20:33 | argument corresponding to s | generic.go:20:33:20:33 | initialization of s |
| generic.go:20:33:20:33 | initialization of s | generic.go:20:38:20:38 | argument corresponding to t |
| generic.go:20:38:20:38 | argument corresponding to t | generic.go:20:38:20:38 | initialization of t |
| generic.go:20:38:20:38 | initialization of t | generic.go:21:9:21:9 | s |
| generic.go:21:2:21:12 | return statement | generic.go:22:1:22:1 | exit |
| generic.go:21:9:21:9 | s | generic.go:21:12:21:12 | t |
| generic.go:21:12:21:12 | t | generic.go:21:2:21:12 | return statement |
| generic.go:24:1:24:1 | entry | generic.go:25:2:25:4 | skip |
| generic.go:24:1:35:1 | function declaration | generic.go:0:0:0:0 | exit |
| generic.go:24:6:24:12 | skip | generic.go:24:1:35:1 | function declaration |
| generic.go:25:2:25:4 | assignment to gs1 | generic.go:26:2:26:2 | skip |
| generic.go:25:2:25:4 | skip | generic.go:25:9:25:35 | struct literal |
| generic.go:25:9:25:35 | struct literal | generic.go:25:32:25:34 | "x" |
| generic.go:25:32:25:34 | "x" | generic.go:25:32:25:34 | init of "x" |
| generic.go:25:32:25:34 | init of "x" | generic.go:25:2:25:4 | assignment to gs1 |
| generic.go:26:2:26:2 | assignment to a | generic.go:27:2:27:4 | skip |
| generic.go:26:2:26:2 | skip | generic.go:26:7:26:9 | gs1 |
| generic.go:26:7:26:9 | gs1 | generic.go:26:7:26:18 | selection of Identity |
| generic.go:26:7:26:18 | selection of Identity | generic.go:26:20:26:26 | "hello" |
| generic.go:26:7:26:27 | call to Identity | generic.go:26:2:26:2 | assignment to a |
| generic.go:26:7:26:27 | call to Identity | generic.go:35:1:35:1 | exit |
| generic.go:26:20:26:26 | "hello" | generic.go:26:7:26:27 | call to Identity |
| generic.go:27:2:27:4 | assignment to gs2 | generic.go:28:2:28:2 | skip |
| generic.go:27:2:27:4 | skip | generic.go:27:9:27:48 | struct literal |
| generic.go:27:9:27:48 | struct literal | generic.go:27:40:27:42 | "y" |
| generic.go:27:40:27:42 | "y" | generic.go:27:40:27:42 | init of "y" |
| generic.go:27:40:27:42 | init of "y" | generic.go:27:45:27:47 | "z" |
| generic.go:27:45:27:47 | "z" | generic.go:27:45:27:47 | init of "z" |
| generic.go:27:45:27:47 | init of "z" | generic.go:27:2:27:4 | assignment to gs2 |
| generic.go:28:2:28:2 | assignment to b | generic.go:29:2:29:2 | skip |
| generic.go:28:2:28:2 | skip | generic.go:28:7:28:9 | gs2 |
| generic.go:28:7:28:9 | gs2 | generic.go:28:7:28:19 | selection of Identity1 |
| generic.go:28:7:28:19 | selection of Identity1 | generic.go:28:21:28:21 | a |
| generic.go:28:7:28:22 | call to Identity1 | generic.go:28:2:28:2 | assignment to b |
| generic.go:28:7:28:22 | call to Identity1 | generic.go:35:1:35:1 | exit |
| generic.go:28:21:28:21 | a | generic.go:28:7:28:22 | call to Identity1 |
| generic.go:29:2:29:2 | assignment to c | generic.go:30:2:30:2 | skip |
| generic.go:29:2:29:2 | skip | generic.go:29:7:29:22 | genericIdentity1 |
| generic.go:29:7:29:22 | genericIdentity1 | generic.go:29:32:29:32 | b |
| generic.go:29:7:29:33 | call to genericIdentity1 | generic.go:29:2:29:2 | assignment to c |
| generic.go:29:7:29:33 | call to genericIdentity1 | generic.go:35:1:35:1 | exit |
| generic.go:29:32:29:32 | b | generic.go:29:7:29:33 | call to genericIdentity1 |
| generic.go:30:2:30:2 | assignment to d | generic.go:31:2:31:2 | skip |
| generic.go:30:2:30:2 | skip | generic.go:30:7:30:22 | genericIdentity1 |
| generic.go:30:7:30:22 | genericIdentity1 | generic.go:30:24:30:24 | c |
| generic.go:30:7:30:25 | call to genericIdentity1 | generic.go:30:2:30:2 | assignment to d |
| generic.go:30:7:30:25 | call to genericIdentity1 | generic.go:35:1:35:1 | exit |
| generic.go:30:24:30:24 | c | generic.go:30:7:30:25 | call to genericIdentity1 |
| generic.go:31:2:31:2 | assignment to e | generic.go:31:2:31:53 | ... := ...[1] |
| generic.go:31:2:31:2 | skip | generic.go:31:5:31:5 | skip |
| generic.go:31:2:31:53 | ... := ...[0] | generic.go:31:2:31:2 | assignment to e |
| generic.go:31:2:31:53 | ... := ...[1] | generic.go:31:5:31:5 | assignment to f |
| generic.go:31:5:31:5 | assignment to f | generic.go:32:2:32:2 | skip |
| generic.go:31:5:31:5 | skip | generic.go:31:10:31:25 | genericIdentity2 |
| generic.go:31:10:31:25 | genericIdentity2 | generic.go:31:43:31:43 | d |
| generic.go:31:10:31:53 | call to genericIdentity2 | generic.go:31:2:31:53 | ... := ...[0] |
| generic.go:31:10:31:53 | call to genericIdentity2 | generic.go:35:1:35:1 | exit |
| generic.go:31:43:31:43 | d | generic.go:31:46:31:52 | "hello" |
| generic.go:31:46:31:52 | "hello" | generic.go:31:10:31:53 | call to genericIdentity2 |
| generic.go:32:2:32:2 | assignment to g | generic.go:32:2:32:31 | ... := ...[1] |
| generic.go:32:2:32:2 | skip | generic.go:32:5:32:5 | skip |
| generic.go:32:2:32:31 | ... := ...[0] | generic.go:32:2:32:2 | assignment to g |
| generic.go:32:2:32:31 | ... := ...[1] | generic.go:32:5:32:5 | assignment to h |
| generic.go:32:5:32:5 | assignment to h | generic.go:33:2:33:2 | skip |
| generic.go:32:5:32:5 | skip | generic.go:32:10:32:25 | genericIdentity2 |
| generic.go:32:10:32:25 | genericIdentity2 | generic.go:32:27:32:27 | e |
| generic.go:32:10:32:31 | call to genericIdentity2 | generic.go:32:2:32:31 | ... := ...[0] |
| generic.go:32:10:32:31 | call to genericIdentity2 | generic.go:35:1:35:1 | exit |
| generic.go:32:27:32:27 | e | generic.go:32:30:32:30 | f |
| generic.go:32:30:32:30 | f | generic.go:32:10:32:31 | call to genericIdentity2 |
| generic.go:33:2:33:2 | skip | generic.go:33:6:33:6 | g |
| generic.go:33:6:33:6 | g | generic.go:34:2:34:2 | skip |
| generic.go:34:2:34:2 | skip | generic.go:34:6:34:6 | h |
| generic.go:34:6:34:6 | h | generic.go:35:1:35:1 | exit |
| hello.go:0:0:0:0 | entry | hello.go:3:1:3:12 | skip | | hello.go:0:0:0:0 | entry | hello.go:3:1:3:12 | skip |
| hello.go:3:1:3:12 | skip | hello.go:5:7:5:13 | skip | | hello.go:3:1:3:12 | skip | hello.go:5:7:5:13 | skip |
| hello.go:5:7:5:13 | assignment to message | hello.go:7:6:7:13 | skip | | hello.go:5:7:5:13 | assignment to message | hello.go:7:6:7:13 | skip |

Просмотреть файл

@ -495,6 +495,111 @@
| exprs.go:94:16:94:16 | (...) is false | exprs.go:94:21:94:21 | z | | exprs.go:94:16:94:16 | (...) is false | exprs.go:94:21:94:21 | z |
| exprs.go:94:16:94:16 | (...) is true | exprs.go:94:9:94:21 | ...\|\|... | | exprs.go:94:16:94:16 | (...) is true | exprs.go:94:9:94:21 | ...\|\|... |
| exprs.go:94:21:94:21 | z | exprs.go:94:9:94:21 | ...\|\|... | | exprs.go:94:21:94:21 | z | exprs.go:94:9:94:21 | ...\|\|... |
| generic.go:0:0:0:0 | entry | generic.go:3:1:5:1 | skip |
| generic.go:3:1:5:1 | skip | generic.go:7:28:7:35 | skip |
| generic.go:7:1:7:1 | entry | generic.go:7:7:7:7 | argument corresponding to g |
| generic.go:7:1:7:55 | function declaration | generic.go:9:1:12:1 | skip |
| generic.go:7:7:7:7 | argument corresponding to g | generic.go:7:7:7:7 | initialization of g |
| generic.go:7:7:7:7 | initialization of g | generic.go:7:37:7:37 | argument corresponding to u |
| generic.go:7:28:7:35 | skip | generic.go:7:1:7:55 | function declaration |
| generic.go:7:37:7:37 | argument corresponding to u | generic.go:7:37:7:37 | initialization of u |
| generic.go:7:37:7:37 | initialization of u | generic.go:7:53:7:53 | u |
| generic.go:7:46:7:53 | return statement | generic.go:7:55:7:55 | exit |
| generic.go:7:53:7:53 | u | generic.go:7:46:7:53 | return statement |
| generic.go:9:1:12:1 | skip | generic.go:14:31:14:39 | skip |
| generic.go:14:1:14:1 | entry | generic.go:14:7:14:7 | argument corresponding to g |
| generic.go:14:1:14:59 | function declaration | generic.go:16:6:16:21 | skip |
| generic.go:14:7:14:7 | argument corresponding to g | generic.go:14:7:14:7 | initialization of g |
| generic.go:14:7:14:7 | initialization of g | generic.go:14:41:14:41 | argument corresponding to u |
| generic.go:14:31:14:39 | skip | generic.go:14:1:14:59 | function declaration |
| generic.go:14:41:14:41 | argument corresponding to u | generic.go:14:41:14:41 | initialization of u |
| generic.go:14:41:14:41 | initialization of u | generic.go:14:57:14:57 | u |
| generic.go:14:50:14:57 | return statement | generic.go:14:59:14:59 | exit |
| generic.go:14:57:14:57 | u | generic.go:14:50:14:57 | return statement |
| generic.go:16:1:16:1 | entry | generic.go:16:30:16:30 | argument corresponding to t |
| generic.go:16:1:18:1 | function declaration | generic.go:20:6:20:21 | skip |
| generic.go:16:6:16:21 | skip | generic.go:16:1:18:1 | function declaration |
| generic.go:16:30:16:30 | argument corresponding to t | generic.go:16:30:16:30 | initialization of t |
| generic.go:16:30:16:30 | initialization of t | generic.go:17:9:17:9 | t |
| generic.go:17:2:17:9 | return statement | generic.go:18:1:18:1 | exit |
| generic.go:17:9:17:9 | t | generic.go:17:2:17:9 | return statement |
| generic.go:20:1:20:1 | entry | generic.go:20:33:20:33 | argument corresponding to s |
| generic.go:20:1:22:1 | function declaration | generic.go:24:6:24:12 | skip |
| generic.go:20:6:20:21 | skip | generic.go:20:1:22:1 | function declaration |
| generic.go:20:33:20:33 | argument corresponding to s | generic.go:20:33:20:33 | initialization of s |
| generic.go:20:33:20:33 | initialization of s | generic.go:20:38:20:38 | argument corresponding to t |
| generic.go:20:38:20:38 | argument corresponding to t | generic.go:20:38:20:38 | initialization of t |
| generic.go:20:38:20:38 | initialization of t | generic.go:21:9:21:9 | s |
| generic.go:21:2:21:12 | return statement | generic.go:22:1:22:1 | exit |
| generic.go:21:9:21:9 | s | generic.go:21:12:21:12 | t |
| generic.go:21:12:21:12 | t | generic.go:21:2:21:12 | return statement |
| generic.go:24:1:24:1 | entry | generic.go:25:2:25:4 | skip |
| generic.go:24:1:35:1 | function declaration | generic.go:0:0:0:0 | exit |
| generic.go:24:6:24:12 | skip | generic.go:24:1:35:1 | function declaration |
| generic.go:25:2:25:4 | assignment to gs1 | generic.go:26:2:26:2 | skip |
| generic.go:25:2:25:4 | skip | generic.go:25:9:25:35 | struct literal |
| generic.go:25:9:25:35 | struct literal | generic.go:25:32:25:34 | "x" |
| generic.go:25:32:25:34 | "x" | generic.go:25:32:25:34 | init of "x" |
| generic.go:25:32:25:34 | init of "x" | generic.go:25:2:25:4 | assignment to gs1 |
| generic.go:26:2:26:2 | assignment to a | generic.go:27:2:27:4 | skip |
| generic.go:26:2:26:2 | skip | generic.go:26:7:26:9 | gs1 |
| generic.go:26:7:26:9 | gs1 | generic.go:26:7:26:18 | selection of Identity |
| generic.go:26:7:26:18 | selection of Identity | generic.go:26:20:26:26 | "hello" |
| generic.go:26:7:26:27 | call to Identity | generic.go:26:2:26:2 | assignment to a |
| generic.go:26:7:26:27 | call to Identity | generic.go:35:1:35:1 | exit |
| generic.go:26:20:26:26 | "hello" | generic.go:26:7:26:27 | call to Identity |
| generic.go:27:2:27:4 | assignment to gs2 | generic.go:28:2:28:2 | skip |
| generic.go:27:2:27:4 | skip | generic.go:27:9:27:48 | struct literal |
| generic.go:27:9:27:48 | struct literal | generic.go:27:40:27:42 | "y" |
| generic.go:27:40:27:42 | "y" | generic.go:27:40:27:42 | init of "y" |
| generic.go:27:40:27:42 | init of "y" | generic.go:27:45:27:47 | "z" |
| generic.go:27:45:27:47 | "z" | generic.go:27:45:27:47 | init of "z" |
| generic.go:27:45:27:47 | init of "z" | generic.go:27:2:27:4 | assignment to gs2 |
| generic.go:28:2:28:2 | assignment to b | generic.go:29:2:29:2 | skip |
| generic.go:28:2:28:2 | skip | generic.go:28:7:28:9 | gs2 |
| generic.go:28:7:28:9 | gs2 | generic.go:28:7:28:19 | selection of Identity1 |
| generic.go:28:7:28:19 | selection of Identity1 | generic.go:28:21:28:21 | a |
| generic.go:28:7:28:22 | call to Identity1 | generic.go:28:2:28:2 | assignment to b |
| generic.go:28:7:28:22 | call to Identity1 | generic.go:35:1:35:1 | exit |
| generic.go:28:21:28:21 | a | generic.go:28:7:28:22 | call to Identity1 |
| generic.go:29:2:29:2 | assignment to c | generic.go:30:2:30:2 | skip |
| generic.go:29:2:29:2 | skip | generic.go:29:7:29:22 | genericIdentity1 |
| generic.go:29:7:29:22 | genericIdentity1 | generic.go:29:32:29:32 | b |
| generic.go:29:7:29:33 | call to genericIdentity1 | generic.go:29:2:29:2 | assignment to c |
| generic.go:29:7:29:33 | call to genericIdentity1 | generic.go:35:1:35:1 | exit |
| generic.go:29:32:29:32 | b | generic.go:29:7:29:33 | call to genericIdentity1 |
| generic.go:30:2:30:2 | assignment to d | generic.go:31:2:31:2 | skip |
| generic.go:30:2:30:2 | skip | generic.go:30:7:30:22 | genericIdentity1 |
| generic.go:30:7:30:22 | genericIdentity1 | generic.go:30:24:30:24 | c |
| generic.go:30:7:30:25 | call to genericIdentity1 | generic.go:30:2:30:2 | assignment to d |
| generic.go:30:7:30:25 | call to genericIdentity1 | generic.go:35:1:35:1 | exit |
| generic.go:30:24:30:24 | c | generic.go:30:7:30:25 | call to genericIdentity1 |
| generic.go:31:2:31:2 | assignment to e | generic.go:31:2:31:53 | ... := ...[1] |
| generic.go:31:2:31:2 | skip | generic.go:31:5:31:5 | skip |
| generic.go:31:2:31:53 | ... := ...[0] | generic.go:31:2:31:2 | assignment to e |
| generic.go:31:2:31:53 | ... := ...[1] | generic.go:31:5:31:5 | assignment to f |
| generic.go:31:5:31:5 | assignment to f | generic.go:32:2:32:2 | skip |
| generic.go:31:5:31:5 | skip | generic.go:31:10:31:25 | genericIdentity2 |
| generic.go:31:10:31:25 | genericIdentity2 | generic.go:31:43:31:43 | d |
| generic.go:31:10:31:53 | call to genericIdentity2 | generic.go:31:2:31:53 | ... := ...[0] |
| generic.go:31:10:31:53 | call to genericIdentity2 | generic.go:35:1:35:1 | exit |
| generic.go:31:43:31:43 | d | generic.go:31:46:31:52 | "hello" |
| generic.go:31:46:31:52 | "hello" | generic.go:31:10:31:53 | call to genericIdentity2 |
| generic.go:32:2:32:2 | assignment to g | generic.go:32:2:32:31 | ... := ...[1] |
| generic.go:32:2:32:2 | skip | generic.go:32:5:32:5 | skip |
| generic.go:32:2:32:31 | ... := ...[0] | generic.go:32:2:32:2 | assignment to g |
| generic.go:32:2:32:31 | ... := ...[1] | generic.go:32:5:32:5 | assignment to h |
| generic.go:32:5:32:5 | assignment to h | generic.go:33:2:33:2 | skip |
| generic.go:32:5:32:5 | skip | generic.go:32:10:32:25 | genericIdentity2 |
| generic.go:32:10:32:25 | genericIdentity2 | generic.go:32:27:32:27 | e |
| generic.go:32:10:32:31 | call to genericIdentity2 | generic.go:32:2:32:31 | ... := ...[0] |
| generic.go:32:10:32:31 | call to genericIdentity2 | generic.go:35:1:35:1 | exit |
| generic.go:32:27:32:27 | e | generic.go:32:30:32:30 | f |
| generic.go:32:30:32:30 | f | generic.go:32:10:32:31 | call to genericIdentity2 |
| generic.go:33:2:33:2 | skip | generic.go:33:6:33:6 | g |
| generic.go:33:6:33:6 | g | generic.go:34:2:34:2 | skip |
| generic.go:34:2:34:2 | skip | generic.go:34:6:34:6 | h |
| generic.go:34:6:34:6 | h | generic.go:35:1:35:1 | exit |
| hello.go:0:0:0:0 | entry | hello.go:3:1:3:12 | skip | | hello.go:0:0:0:0 | entry | hello.go:3:1:3:12 | skip |
| hello.go:3:1:3:12 | skip | hello.go:5:7:5:13 | skip | | hello.go:3:1:3:12 | skip | hello.go:5:7:5:13 | skip |
| hello.go:5:7:5:13 | assignment to message | hello.go:7:6:7:13 | skip | | hello.go:5:7:5:13 | assignment to message | hello.go:7:6:7:13 | skip |

Просмотреть файл

@ -0,0 +1,35 @@
package main
type GenericStruct1[T any] struct {
Field T
}
func (g GenericStruct1[U]) Identity(u U) U { return u }
type GenericStruct2[S, T any] struct {
Field1 S
Field2 T
}
func (g GenericStruct2[U, _]) Identity1(u U) U { return u }
func genericIdentity1[T any](t T) T {
return t
}
func genericIdentity2[S, T any](s S, t T) (S, T) {
return s, t
}
func generic() {
gs1 := GenericStruct1[string]{"x"}
a := gs1.Identity("hello")
gs2 := GenericStruct2[string, string]{"y", "z"}
b := gs2.Identity1(a)
c := genericIdentity1[string](b)
d := genericIdentity1(c)
e, f := genericIdentity2[string, string](d, "hello")
g, h := genericIdentity2(e, f)
_ = g
_ = h
}

Просмотреть файл

Просмотреть файл

@ -0,0 +1,2 @@
import go
import TestUtilities.InlineFlowTest

Просмотреть файл

@ -0,0 +1,68 @@
package main
func genericSource[T any](t T) string {
x := source()
return x
}
func genericIdentity[T any](t T) T {
return t
}
func genericSink1[T any](t T, u string) {
sink(u) // $ hasValueFlow="u"
}
func genericSink2[T any](t T, u string) {
sink(u) // $ hasValueFlow="u"
}
func genericSink3[T any](t T, u string) {
sink(u) // $ hasValueFlow="u"
}
func test() {
var x struct {
x1 int
x2 string
}
{
s := genericSource(x)
sink(s) // $ hasValueFlow="s"
}
{
s := genericSource[int8](2)
sink(s) // $ hasValueFlow="s"
}
{
f := genericSource[int8]
s := f(2)
sink(s) // $ hasValueFlow="s"
}
{
s := genericIdentity(source())
sink(s) // $ hasValueFlow="s"
}
{
s := genericIdentity[string](source())
sink(s) // $ hasValueFlow="s"
}
{
f := genericIdentity[string]
s := f(source())
sink(s) // $ hasValueFlow="s"
}
{
s := source()
genericSink1(x, s)
}
{
s := source()
genericSink2[uint16](3, s)
}
{
s := source()
f := genericSink3[uint16]
f(3, s)
}
}

Просмотреть файл

@ -0,0 +1,139 @@
package main
func source() string {
return "untrusted data"
}
func sink(string) {
}
type GenericStruct1[T any] struct {
Field T
}
func (g GenericStruct1[U]) Identity(u U) U { return u }
func (g GenericStruct1[U]) Getter() U { return g.Field }
func (g GenericStruct1[U]) Setter(u U) { g.Field = u }
type GenericStruct2[S, T any] struct {
Field1 S
Field2 T
}
func (g GenericStruct2[U, _]) Identity1(u U) U { return u }
func (g GenericStruct2[U, _]) Getter1() U { return g.Field1 }
func (g GenericStruct2[U, _]) Setter1(u U) { g.Field1 = u }
func (g GenericStruct2[_, V]) Identity2(v V) V { return v }
func (g GenericStruct2[_, V]) Getter2() V { return g.Field2 }
func (g GenericStruct2[_, V]) Setter2(v V) { g.Field2 = v }
func main() {
{
gs1 := GenericStruct1[string]{source()}
sink(gs1.Field) // $ hasValueFlow="selection of Field"
}
{
gs1 := GenericStruct1[string]{""}
sink(gs1.Identity(source())) // $ hasValueFlow="call to Identity"
}
{
gs1 := GenericStruct1[string]{""}
f := gs1.Identity
sink(f(source())) // $ hasValueFlow="call to f"
}
{
gs1 := GenericStruct1[string]{""}
gs1.Field = source()
sink(gs1.Getter()) // $ hasValueFlow="call to Getter"
}
{
gs1 := GenericStruct1[string]{""}
gs1.Field = source()
f := gs1.Getter
sink(f()) // $ MISSING: hasValueFlow="call to f"
}
{
gs1 := GenericStruct1[string]{""}
gs1.Setter(source())
sink(gs1.Field) // $ hasValueFlow="selection of Field"
}
{
gs1 := GenericStruct1[string]{""}
f := gs1.Setter
f(source())
sink(gs1.Field) // $ MISSING: hasValueFlow="selection of Field"
}
{
gs2 := GenericStruct2[string, string]{source(), ""}
sink(gs2.Field1) // $ hasValueFlow="selection of Field1"
}
{
gs2 := GenericStruct2[string, string]{"", ""}
sink(gs2.Identity1(source())) // $ hasValueFlow="call to Identity1"
}
{
gs2 := GenericStruct2[string, string]{"", ""}
f := gs2.Identity1
sink(f(source())) // $ hasValueFlow="call to f"
}
{
gs2 := GenericStruct2[string, string]{"", ""}
gs2.Field1 = source()
sink(gs2.Getter1()) // $ hasValueFlow="call to Getter1"
}
{
gs2 := GenericStruct2[string, string]{"", ""}
gs2.Field1 = source()
f := gs2.Getter1
sink(f()) // $ MISSING: hasValueFlow="call to f"
}
{
gs2 := GenericStruct2[string, string]{"", ""}
gs2.Setter1(source())
sink(gs2.Field1) // $ hasValueFlow="selection of Field1"
}
{
gs2 := GenericStruct2[string, string]{"", ""}
f := gs2.Setter1
f(source())
sink(gs2.Field1) // $ MISSING: hasValueFlow="selection of Field1"
}
{
gs2 := GenericStruct2[string, string]{"", source()}
sink(gs2.Field2) // $ hasValueFlow="selection of Field2"
}
{
gs2 := GenericStruct2[string, string]{"", ""}
sink(gs2.Identity2(source())) // $ hasValueFlow="call to Identity2"
}
{
gs2 := GenericStruct2[string, string]{"", ""}
f := gs2.Identity2
sink(f(source())) // $ hasValueFlow="call to f"
}
{
gs2 := GenericStruct2[string, string]{"", ""}
gs2.Field2 = source()
sink(gs2.Getter2()) // $ hasValueFlow="call to Getter2"
}
{
gs2 := GenericStruct2[string, string]{"", ""}
gs2.Field2 = source()
f := gs2.Getter2
sink(f()) // $ MISSING: hasValueFlow="call to f"
}
{
gs2 := GenericStruct2[string, string]{"", ""}
gs2.Setter2(source())
sink(gs2.Field2) // $ hasValueFlow="selection of Field2"
}
{
gs2 := GenericStruct2[string, string]{"", ""}
f := gs2.Setter2
f(source())
sink(gs2.Field2) // $ MISSING: hasValueFlow="selection of Field2"
}
}

Просмотреть файл

@ -8,7 +8,7 @@ edges
| test.go:30:20:30:26 | selection of c : subBindMe | test.go:30:13:30:29 | type conversion | | test.go:30:20:30:26 | selection of c : subBindMe | test.go:30:13:30:29 | type conversion |
| test.go:35:20:35:42 | call to Cookie : string | test.go:35:13:35:43 | type conversion | | test.go:35:20:35:42 | call to Cookie : string | test.go:35:13:35:43 | type conversion |
| test.go:40:20:40:31 | call to Data : map type | test.go:40:13:40:52 | type conversion | | test.go:40:20:40:31 | call to Data : map type | test.go:40:13:40:52 | type conversion |
| test.go:45:20:45:43 | call to GetData : interface type | test.go:45:13:45:53 | type conversion | | test.go:45:20:45:43 | call to GetData : basic interface type | test.go:45:13:45:53 | type conversion |
| test.go:50:20:50:42 | call to Header : string | test.go:50:13:50:43 | type conversion | | test.go:50:20:50:42 | call to Header : string | test.go:50:13:50:43 | type conversion |
| test.go:55:20:55:41 | call to Param : string | test.go:55:13:55:42 | type conversion | | test.go:55:20:55:41 | call to Param : string | test.go:55:13:55:42 | type conversion |
| test.go:60:20:60:33 | call to Params : map type | test.go:60:13:60:45 | type conversion | | test.go:60:20:60:33 | call to Params : map type | test.go:60:13:60:45 | type conversion |
@ -153,7 +153,7 @@ nodes
| test.go:40:13:40:52 | type conversion | semmle.label | type conversion | | test.go:40:13:40:52 | type conversion | semmle.label | type conversion |
| test.go:40:20:40:31 | call to Data : map type | semmle.label | call to Data : map type | | test.go:40:20:40:31 | call to Data : map type | semmle.label | call to Data : map type |
| test.go:45:13:45:53 | type conversion | semmle.label | type conversion | | test.go:45:13:45:53 | type conversion | semmle.label | type conversion |
| test.go:45:20:45:43 | call to GetData : interface type | semmle.label | call to GetData : interface type | | test.go:45:20:45:43 | call to GetData : basic interface type | semmle.label | call to GetData : basic interface type |
| test.go:50:13:50:43 | type conversion | semmle.label | type conversion | | test.go:50:13:50:43 | type conversion | semmle.label | type conversion |
| test.go:50:20:50:42 | call to Header : string | semmle.label | call to Header : string | | test.go:50:20:50:42 | call to Header : string | semmle.label | call to Header : string |
| test.go:55:13:55:42 | type conversion | semmle.label | type conversion | | test.go:55:13:55:42 | type conversion | semmle.label | type conversion |
@ -267,7 +267,7 @@ subpaths
| test.go:30:13:30:29 | type conversion | test.go:26:6:26:10 | definition of bound : bindMe | test.go:30:13:30:29 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:26:6:26:10 | definition of bound | user-provided value | test.go:0:0:0:0 | test.go | | | test.go:30:13:30:29 | type conversion | test.go:26:6:26:10 | definition of bound : bindMe | test.go:30:13:30:29 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:26:6:26:10 | definition of bound | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:35:13:35:43 | type conversion | test.go:35:20:35:42 | call to Cookie : string | test.go:35:13:35:43 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:35:20:35:42 | call to Cookie | user-provided value | test.go:0:0:0:0 | test.go | | | test.go:35:13:35:43 | type conversion | test.go:35:20:35:42 | call to Cookie : string | test.go:35:13:35:43 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:35:20:35:42 | call to Cookie | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:40:13:40:52 | type conversion | test.go:40:20:40:31 | call to Data : map type | test.go:40:13:40:52 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:40:20:40:31 | call to Data | user-provided value | test.go:0:0:0:0 | test.go | | | test.go:40:13:40:52 | type conversion | test.go:40:20:40:31 | call to Data : map type | test.go:40:13:40:52 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:40:20:40:31 | call to Data | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:45:13:45:53 | type conversion | test.go:45:20:45:43 | call to GetData : interface type | test.go:45:13:45:53 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:45:20:45:43 | call to GetData | user-provided value | test.go:0:0:0:0 | test.go | | | test.go:45:13:45:53 | type conversion | test.go:45:20:45:43 | call to GetData : basic interface type | test.go:45:13:45:53 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:45:20:45:43 | call to GetData | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:50:13:50:43 | type conversion | test.go:50:20:50:42 | call to Header : string | test.go:50:13:50:43 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:50:20:50:42 | call to Header | user-provided value | test.go:0:0:0:0 | test.go | | | test.go:50:13:50:43 | type conversion | test.go:50:20:50:42 | call to Header : string | test.go:50:13:50:43 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:50:20:50:42 | call to Header | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:55:13:55:42 | type conversion | test.go:55:20:55:41 | call to Param : string | test.go:55:13:55:42 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:55:20:55:41 | call to Param | user-provided value | test.go:0:0:0:0 | test.go | | | test.go:55:13:55:42 | type conversion | test.go:55:20:55:41 | call to Param : string | test.go:55:13:55:42 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:55:20:55:41 | call to Param | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:60:13:60:45 | type conversion | test.go:60:20:60:33 | call to Params : map type | test.go:60:13:60:45 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:60:20:60:33 | call to Params | user-provided value | test.go:0:0:0:0 | test.go | | | test.go:60:13:60:45 | type conversion | test.go:60:20:60:33 | call to Params : map type | test.go:60:13:60:45 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:60:20:60:33 | call to Params | user-provided value | test.go:0:0:0:0 | test.go | |

Просмотреть файл

@ -9,13 +9,13 @@ edges
| test.go:82:22:82:26 | &... : pointer type | test.go:83:13:83:30 | type conversion | | test.go:82:22:82:26 | &... : pointer type | test.go:83:13:83:30 | type conversion |
| test.go:86:21:86:25 | &... : pointer type | test.go:87:13:87:30 | type conversion | | test.go:86:21:86:25 | &... : pointer type | test.go:87:13:87:30 | type conversion |
| test.go:92:20:92:36 | call to Value : string | test.go:92:13:92:37 | type conversion | | test.go:92:20:92:36 | call to Value : string | test.go:92:13:92:37 | type conversion |
| test.go:93:20:93:39 | call to RawValue : interface type | test.go:93:13:93:49 | type conversion | | test.go:93:20:93:39 | call to RawValue : basic interface type | test.go:93:13:93:49 | type conversion |
| test.go:94:20:94:37 | call to String : string | test.go:94:13:94:38 | type conversion | | test.go:94:20:94:37 | call to String : string | test.go:94:13:94:38 | type conversion |
| test.go:95:20:95:36 | call to Value : string | test.go:95:13:95:37 | type conversion | | test.go:95:20:95:36 | call to Value : string | test.go:95:13:95:37 | type conversion |
| test.go:96:20:96:39 | call to RawValue : interface type | test.go:96:13:96:49 | type conversion | | test.go:96:20:96:39 | call to RawValue : basic interface type | test.go:96:13:96:49 | type conversion |
| test.go:97:20:97:37 | call to String : string | test.go:97:13:97:38 | type conversion | | test.go:97:20:97:37 | call to String : string | test.go:97:13:97:38 | type conversion |
| test.go:98:20:98:37 | call to Value : string | test.go:98:13:98:38 | type conversion | | test.go:98:20:98:37 | call to Value : string | test.go:98:13:98:38 | type conversion |
| test.go:99:20:99:40 | call to RawValue : interface type | test.go:99:13:99:50 | type conversion | | test.go:99:20:99:40 | call to RawValue : basic interface type | test.go:99:13:99:50 | type conversion |
| test.go:100:20:100:38 | call to String : string | test.go:100:13:100:39 | type conversion | | test.go:100:20:100:38 | call to String : string | test.go:100:13:100:39 | type conversion |
| test.go:106:9:106:13 | &... : pointer type | test.go:107:13:107:33 | type conversion | | test.go:106:9:106:13 | &... : pointer type | test.go:107:13:107:33 | type conversion |
| test.go:106:9:106:13 | &... : pointer type | test.go:107:20:107:26 | implicit dereference : MyStruct | | test.go:106:9:106:13 | &... : pointer type | test.go:107:20:107:26 | implicit dereference : MyStruct |
@ -52,19 +52,19 @@ nodes
| test.go:92:13:92:37 | type conversion | semmle.label | type conversion | | test.go:92:13:92:37 | type conversion | semmle.label | type conversion |
| test.go:92:20:92:36 | call to Value : string | semmle.label | call to Value : string | | test.go:92:20:92:36 | call to Value : string | semmle.label | call to Value : string |
| test.go:93:13:93:49 | type conversion | semmle.label | type conversion | | test.go:93:13:93:49 | type conversion | semmle.label | type conversion |
| test.go:93:20:93:39 | call to RawValue : interface type | semmle.label | call to RawValue : interface type | | test.go:93:20:93:39 | call to RawValue : basic interface type | semmle.label | call to RawValue : basic interface type |
| test.go:94:13:94:38 | type conversion | semmle.label | type conversion | | test.go:94:13:94:38 | type conversion | semmle.label | type conversion |
| test.go:94:20:94:37 | call to String : string | semmle.label | call to String : string | | test.go:94:20:94:37 | call to String : string | semmle.label | call to String : string |
| test.go:95:13:95:37 | type conversion | semmle.label | type conversion | | test.go:95:13:95:37 | type conversion | semmle.label | type conversion |
| test.go:95:20:95:36 | call to Value : string | semmle.label | call to Value : string | | test.go:95:20:95:36 | call to Value : string | semmle.label | call to Value : string |
| test.go:96:13:96:49 | type conversion | semmle.label | type conversion | | test.go:96:13:96:49 | type conversion | semmle.label | type conversion |
| test.go:96:20:96:39 | call to RawValue : interface type | semmle.label | call to RawValue : interface type | | test.go:96:20:96:39 | call to RawValue : basic interface type | semmle.label | call to RawValue : basic interface type |
| test.go:97:13:97:38 | type conversion | semmle.label | type conversion | | test.go:97:13:97:38 | type conversion | semmle.label | type conversion |
| test.go:97:20:97:37 | call to String : string | semmle.label | call to String : string | | test.go:97:20:97:37 | call to String : string | semmle.label | call to String : string |
| test.go:98:13:98:38 | type conversion | semmle.label | type conversion | | test.go:98:13:98:38 | type conversion | semmle.label | type conversion |
| test.go:98:20:98:37 | call to Value : string | semmle.label | call to Value : string | | test.go:98:20:98:37 | call to Value : string | semmle.label | call to Value : string |
| test.go:99:13:99:50 | type conversion | semmle.label | type conversion | | test.go:99:13:99:50 | type conversion | semmle.label | type conversion |
| test.go:99:20:99:40 | call to RawValue : interface type | semmle.label | call to RawValue : interface type | | test.go:99:20:99:40 | call to RawValue : basic interface type | semmle.label | call to RawValue : basic interface type |
| test.go:100:13:100:39 | type conversion | semmle.label | type conversion | | test.go:100:13:100:39 | type conversion | semmle.label | type conversion |
| test.go:100:20:100:38 | call to String : string | semmle.label | call to String : string | | test.go:100:20:100:38 | call to String : string | semmle.label | call to String : string |
| test.go:106:9:106:13 | &... : pointer type | semmle.label | &... : pointer type | | test.go:106:9:106:13 | &... : pointer type | semmle.label | &... : pointer type |
@ -104,13 +104,13 @@ subpaths
| test.go:83:13:83:30 | type conversion | test.go:82:22:82:26 | &... : pointer type | test.go:83:13:83:30 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:82:22:82:26 | &... | stored value | | test.go:83:13:83:30 | type conversion | test.go:82:22:82:26 | &... : pointer type | test.go:83:13:83:30 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:82:22:82:26 | &... | stored value |
| test.go:87:13:87:30 | type conversion | test.go:86:21:86:25 | &... : pointer type | test.go:87:13:87:30 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:86:21:86:25 | &... | stored value | | test.go:87:13:87:30 | type conversion | test.go:86:21:86:25 | &... : pointer type | test.go:87:13:87:30 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:86:21:86:25 | &... | stored value |
| test.go:92:13:92:37 | type conversion | test.go:92:20:92:36 | call to Value : string | test.go:92:13:92:37 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:92:20:92:36 | call to Value | stored value | | test.go:92:13:92:37 | type conversion | test.go:92:20:92:36 | call to Value : string | test.go:92:13:92:37 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:92:20:92:36 | call to Value | stored value |
| test.go:93:13:93:49 | type conversion | test.go:93:20:93:39 | call to RawValue : interface type | test.go:93:13:93:49 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:93:20:93:39 | call to RawValue | stored value | | test.go:93:13:93:49 | type conversion | test.go:93:20:93:39 | call to RawValue : basic interface type | test.go:93:13:93:49 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:93:20:93:39 | call to RawValue | stored value |
| test.go:94:13:94:38 | type conversion | test.go:94:20:94:37 | call to String : string | test.go:94:13:94:38 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:94:20:94:37 | call to String | stored value | | test.go:94:13:94:38 | type conversion | test.go:94:20:94:37 | call to String : string | test.go:94:13:94:38 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:94:20:94:37 | call to String | stored value |
| test.go:95:13:95:37 | type conversion | test.go:95:20:95:36 | call to Value : string | test.go:95:13:95:37 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:95:20:95:36 | call to Value | stored value | | test.go:95:13:95:37 | type conversion | test.go:95:20:95:36 | call to Value : string | test.go:95:13:95:37 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:95:20:95:36 | call to Value | stored value |
| test.go:96:13:96:49 | type conversion | test.go:96:20:96:39 | call to RawValue : interface type | test.go:96:13:96:49 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:96:20:96:39 | call to RawValue | stored value | | test.go:96:13:96:49 | type conversion | test.go:96:20:96:39 | call to RawValue : basic interface type | test.go:96:13:96:49 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:96:20:96:39 | call to RawValue | stored value |
| test.go:97:13:97:38 | type conversion | test.go:97:20:97:37 | call to String : string | test.go:97:13:97:38 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:97:20:97:37 | call to String | stored value | | test.go:97:13:97:38 | type conversion | test.go:97:20:97:37 | call to String : string | test.go:97:13:97:38 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:97:20:97:37 | call to String | stored value |
| test.go:98:13:98:38 | type conversion | test.go:98:20:98:37 | call to Value : string | test.go:98:13:98:38 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:98:20:98:37 | call to Value | stored value | | test.go:98:13:98:38 | type conversion | test.go:98:20:98:37 | call to Value : string | test.go:98:13:98:38 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:98:20:98:37 | call to Value | stored value |
| test.go:99:13:99:50 | type conversion | test.go:99:20:99:40 | call to RawValue : interface type | test.go:99:13:99:50 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:99:20:99:40 | call to RawValue | stored value | | test.go:99:13:99:50 | type conversion | test.go:99:20:99:40 | call to RawValue : basic interface type | test.go:99:13:99:50 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:99:20:99:40 | call to RawValue | stored value |
| test.go:100:13:100:39 | type conversion | test.go:100:20:100:38 | call to String : string | test.go:100:13:100:39 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:100:20:100:38 | call to String | stored value | | test.go:100:13:100:39 | type conversion | test.go:100:20:100:38 | call to String : string | test.go:100:13:100:39 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:100:20:100:38 | call to String | stored value |
| test.go:107:13:107:33 | type conversion | test.go:106:9:106:13 | &... : pointer type | test.go:107:13:107:33 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:106:9:106:13 | &... | stored value | | test.go:107:13:107:33 | type conversion | test.go:106:9:106:13 | &... : pointer type | test.go:107:13:107:33 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:106:9:106:13 | &... | stored value |
| test.go:111:13:111:29 | type conversion | test.go:110:9:110:12 | &... : pointer type | test.go:111:13:111:29 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:110:9:110:12 | &... | stored value | | test.go:111:13:111:29 | type conversion | test.go:110:9:110:12 | &... : pointer type | test.go:111:13:111:29 | type conversion | Stored cross-site scripting vulnerability due to $@. | test.go:110:9:110:12 | &... | stored value |