Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions swift/extractor/translators/DeclTranslator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -390,4 +390,15 @@ codeql::IfConfigDecl DeclTranslator::translateIfConfigDecl(const swift::IfConfig
return entry;
}

std::optional<codeql::OpaqueTypeDecl> DeclTranslator::translateOpaqueTypeDecl(
const swift::OpaqueTypeDecl& decl) {
if (auto entry = createNamedEntry(decl)) {
fillTypeDecl(decl, *entry);
entry->naming_declaration = dispatcher.fetchLabel(decl.getNamingDecl());
entry->opaque_generic_params = dispatcher.fetchRepeatedLabels(decl.getOpaqueGenericParams());
return entry;
}
return std::nullopt;
}

} // namespace codeql
1 change: 1 addition & 0 deletions swift/extractor/translators/DeclTranslator.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class DeclTranslator : public AstTranslatorBase<DeclTranslator> {
codeql::ImportDecl translateImportDecl(const swift::ImportDecl& decl);
std::optional<codeql::ModuleDecl> translateModuleDecl(const swift::ModuleDecl& decl);
codeql::IfConfigDecl translateIfConfigDecl(const swift::IfConfigDecl& decl);
std::optional<codeql::OpaqueTypeDecl> translateOpaqueTypeDecl(const swift::OpaqueTypeDecl& decl);

private:
std::string mangledName(const swift::ValueDecl& decl);
Expand Down
8 changes: 8 additions & 0 deletions swift/extractor/translators/TypeTranslator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,4 +250,12 @@ codeql::ModuleType TypeTranslator::translateModuleType(const swift::ModuleType&
entry.module = dispatcher.fetchLabel(type.getModule());
return entry;
}

codeql::OpaqueTypeArchetypeType TypeTranslator::translateOpaqueTypeArchetypeType(
const swift::OpaqueTypeArchetypeType& type) {
auto entry = createTypeEntry(type);
fillArchetypeType(type, entry);
entry.declaration = dispatcher.fetchLabel(type.getDecl());
return entry;
}
} // namespace codeql
2 changes: 2 additions & 0 deletions swift/extractor/translators/TypeTranslator.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ class TypeTranslator : public TypeTranslatorBase<TypeTranslator> {
codeql::BuiltinIntegerType translateBuiltinIntegerType(const swift::BuiltinIntegerType& type);
codeql::OpenedArchetypeType translateOpenedArchetypeType(const swift::OpenedArchetypeType& type);
codeql::ModuleType translateModuleType(const swift::ModuleType& type);
codeql::OpaqueTypeArchetypeType translateOpaqueTypeArchetypeType(
const swift::OpaqueTypeArchetypeType& type);

private:
void fillType(const swift::TypeBase& type, codeql::Type& entry);
Expand Down
8 changes: 8 additions & 0 deletions swift/ql/lib/codeql/swift/generated/Raw.qll
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,12 @@ module Raw {

class OpaqueTypeDecl extends @opaque_type_decl, GenericTypeDecl {
override string toString() { result = "OpaqueTypeDecl" }

ValueDecl getNamingDeclaration() { opaque_type_decls(this, result) }

GenericTypeParamType getOpaqueGenericParam(int index) {
opaque_type_decl_opaque_generic_params(this, index, result)
}
}

class ParamDecl extends @param_decl, VarDecl {
Expand Down Expand Up @@ -1477,6 +1483,8 @@ module Raw {

class OpaqueTypeArchetypeType extends @opaque_type_archetype_type, ArchetypeType {
override string toString() { result = "OpaqueTypeArchetypeType" }

OpaqueTypeDecl getDeclaration() { opaque_type_archetype_types(this, result) }
}

class OpenedArchetypeType extends @opened_archetype_type, ArchetypeType {
Expand Down
61 changes: 61 additions & 0 deletions swift/ql/lib/codeql/swift/generated/decl/OpaqueTypeDecl.qll
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,70 @@
private import codeql.swift.generated.Synth
private import codeql.swift.generated.Raw
import codeql.swift.elements.decl.GenericTypeDecl
import codeql.swift.elements.type.GenericTypeParamType
import codeql.swift.elements.decl.ValueDecl

module Generated {
/**
* A declaration of an opaque type, that is formally equivalent to a given type but abstracts it
* away.
*
* Such a declaration is implicitly given when a declaration is written with an opaque result type,
* for example
* ```
* func opaque() -> some SignedInteger { return 1 }
* ```
* See https://docs.swift.org/swift-book/LanguageGuide/OpaqueTypes.html.
*/
class OpaqueTypeDecl extends Synth::TOpaqueTypeDecl, GenericTypeDecl {
override string getAPrimaryQlClass() { result = "OpaqueTypeDecl" }

/**
* Gets the naming declaration of this opaque type declaration.
*
* This includes nodes from the "hidden" AST. It can be overridden in subclasses to change the
* behavior of both the `Immediate` and non-`Immediate` versions.
*/
ValueDecl getImmediateNamingDeclaration() {
result =
Synth::convertValueDeclFromRaw(Synth::convertOpaqueTypeDeclToRaw(this)
.(Raw::OpaqueTypeDecl)
.getNamingDeclaration())
}

/**
* Gets the naming declaration of this opaque type declaration.
*/
final ValueDecl getNamingDeclaration() { result = getImmediateNamingDeclaration().resolve() }

/**
* Gets the `index`th opaque generic parameter of this opaque type declaration (0-based).
*
* This includes nodes from the "hidden" AST. It can be overridden in subclasses to change the
* behavior of both the `Immediate` and non-`Immediate` versions.
*/
GenericTypeParamType getImmediateOpaqueGenericParam(int index) {
result =
Synth::convertGenericTypeParamTypeFromRaw(Synth::convertOpaqueTypeDeclToRaw(this)
.(Raw::OpaqueTypeDecl)
.getOpaqueGenericParam(index))
}

/**
* Gets the `index`th opaque generic parameter of this opaque type declaration (0-based).
*/
final GenericTypeParamType getOpaqueGenericParam(int index) {
result = getImmediateOpaqueGenericParam(index).resolve()
}

/**
* Gets any of the opaque generic parameters of this opaque type declaration.
*/
final GenericTypeParamType getAnOpaqueGenericParam() { result = getOpaqueGenericParam(_) }

/**
* Gets the number of opaque generic parameters of this opaque type declaration.
*/
final int getNumberOfOpaqueGenericParams() { result = count(getAnOpaqueGenericParam()) }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,33 @@
private import codeql.swift.generated.Synth
private import codeql.swift.generated.Raw
import codeql.swift.elements.type.ArchetypeType
import codeql.swift.elements.decl.OpaqueTypeDecl

module Generated {
/**
* An opaque type, that is a type formally equivalent to an underlying type but abstracting it away.
*
* See https://docs.swift.org/swift-book/LanguageGuide/OpaqueTypes.html.
*/
class OpaqueTypeArchetypeType extends Synth::TOpaqueTypeArchetypeType, ArchetypeType {
override string getAPrimaryQlClass() { result = "OpaqueTypeArchetypeType" }

/**
* Gets the declaration of this opaque type archetype type.
*
* This includes nodes from the "hidden" AST. It can be overridden in subclasses to change the
* behavior of both the `Immediate` and non-`Immediate` versions.
*/
OpaqueTypeDecl getImmediateDeclaration() {
result =
Synth::convertOpaqueTypeDeclFromRaw(Synth::convertOpaqueTypeArchetypeTypeToRaw(this)
.(Raw::OpaqueTypeArchetypeType)
.getDeclaration())
}

/**
* Gets the declaration of this opaque type archetype type.
*/
final OpaqueTypeDecl getDeclaration() { result = getImmediateDeclaration().resolve() }
}
}
18 changes: 16 additions & 2 deletions swift/ql/lib/swift.dbscheme
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,15 @@ nominal_type_decls( //dir=decl
);

opaque_type_decls( //dir=decl
unique int id: @opaque_type_decl
unique int id: @opaque_type_decl,
int naming_declaration: @value_decl_or_none ref
);

#keyset[id, index]
opaque_type_decl_opaque_generic_params( //dir=decl
int id: @opaque_type_decl ref,
int index: int ref,
int opaque_generic_param: @generic_type_param_type_or_none ref
);

param_decls( //dir=decl
Expand Down Expand Up @@ -2222,7 +2230,8 @@ dictionary_types( //dir=type
;

opaque_type_archetype_types( //dir=type
unique int id: @opaque_type_archetype_type
unique int id: @opaque_type_archetype_type,
int declaration: @opaque_type_decl_or_none ref
);

opened_archetype_types( //dir=type
Expand Down Expand Up @@ -2389,6 +2398,11 @@ variadic_sequence_types( //dir=type
| @unspecified_element
;

@opaque_type_decl_or_none =
@opaque_type_decl
| @unspecified_element
;

@opaque_value_expr_or_none =
@opaque_value_expr
| @unspecified_element
Expand Down
39 changes: 20 additions & 19 deletions swift/ql/test/TestUtils.qll
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,31 @@ predicate toBeTested(Element e) {
e instanceof File
or
exists(ModuleDecl m |
m = e and
not m.isBuiltinModule() and
not m.isSystemModule() and
(m = e or m.getInterfaceType() = e)
not m.isSystemModule()
)
or
exists(Locatable loc |
loc.getLocation().getFile().getName().matches("%swift/ql/test%") and
e.(Locatable).getLocation().getFile().getName().matches("%swift/ql/test%")
or
exists(Element tested |
toBeTested(tested) and
(
e = loc
e = tested.(ValueDecl).getInterfaceType()
or
e = tested.(NominalTypeDecl).getType()
or
e = tested.(VarDecl).getType()
or
e = tested.(Expr).getType()
or
exists(Type t |
(e = t or e = t.(ExistentialType).getConstraint() or e = t.getCanonicalType()) and
(
t = loc.(ValueDecl).getInterfaceType()
or
t = loc.(NominalTypeDecl).getType()
or
t = loc.(VarDecl).getType()
or
t = loc.(Expr).getType()
)
)
e = tested.(Type).getCanonicalType()
or
e = tested.(ExistentialType).getConstraint()
or
e.(UnspecifiedElement).getParent() = tested
or
e.(OpaqueTypeDecl).getNamingDeclaration() = tested
)
)
or
toBeTested(e.(UnspecifiedElement).getParent())
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
| file://:0:0:0:0 | _ | getModule: | file://:0:0:0:0 | opaque_types | getInterfaceType: | (some Base).Type | getName: | _ | getNamingDeclaration: | opaque_types.swift:9:1:9:51 | baz(_:) |
| file://:0:0:0:0 | _ | getModule: | file://:0:0:0:0 | opaque_types | getInterfaceType: | (some P).Type | getName: | _ | getNamingDeclaration: | opaque_types.swift:5:1:5:45 | bar(_:) |
| file://:0:0:0:0 | _ | getModule: | file://:0:0:0:0 | opaque_types | getInterfaceType: | (some P).Type | getName: | _ | getNamingDeclaration: | opaque_types.swift:13:1:13:59 | bazz() |
| file://:0:0:0:0 | _ | getModule: | file://:0:0:0:0 | opaque_types | getInterfaceType: | (some SignedInteger).Type | getName: | _ | getNamingDeclaration: | opaque_types.swift:1:1:1:45 | foo() |
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// generated by codegen/codegen.py
import codeql.swift.elements
import TestUtils

from
OpaqueTypeDecl x, ModuleDecl getModule, Type getInterfaceType, string getName,
ValueDecl getNamingDeclaration
where
toBeTested(x) and
not x.isUnknown() and
getModule = x.getModule() and
getInterfaceType = x.getInterfaceType() and
getName = x.getName() and
getNamingDeclaration = x.getNamingDeclaration()
select x, "getModule:", getModule, "getInterfaceType:", getInterfaceType, "getName:", getName,
"getNamingDeclaration:", getNamingDeclaration
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// generated by codegen/codegen.py
import codeql.swift.elements
import TestUtils

from OpaqueTypeDecl x, int index
where toBeTested(x) and not x.isUnknown()
select x, index, x.getBaseType(index)
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// generated by codegen/codegen.py
import codeql.swift.elements
import TestUtils

from OpaqueTypeDecl x, int index
where toBeTested(x) and not x.isUnknown()
select x, index, x.getGenericTypeParam(index)
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
| file://:0:0:0:0 | _ | 0 | \u03c4_0_0 |
| file://:0:0:0:0 | _ | 0 | \u03c4_1_0 |
| file://:0:0:0:0 | _ | 0 | \u03c4_1_0 |
| file://:0:0:0:0 | _ | 0 | \u03c4_1_0 |
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// generated by codegen/codegen.py
import codeql.swift.elements
import TestUtils

from OpaqueTypeDecl x, int index
where toBeTested(x) and not x.isUnknown()
select x, index, x.getOpaqueGenericParam(index)
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
func foo() -> some SignedInteger { return 1 }

protocol P {}

func bar<T: P>(_ x: T) -> some P { return x }

class Base {}

func baz<T: Base>(_ x: T) -> some Base { return x }

class Generic<T: Equatable>: P {}

func bazz<T: Equatable>() -> some P { return Generic<T>() }

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
| some Base | getName: | some Base | getCanonicalType: | some Base | getInterfaceType: | \u03c4_1_0 | getDeclaration: | file://:0:0:0:0 | _ |
| some P | getName: | some P | getCanonicalType: | some P | getInterfaceType: | \u03c4_1_0 | getDeclaration: | file://:0:0:0:0 | _ |
| some P | getName: | some P | getCanonicalType: | some P | getInterfaceType: | \u03c4_1_0 | getDeclaration: | file://:0:0:0:0 | _ |
| some SignedInteger | getName: | some SignedInteger | getCanonicalType: | some SignedInteger | getInterfaceType: | \u03c4_0_0 | getDeclaration: | file://:0:0:0:0 | _ |
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// generated by codegen/codegen.py
import codeql.swift.elements
import TestUtils

from
OpaqueTypeArchetypeType x, string getName, Type getCanonicalType, Type getInterfaceType,
OpaqueTypeDecl getDeclaration
where
toBeTested(x) and
not x.isUnknown() and
getName = x.getName() and
getCanonicalType = x.getCanonicalType() and
getInterfaceType = x.getInterfaceType() and
getDeclaration = x.getDeclaration()
select x, "getName:", getName, "getCanonicalType:", getCanonicalType, "getInterfaceType:",
getInterfaceType, "getDeclaration:", getDeclaration
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
| some P | 0 | opaque_types.swift:3:1:3:13 | P |
| some P | 0 | opaque_types.swift:3:1:3:13 | P |
| some SignedInteger | 0 | file://:0:0:0:0 | SignedInteger |
| some SignedInteger | 1 | file://:0:0:0:0 | BinaryInteger |
| some SignedInteger | 2 | file://:0:0:0:0 | SignedNumeric |
| some SignedInteger | 3 | file://:0:0:0:0 | CustomStringConvertible |
| some SignedInteger | 4 | file://:0:0:0:0 | Hashable |
| some SignedInteger | 5 | file://:0:0:0:0 | Numeric |
| some SignedInteger | 6 | file://:0:0:0:0 | Strideable |
| some SignedInteger | 7 | file://:0:0:0:0 | Equatable |
| some SignedInteger | 8 | file://:0:0:0:0 | AdditiveArithmetic |
| some SignedInteger | 9 | file://:0:0:0:0 | ExpressibleByIntegerLiteral |
| some SignedInteger | 10 | file://:0:0:0:0 | Comparable |
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// generated by codegen/codegen.py
import codeql.swift.elements
import TestUtils

from OpaqueTypeArchetypeType x, int index
where toBeTested(x) and not x.isUnknown()
select x, index, x.getProtocol(index)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
| some Base | Base |
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// generated by codegen/codegen.py
import codeql.swift.elements
import TestUtils

from OpaqueTypeArchetypeType x
where toBeTested(x) and not x.isUnknown()
select x, x.getSuperclass()
Loading