Skip to content

Commit c95a6ea

Browse files
authored
Merge pull request github#11176 from github/redsun82/swift-opaque-types
Swift: extract opaque types and their decls
2 parents ac5a1d6 + b399d8d commit c95a6ea

28 files changed

+288
-31
lines changed

swift/extractor/translators/DeclTranslator.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,4 +390,15 @@ codeql::IfConfigDecl DeclTranslator::translateIfConfigDecl(const swift::IfConfig
390390
return entry;
391391
}
392392

393+
std::optional<codeql::OpaqueTypeDecl> DeclTranslator::translateOpaqueTypeDecl(
394+
const swift::OpaqueTypeDecl& decl) {
395+
if (auto entry = createNamedEntry(decl)) {
396+
fillTypeDecl(decl, *entry);
397+
entry->naming_declaration = dispatcher.fetchLabel(decl.getNamingDecl());
398+
entry->opaque_generic_params = dispatcher.fetchRepeatedLabels(decl.getOpaqueGenericParams());
399+
return entry;
400+
}
401+
return std::nullopt;
402+
}
403+
393404
} // namespace codeql

swift/extractor/translators/DeclTranslator.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class DeclTranslator : public AstTranslatorBase<DeclTranslator> {
4545
codeql::ImportDecl translateImportDecl(const swift::ImportDecl& decl);
4646
std::optional<codeql::ModuleDecl> translateModuleDecl(const swift::ModuleDecl& decl);
4747
codeql::IfConfigDecl translateIfConfigDecl(const swift::IfConfigDecl& decl);
48+
std::optional<codeql::OpaqueTypeDecl> translateOpaqueTypeDecl(const swift::OpaqueTypeDecl& decl);
4849

4950
private:
5051
std::string mangledName(const swift::ValueDecl& decl);

swift/extractor/translators/TypeTranslator.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,4 +250,12 @@ codeql::ModuleType TypeTranslator::translateModuleType(const swift::ModuleType&
250250
entry.module = dispatcher.fetchLabel(type.getModule());
251251
return entry;
252252
}
253+
254+
codeql::OpaqueTypeArchetypeType TypeTranslator::translateOpaqueTypeArchetypeType(
255+
const swift::OpaqueTypeArchetypeType& type) {
256+
auto entry = createTypeEntry(type);
257+
fillArchetypeType(type, entry);
258+
entry.declaration = dispatcher.fetchLabel(type.getDecl());
259+
return entry;
260+
}
253261
} // namespace codeql

swift/extractor/translators/TypeTranslator.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ class TypeTranslator : public TypeTranslatorBase<TypeTranslator> {
6969
codeql::BuiltinIntegerType translateBuiltinIntegerType(const swift::BuiltinIntegerType& type);
7070
codeql::OpenedArchetypeType translateOpenedArchetypeType(const swift::OpenedArchetypeType& type);
7171
codeql::ModuleType translateModuleType(const swift::ModuleType& type);
72+
codeql::OpaqueTypeArchetypeType translateOpaqueTypeArchetypeType(
73+
const swift::OpaqueTypeArchetypeType& type);
7274

7375
private:
7476
void fillType(const swift::TypeBase& type, codeql::Type& entry);

swift/ql/lib/codeql/swift/generated/Raw.qll

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,12 @@ module Raw {
259259

260260
class OpaqueTypeDecl extends @opaque_type_decl, GenericTypeDecl {
261261
override string toString() { result = "OpaqueTypeDecl" }
262+
263+
ValueDecl getNamingDeclaration() { opaque_type_decls(this, result) }
264+
265+
GenericTypeParamType getOpaqueGenericParam(int index) {
266+
opaque_type_decl_opaque_generic_params(this, index, result)
267+
}
262268
}
263269

264270
class ParamDecl extends @param_decl, VarDecl {
@@ -1477,6 +1483,8 @@ module Raw {
14771483

14781484
class OpaqueTypeArchetypeType extends @opaque_type_archetype_type, ArchetypeType {
14791485
override string toString() { result = "OpaqueTypeArchetypeType" }
1486+
1487+
OpaqueTypeDecl getDeclaration() { opaque_type_archetype_types(this, result) }
14801488
}
14811489

14821490
class OpenedArchetypeType extends @opened_archetype_type, ArchetypeType {

swift/ql/lib/codeql/swift/generated/decl/OpaqueTypeDecl.qll

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,70 @@
22
private import codeql.swift.generated.Synth
33
private import codeql.swift.generated.Raw
44
import codeql.swift.elements.decl.GenericTypeDecl
5+
import codeql.swift.elements.type.GenericTypeParamType
6+
import codeql.swift.elements.decl.ValueDecl
57

68
module Generated {
9+
/**
10+
* A declaration of an opaque type, that is formally equivalent to a given type but abstracts it
11+
* away.
12+
*
13+
* Such a declaration is implicitly given when a declaration is written with an opaque result type,
14+
* for example
15+
* ```
16+
* func opaque() -> some SignedInteger { return 1 }
17+
* ```
18+
* See https://docs.swift.org/swift-book/LanguageGuide/OpaqueTypes.html.
19+
*/
720
class OpaqueTypeDecl extends Synth::TOpaqueTypeDecl, GenericTypeDecl {
821
override string getAPrimaryQlClass() { result = "OpaqueTypeDecl" }
22+
23+
/**
24+
* Gets the naming declaration of this opaque type declaration.
25+
*
26+
* This includes nodes from the "hidden" AST. It can be overridden in subclasses to change the
27+
* behavior of both the `Immediate` and non-`Immediate` versions.
28+
*/
29+
ValueDecl getImmediateNamingDeclaration() {
30+
result =
31+
Synth::convertValueDeclFromRaw(Synth::convertOpaqueTypeDeclToRaw(this)
32+
.(Raw::OpaqueTypeDecl)
33+
.getNamingDeclaration())
34+
}
35+
36+
/**
37+
* Gets the naming declaration of this opaque type declaration.
38+
*/
39+
final ValueDecl getNamingDeclaration() { result = getImmediateNamingDeclaration().resolve() }
40+
41+
/**
42+
* Gets the `index`th opaque generic parameter of this opaque type declaration (0-based).
43+
*
44+
* This includes nodes from the "hidden" AST. It can be overridden in subclasses to change the
45+
* behavior of both the `Immediate` and non-`Immediate` versions.
46+
*/
47+
GenericTypeParamType getImmediateOpaqueGenericParam(int index) {
48+
result =
49+
Synth::convertGenericTypeParamTypeFromRaw(Synth::convertOpaqueTypeDeclToRaw(this)
50+
.(Raw::OpaqueTypeDecl)
51+
.getOpaqueGenericParam(index))
52+
}
53+
54+
/**
55+
* Gets the `index`th opaque generic parameter of this opaque type declaration (0-based).
56+
*/
57+
final GenericTypeParamType getOpaqueGenericParam(int index) {
58+
result = getImmediateOpaqueGenericParam(index).resolve()
59+
}
60+
61+
/**
62+
* Gets any of the opaque generic parameters of this opaque type declaration.
63+
*/
64+
final GenericTypeParamType getAnOpaqueGenericParam() { result = getOpaqueGenericParam(_) }
65+
66+
/**
67+
* Gets the number of opaque generic parameters of this opaque type declaration.
68+
*/
69+
final int getNumberOfOpaqueGenericParams() { result = count(getAnOpaqueGenericParam()) }
970
}
1071
}

swift/ql/lib/codeql/swift/generated/type/OpaqueTypeArchetypeType.qll

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,33 @@
22
private import codeql.swift.generated.Synth
33
private import codeql.swift.generated.Raw
44
import codeql.swift.elements.type.ArchetypeType
5+
import codeql.swift.elements.decl.OpaqueTypeDecl
56

67
module Generated {
8+
/**
9+
* An opaque type, that is a type formally equivalent to an underlying type but abstracting it away.
10+
*
11+
* See https://docs.swift.org/swift-book/LanguageGuide/OpaqueTypes.html.
12+
*/
713
class OpaqueTypeArchetypeType extends Synth::TOpaqueTypeArchetypeType, ArchetypeType {
814
override string getAPrimaryQlClass() { result = "OpaqueTypeArchetypeType" }
15+
16+
/**
17+
* Gets the declaration of this opaque type archetype type.
18+
*
19+
* This includes nodes from the "hidden" AST. It can be overridden in subclasses to change the
20+
* behavior of both the `Immediate` and non-`Immediate` versions.
21+
*/
22+
OpaqueTypeDecl getImmediateDeclaration() {
23+
result =
24+
Synth::convertOpaqueTypeDeclFromRaw(Synth::convertOpaqueTypeArchetypeTypeToRaw(this)
25+
.(Raw::OpaqueTypeArchetypeType)
26+
.getDeclaration())
27+
}
28+
29+
/**
30+
* Gets the declaration of this opaque type archetype type.
31+
*/
32+
final OpaqueTypeDecl getDeclaration() { result = getImmediateDeclaration().resolve() }
933
}
1034
}

swift/ql/lib/swift.dbscheme

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,15 @@ nominal_type_decls( //dir=decl
528528
);
529529

530530
opaque_type_decls( //dir=decl
531-
unique int id: @opaque_type_decl
531+
unique int id: @opaque_type_decl,
532+
int naming_declaration: @value_decl_or_none ref
533+
);
534+
535+
#keyset[id, index]
536+
opaque_type_decl_opaque_generic_params( //dir=decl
537+
int id: @opaque_type_decl ref,
538+
int index: int ref,
539+
int opaque_generic_param: @generic_type_param_type_or_none ref
532540
);
533541

534542
param_decls( //dir=decl
@@ -2222,7 +2230,8 @@ dictionary_types( //dir=type
22222230
;
22232231

22242232
opaque_type_archetype_types( //dir=type
2225-
unique int id: @opaque_type_archetype_type
2233+
unique int id: @opaque_type_archetype_type,
2234+
int declaration: @opaque_type_decl_or_none ref
22262235
);
22272236

22282237
opened_archetype_types( //dir=type
@@ -2389,6 +2398,11 @@ variadic_sequence_types( //dir=type
23892398
| @unspecified_element
23902399
;
23912400

2401+
@opaque_type_decl_or_none =
2402+
@opaque_type_decl
2403+
| @unspecified_element
2404+
;
2405+
23922406
@opaque_value_expr_or_none =
23932407
@opaque_value_expr
23942408
| @unspecified_element

swift/ql/test/TestUtils.qll

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,30 +5,31 @@ predicate toBeTested(Element e) {
55
e instanceof File
66
or
77
exists(ModuleDecl m |
8+
m = e and
89
not m.isBuiltinModule() and
9-
not m.isSystemModule() and
10-
(m = e or m.getInterfaceType() = e)
10+
not m.isSystemModule()
1111
)
1212
or
13-
exists(Locatable loc |
14-
loc.getLocation().getFile().getName().matches("%swift/ql/test%") and
13+
e.(Locatable).getLocation().getFile().getName().matches("%swift/ql/test%")
14+
or
15+
exists(Element tested |
16+
toBeTested(tested) and
1517
(
16-
e = loc
18+
e = tested.(ValueDecl).getInterfaceType()
19+
or
20+
e = tested.(NominalTypeDecl).getType()
21+
or
22+
e = tested.(VarDecl).getType()
23+
or
24+
e = tested.(Expr).getType()
1725
or
18-
exists(Type t |
19-
(e = t or e = t.(ExistentialType).getConstraint() or e = t.getCanonicalType()) and
20-
(
21-
t = loc.(ValueDecl).getInterfaceType()
22-
or
23-
t = loc.(NominalTypeDecl).getType()
24-
or
25-
t = loc.(VarDecl).getType()
26-
or
27-
t = loc.(Expr).getType()
28-
)
29-
)
26+
e = tested.(Type).getCanonicalType()
27+
or
28+
e = tested.(ExistentialType).getConstraint()
29+
or
30+
e.(UnspecifiedElement).getParent() = tested
31+
or
32+
e.(OpaqueTypeDecl).getNamingDeclaration() = tested
3033
)
3134
)
32-
or
33-
toBeTested(e.(UnspecifiedElement).getParent())
3435
}

swift/ql/test/extractor-tests/generated/decl/OpaqueTypeDecl/MISSING_SOURCE.txt

Lines changed: 0 additions & 4 deletions
This file was deleted.

0 commit comments

Comments
 (0)