Merge pull request #9795 from github/redsun82/swift-extraction

Swift: extract more entities
This commit is contained in:
Paolo Tranquilli
2022-07-18 13:37:43 +02:00
committed by GitHub
53 changed files with 410 additions and 17 deletions

View File

@@ -274,6 +274,16 @@ EnumCaseDecl:
IfConfigDecl:
_extends: Decl
_children:
clauses: IfConfigClause*
IfConfigClause:
_extends: Locatable
_children:
condition: Expr?
elements: AstNode*
is_active: predicate
_dir: decl
ImportDecl:
_extends: Decl
@@ -550,7 +560,6 @@ TypeExpr:
UnresolvedDeclRefExpr:
_extends: Expr
name: string?
_pragma: qltest_skip # we should really never extract these
UnresolvedDotExpr:
_extends: Expr
@@ -565,7 +574,8 @@ UnresolvedMemberExpr:
UnresolvedPatternExpr:
_extends: Expr
_pragma: qltest_skip # we should really never extract these
_children:
sub_pattern: Pattern
UnresolvedSpecializeExpr:
_extends: Expr

View File

@@ -93,6 +93,10 @@ class SwiftDispatcher {
return fetchLabelFromUnion<AstNodeTag>(node);
}
TrapLabel<IfConfigClauseTag> fetchLabel(const swift::IfConfigClause& clause) {
return fetchLabel(&clause);
}
TrapLabel<ConditionElementTag> fetchLabel(const swift::StmtConditionElement& element) {
return fetchLabel(&element);
}
@@ -140,6 +144,15 @@ class SwiftDispatcher {
attachLocation(locatable->getStartLoc(), locatable->getEndLoc(), locatableLabel);
}
void attachLocation(const swift::IfConfigClause* clause, TrapLabel<LocatableTag> locatableLabel) {
attachLocation(clause->Loc, clause->Loc, locatableLabel);
}
// Emits a Location TRAP entry and attaches it to a `Locatable` trap label for a given `SourceLoc`
void attachLocation(swift::SourceLoc loc, TrapLabel<LocatableTag> locatableLabel) {
attachLocation(loc, loc, locatableLabel);
}
// Emits a Location TRAP entry for a list of swift entities and attaches it to a `Locatable` trap
// label
template <typename Locatable>
@@ -215,7 +228,8 @@ class SwiftDispatcher {
swift::Expr,
swift::Pattern,
swift::TypeRepr,
swift::TypeBase>;
swift::TypeBase,
swift::IfConfigClause>;
void attachLocation(swift::SourceLoc start,
swift::SourceLoc end,
@@ -269,9 +283,11 @@ class SwiftDispatcher {
return realPath.str().str();
}
// TODO: The following methods are supposed to redirect TRAP emission to correpsonding visitors,
// which are to be introduced in follow-up PRs
// TODO: for const correctness these should consistently be `const` (and maybe const references
// as we don't expect `nullptr` here. However `swift::ASTVisitor` and `swift::TypeVisitor` do not
// accept const pointers
virtual void visit(swift::Decl* decl) = 0;
virtual void visit(const swift::IfConfigClause* clause) = 0;
virtual void visit(swift::Stmt* stmt) = 0;
virtual void visit(const swift::StmtCondition* cond) = 0;
virtual void visit(const swift::StmtConditionElement* cond) = 0;

View File

@@ -49,6 +49,7 @@ MAP_TAG(Argument);
#include <swift/AST/ExprNodes.def>
MAP_TAG(Decl);
MAP_TAG(IfConfigClause);
#define ABSTRACT_DECL(CLASS, PARENT) MAP_SUBTAG(CLASS##Decl, PARENT)
#define DECL(CLASS, PARENT) ABSTRACT_DECL(CLASS, PARENT)
#include <swift/AST/DeclNodes.def>

View File

@@ -358,4 +358,18 @@ void DeclVisitor::fillAbstractStorageDecl(const swift::AbstractStorageDecl& decl
fillValueDecl(decl, entry);
}
codeql::IfConfigDecl DeclVisitor::translateIfConfigDecl(const swift::IfConfigDecl& decl) {
auto entry = dispatcher_.createEntry(decl);
entry.clauses = dispatcher_.fetchRepeatedLabels(decl.getClauses());
return entry;
}
codeql::IfConfigClause DeclVisitor::translateIfConfigClause(const swift::IfConfigClause& clause) {
auto entry = dispatcher_.createEntry(clause);
entry.condition = dispatcher_.fetchOptionalLabel(clause.Cond);
entry.elements = dispatcher_.fetchRepeatedLabels(clause.Elements);
entry.is_active = clause.isActive;
return entry;
}
} // namespace codeql

View File

@@ -14,6 +14,11 @@ namespace codeql {
class DeclVisitor : public AstVisitorBase<DeclVisitor> {
public:
using AstVisitorBase<DeclVisitor>::AstVisitorBase;
using AstVisitorBase<DeclVisitor>::visit;
void visit(const swift::IfConfigClause* clause) {
dispatcher_.emit(translateIfConfigClause(*clause));
}
std::variant<codeql::ConcreteFuncDecl, codeql::ConcreteFuncDeclsTrap> translateFuncDecl(
const swift::FuncDecl& decl);
@@ -52,6 +57,8 @@ class DeclVisitor : public AstVisitorBase<DeclVisitor> {
codeql::ExtensionDecl translateExtensionDecl(const swift::ExtensionDecl& decl);
codeql::ImportDecl translateImportDecl(const swift::ImportDecl& decl);
std::optional<codeql::ModuleDecl> translateModuleDecl(const swift::ModuleDecl& decl);
codeql::IfConfigDecl translateIfConfigDecl(const swift::IfConfigDecl& decl);
codeql::IfConfigClause translateIfConfigClause(const swift::IfConfigClause& clause);
private:
std::string mangledName(const swift::ValueDecl& decl);

View File

@@ -668,4 +668,10 @@ void ExprVisitor::emitLookupExpr(const swift::LookupExpr* expr, TrapLabel<Lookup
}
}
codeql::UnresolvedPatternExpr ExprVisitor::translateUnresolvedPatternExpr(
swift::UnresolvedPatternExpr& expr) {
auto entry = dispatcher_.createEntry(expr);
entry.sub_pattern = dispatcher_.fetchLabel(expr.getSubPattern());
return entry;
}
} // namespace codeql

View File

@@ -84,6 +84,13 @@ class ExprVisitor : public AstVisitorBase<ExprVisitor> {
codeql::BridgeFromObjCExpr translateBridgeFromObjCExpr(const swift::BridgeFromObjCExpr& expr);
codeql::DotSelfExpr translateDotSelfExpr(const swift::DotSelfExpr& expr);
codeql::ErrorExpr translateErrorExpr(const swift::ErrorExpr& expr);
// The following function requires a non-const parameter because:
// * `swift::UnresolvedPatternExpr::getSubPattern` has a `const`-qualified overload returning
// `const swift::Pattern*`
// * `swift::ASTVisitor` only visits non-const pointers
// either we accept this, or we fix constness, e.g. by providing `visit` on `const` pointers
// in `VisitorBase`, or by doing a `const_cast` in `SwifDispatcher::fetchLabel`
codeql::UnresolvedPatternExpr translateUnresolvedPatternExpr(swift::UnresolvedPatternExpr& expr);
private:
void fillAbstractClosureExpr(const swift::AbstractClosureExpr& expr,

View File

@@ -21,6 +21,7 @@ class SwiftVisitor : private SwiftDispatcher {
private:
void visit(swift::Decl* decl) override { declVisitor.visit(decl); }
void visit(const swift::IfConfigClause* clause) override { declVisitor.visit(clause); }
void visit(swift::Stmt* stmt) override { stmtVisitor.visit(stmt); }
void visit(const swift::StmtCondition* cond) override {
emit(stmtVisitor.translateStmtCondition(*cond));

View File

@@ -1,4 +1,5 @@
#include "swift/extractor/visitors/TypeVisitor.h"
namespace codeql {
void TypeVisitor::visit(swift::TypeBase* type) {
TypeVisitorBase<TypeVisitor>::visit(type);
@@ -368,4 +369,10 @@ codeql::BuiltinVectorType TypeVisitor::translateBuiltinVectorType(
return createTypeEntry(type);
}
codeql::OpenedArchetypeType TypeVisitor::translateOpenedArchetypeType(
const swift::OpenedArchetypeType& type) {
auto entry = createTypeEntry(type);
fillArchetypeType(type, entry);
return entry;
}
} // namespace codeql

View File

@@ -68,6 +68,7 @@ class TypeVisitor : public TypeVisitorBase<TypeVisitor> {
codeql::BuiltinUnsafeValueBufferType translateBuiltinUnsafeValueBufferType(
const swift::BuiltinUnsafeValueBufferType& type);
codeql::BuiltinVectorType translateBuiltinVectorType(const swift::BuiltinVectorType& type);
codeql::OpenedArchetypeType translateOpenedArchetypeType(const swift::OpenedArchetypeType& type);
private:
void fillType(const swift::TypeBase& type, codeql::Type& entry);

View File

@@ -29,7 +29,7 @@ class VisitorBase {
public: \
void visit##CLASS##KIND(swift::CLASS##KIND* e) { \
using TranslateResult = std::invoke_result_t<decltype(&CrtpSubclass::translate##CLASS##KIND), \
CrtpSubclass, swift::CLASS##KIND>; \
CrtpSubclass, swift::CLASS##KIND&>; \
constexpr bool hasTranslateImplementation = !std::is_same_v<TranslateResult, void>; \
if constexpr (hasTranslateImplementation) { \
dispatcher_.emit(static_cast<CrtpSubclass*>(this)->translate##CLASS##KIND(*e)); \

View File

@@ -24,6 +24,7 @@ import codeql.swift.elements.decl.FuncDecl
import codeql.swift.elements.decl.GenericContext
import codeql.swift.elements.decl.GenericTypeDecl
import codeql.swift.elements.decl.GenericTypeParamDecl
import codeql.swift.elements.decl.IfConfigClause
import codeql.swift.elements.decl.IfConfigDecl
import codeql.swift.elements.decl.ImportDecl
import codeql.swift.elements.decl.InfixOperatorDecl

View File

@@ -0,0 +1,4 @@
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.decl.IfConfigClause
class IfConfigClause extends IfConfigClauseBase { }

View File

@@ -1,4 +1,9 @@
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.expr.UnresolvedDeclRefExpr
class UnresolvedDeclRefExpr extends UnresolvedDeclRefExprBase { }
class UnresolvedDeclRefExpr extends UnresolvedDeclRefExprBase {
override string toString() {
result = getName() + " (unresolved)"
or
not hasName() and result = "(unresolved)"
}
}

View File

@@ -28,6 +28,12 @@ Element getAnImmediateChild(Element e) {
or
enum_element_decl_params(e, _, x)
or
if_config_clause_conditions(e, x)
or
if_config_clause_elements(e, _, x)
or
if_config_decl_clauses(e, _, x)
or
pattern_binding_decl_inits(e, _, x)
or
pattern_binding_decl_patterns(e, _, x)
@@ -144,6 +150,8 @@ Element getAnImmediateChild(Element e) {
or
unresolved_dot_exprs(e, x, _)
or
unresolved_pattern_exprs(e, x)
or
vararg_expansion_exprs(e, x)
or
binding_patterns(e, x)

View File

@@ -0,0 +1,30 @@
// generated by codegen/codegen.py
import codeql.swift.elements.AstNode
import codeql.swift.elements.expr.Expr
import codeql.swift.elements.Locatable
class IfConfigClauseBase extends @if_config_clause, Locatable {
override string getAPrimaryQlClass() { result = "IfConfigClause" }
Expr getCondition() {
exists(Expr x |
if_config_clause_conditions(this, x) and
result = x.resolve()
)
}
predicate hasCondition() { exists(getCondition()) }
AstNode getElement(int index) {
exists(AstNode x |
if_config_clause_elements(this, index, x) and
result = x.resolve()
)
}
AstNode getAnElement() { result = getElement(_) }
int getNumberOfElements() { result = count(getAnElement()) }
predicate isActive() { if_config_clause_is_active(this) }
}

View File

@@ -1,6 +1,18 @@
// generated by codegen/codegen.py
import codeql.swift.elements.decl.Decl
import codeql.swift.elements.decl.IfConfigClause
class IfConfigDeclBase extends @if_config_decl, Decl {
override string getAPrimaryQlClass() { result = "IfConfigDecl" }
IfConfigClause getClause(int index) {
exists(IfConfigClause x |
if_config_decl_clauses(this, index, x) and
result = x.resolve()
)
}
IfConfigClause getAClause() { result = getClause(_) }
int getNumberOfClauses() { result = count(getAClause()) }
}

View File

@@ -1,6 +1,14 @@
// generated by codegen/codegen.py
import codeql.swift.elements.expr.Expr
import codeql.swift.elements.pattern.Pattern
class UnresolvedPatternExprBase extends @unresolved_pattern_expr, Expr {
override string getAPrimaryQlClass() { result = "UnresolvedPatternExpr" }
Pattern getSubPattern() {
exists(Pattern x |
unresolved_pattern_exprs(this, x) and
result = x.resolve()
)
}
}

View File

@@ -36,6 +36,7 @@ files(
@argument
| @ast_node
| @condition_element
| @if_config_clause
;
#keyset[id]
@@ -643,6 +644,35 @@ if_config_decls( //dir=decl
unique int id: @if_config_decl
);
#keyset[id, index]
if_config_decl_clauses( //dir=decl
int id: @if_config_decl ref,
int index: int ref,
int clause: @if_config_clause ref
);
if_config_clauses( //dir=decl
unique int id: @if_config_clause
);
#keyset[id]
if_config_clause_conditions( //dir=decl
int id: @if_config_clause ref,
int condition: @expr ref
);
#keyset[id, index]
if_config_clause_elements( //dir=decl
int id: @if_config_clause ref,
int index: int ref,
int element: @ast_node ref
);
#keyset[id]
if_config_clause_is_active( //dir=decl
int id: @if_config_clause ref
);
import_decls( //dir=decl
unique int id: @import_decl,
int module: @module_decl ref
@@ -1141,7 +1171,8 @@ unresolved_member_exprs( //dir=expr
);
unresolved_pattern_exprs( //dir=expr
unique int id: @unresolved_pattern_expr
unique int id: @unresolved_pattern_expr,
int sub_pattern: @pattern ref
);
unresolved_specialize_exprs( //dir=expr

View File

@@ -0,0 +1,6 @@
| if_config.swift:1:1:1:1 | IfConfigClause | isActive: | no |
| if_config.swift:4:1:4:1 | IfConfigClause | isActive: | no |
| if_config.swift:7:1:7:1 | IfConfigClause | isActive: | yes |
| if_config_active.swift:3:1:3:1 | IfConfigClause | isActive: | yes |
| if_config_active.swift:6:1:6:1 | IfConfigClause | isActive: | no |
| if_config_active.swift:9:1:9:1 | IfConfigClause | isActive: | no |

View File

@@ -0,0 +1,10 @@
// generated by codegen/codegen.py
import codeql.swift.elements
import TestUtils
from IfConfigClause x, string isActive
where
toBeTested(x) and
not x.isUnknown() and
if x.isActive() then isActive = "yes" else isActive = "no"
select x, "isActive:", isActive

View File

@@ -0,0 +1,4 @@
| if_config.swift:1:1:1:1 | IfConfigClause | if_config.swift:1:5:1:5 | FOO (unresolved) |
| if_config.swift:4:1:4:1 | IfConfigClause | if_config.swift:4:9:4:19 | call to ... |
| if_config_active.swift:3:1:3:1 | IfConfigClause | if_config_active.swift:3:5:3:5 | FOO (unresolved) |
| if_config_active.swift:6:1:6:1 | IfConfigClause | if_config_active.swift:6:9:6:17 | call to ... |

View File

@@ -0,0 +1,7 @@
// generated by codegen/codegen.py
import codeql.swift.elements
import TestUtils
from IfConfigClause x
where toBeTested(x) and not x.isUnknown()
select x, x.getCondition()

View File

@@ -0,0 +1,18 @@
| if_config.swift:1:1:1:1 | IfConfigClause | 0 | if_config.swift:2:1:2:16 | { ... } |
| if_config.swift:1:1:1:1 | IfConfigClause | 1 | if_config.swift:2:5:2:5 | foo |
| if_config.swift:1:1:1:1 | IfConfigClause | 2 | if_config.swift:3:1:3:12 | { ... } |
| if_config.swift:4:1:4:1 | IfConfigClause | 0 | if_config.swift:5:1:5:16 | { ... } |
| if_config.swift:4:1:4:1 | IfConfigClause | 1 | if_config.swift:5:5:5:5 | bar |
| if_config.swift:4:1:4:1 | IfConfigClause | 2 | if_config.swift:6:1:6:12 | { ... } |
| if_config.swift:7:1:7:1 | IfConfigClause | 0 | if_config.swift:8:1:8:16 | { ... } |
| if_config.swift:7:1:7:1 | IfConfigClause | 1 | if_config.swift:8:5:8:5 | baz |
| if_config.swift:7:1:7:1 | IfConfigClause | 2 | if_config.swift:9:1:9:12 | { ... } |
| if_config_active.swift:3:1:3:1 | IfConfigClause | 0 | if_config_active.swift:4:1:4:16 | { ... } |
| if_config_active.swift:3:1:3:1 | IfConfigClause | 1 | if_config_active.swift:4:5:4:5 | foo |
| if_config_active.swift:3:1:3:1 | IfConfigClause | 2 | if_config_active.swift:5:1:5:12 | { ... } |
| if_config_active.swift:6:1:6:1 | IfConfigClause | 0 | if_config_active.swift:7:1:7:16 | { ... } |
| if_config_active.swift:6:1:6:1 | IfConfigClause | 1 | if_config_active.swift:7:5:7:5 | bar |
| if_config_active.swift:6:1:6:1 | IfConfigClause | 2 | if_config_active.swift:8:1:8:12 | { ... } |
| if_config_active.swift:9:1:9:1 | IfConfigClause | 0 | if_config_active.swift:10:1:10:16 | { ... } |
| if_config_active.swift:9:1:9:1 | IfConfigClause | 1 | if_config_active.swift:10:5:10:5 | baz |
| if_config_active.swift:9:1:9:1 | IfConfigClause | 2 | if_config_active.swift:11:1:11:12 | { ... } |

View File

@@ -0,0 +1,7 @@
// generated by codegen/codegen.py
import codeql.swift.elements
import TestUtils
from IfConfigClause x, int index
where toBeTested(x) and not x.isUnknown()
select x, index, x.getElement(index)

View File

@@ -0,0 +1,10 @@
#if FOO
var foo: Int = 1
print("foo")
#elseif os(watchOS)
var bar: Int = 2
print("bar")
#else
var baz: Int = 3
print("baz")
#endif

View File

@@ -0,0 +1,12 @@
//codeql-extractor-options: -D FOO
#if FOO
var foo: Int = 1
print("foo")
#elseif os(macOS)
var bar: Int = 2
print("bar")
#else
var baz: Int = 3
print("baz")
#endif

View File

@@ -0,0 +1 @@
| if_config.swift:1:1:10:1 | #if ... |

View File

@@ -0,0 +1,7 @@
// generated by codegen/codegen.py
import codeql.swift.elements
import TestUtils
from IfConfigDecl x
where toBeTested(x) and not x.isUnknown()
select x

View File

@@ -0,0 +1,3 @@
| if_config.swift:1:1:10:1 | #if ... | 0 | if_config.swift:1:1:1:1 | IfConfigClause |
| if_config.swift:1:1:10:1 | #if ... | 1 | if_config.swift:4:1:4:1 | IfConfigClause |
| if_config.swift:1:1:10:1 | #if ... | 2 | if_config.swift:7:1:7:1 | IfConfigClause |

View File

@@ -0,0 +1,7 @@
// generated by codegen/codegen.py
import codeql.swift.elements
import TestUtils
from IfConfigDecl x, int index
where toBeTested(x) and not x.isUnknown()
select x, index, x.getClause(index)

View File

@@ -1,4 +0,0 @@
// generated by codegen/codegen.py
After a swift source file is added in this directory and codegen/codegen.py is run again, test queries
will appear and this file will be deleted

View File

@@ -0,0 +1,10 @@
#if FOO
var foo: Int = 1
print("foo")
#elseif BAR
var bar: Int = 2
print("bar")
#else
var baz: Int = 3
print("baz")
#endif

View File

@@ -0,0 +1,10 @@
| unresolved_decl_ref.swift:4:5:4:5 | FOO (unresolved) |
| unresolved_decl_ref.swift:4:9:4:9 | && (unresolved) |
| unresolved_decl_ref.swift:4:12:4:12 | os (unresolved) |
| unresolved_decl_ref.swift:4:15:4:15 | Windows (unresolved) |
| unresolved_decl_ref.swift:5:1:5:1 | print (unresolved) |
| unresolved_decl_ref.swift:6:9:6:9 | BAR (unresolved) |
| unresolved_decl_ref.swift:6:13:6:13 | \|\| (unresolved) |
| unresolved_decl_ref.swift:6:16:6:16 | arch (unresolved) |
| unresolved_decl_ref.swift:6:21:6:21 | i386 (unresolved) |
| unresolved_decl_ref.swift:9:1:9:1 | print (unresolved) |

View File

@@ -0,0 +1,7 @@
// generated by codegen/codegen.py
import codeql.swift.elements
import TestUtils
from UnresolvedDeclRefExpr x
where toBeTested(x) and not x.isUnknown()
select x

View File

@@ -0,0 +1,10 @@
| unresolved_decl_ref.swift:4:5:4:5 | FOO (unresolved) | FOO |
| unresolved_decl_ref.swift:4:9:4:9 | && (unresolved) | && |
| unresolved_decl_ref.swift:4:12:4:12 | os (unresolved) | os |
| unresolved_decl_ref.swift:4:15:4:15 | Windows (unresolved) | Windows |
| unresolved_decl_ref.swift:5:1:5:1 | print (unresolved) | print |
| unresolved_decl_ref.swift:6:9:6:9 | BAR (unresolved) | BAR |
| unresolved_decl_ref.swift:6:13:6:13 | \|\| (unresolved) | \|\| |
| unresolved_decl_ref.swift:6:16:6:16 | arch (unresolved) | arch |
| unresolved_decl_ref.swift:6:21:6:21 | i386 (unresolved) | i386 |
| unresolved_decl_ref.swift:9:1:9:1 | print (unresolved) | print |

View File

@@ -0,0 +1,7 @@
// generated by codegen/codegen.py
import codeql.swift.elements
import TestUtils
from UnresolvedDeclRefExpr x
where toBeTested(x) and not x.isUnknown()
select x, x.getName()

View File

@@ -0,0 +1,7 @@
// generated by codegen/codegen.py
import codeql.swift.elements
import TestUtils
from UnresolvedDeclRefExpr x
where toBeTested(x) and not x.isUnknown()
select x, x.getType()

View File

@@ -0,0 +1,10 @@
//codeql-extractor-options: -D BAR
// conditions and inactive branches in conditional compilation blocks are not resolved
#if FOO && os(Windows)
print(1)
#elseif BAR || arch(i386)
print(2)
#else
print(3)
#endif

View File

@@ -0,0 +1 @@
| unresolved_pattern_expr.swift:2:19:2:19 | UnresolvedPatternExpr | getSubPattern: | unresolved_pattern_expr.swift:2:19:2:19 | x |

View File

@@ -0,0 +1,10 @@
// generated by codegen/codegen.py
import codeql.swift.elements
import TestUtils
from UnresolvedPatternExpr x, Pattern getSubPattern
where
toBeTested(x) and
not x.isUnknown() and
getSubPattern = x.getSubPattern()
select x, "getSubPattern:", getSubPattern

View File

@@ -0,0 +1,7 @@
// generated by codegen/codegen.py
import codeql.swift.elements
import TestUtils
from UnresolvedPatternExpr x
where toBeTested(x) and not x.isUnknown()
select x, x.getType()

View File

@@ -0,0 +1,5 @@
#if FOO
if case let .some(x) = 42 {
print(x)
}
#endif

View File

@@ -1,4 +0,0 @@
// generated by codegen/codegen.py
After a swift source file is added in this directory and codegen/codegen.py is run again, test queries
will appear and this file will be deleted

View File

@@ -0,0 +1 @@
| C & P1 & P2 | getName: | C & P1 & P2 | getCanonicalType: | C & P1 & P2 | getInterfaceType: | \u03c4_0_0 |

View File

@@ -0,0 +1,13 @@
// generated by codegen/codegen.py
import codeql.swift.elements
import TestUtils
from OpenedArchetypeType x, string getName, Type getCanonicalType, Type getInterfaceType
where
toBeTested(x) and
not x.isUnknown() and
getName = x.getName() and
getCanonicalType = x.getCanonicalType() and
getInterfaceType = x.getInterfaceType()
select x, "getName:", getName, "getCanonicalType:", getCanonicalType, "getInterfaceType:",
getInterfaceType

View File

@@ -0,0 +1,2 @@
| C & P1 & P2 | 0 | opened_archetypes.swift:3:1:3:14 | P1 |
| C & P1 & P2 | 1 | opened_archetypes.swift:9:1:9:14 | P2 |

View File

@@ -0,0 +1,7 @@
// generated by codegen/codegen.py
import codeql.swift.elements
import TestUtils
from OpenedArchetypeType x, int index
where toBeTested(x) and not x.isUnknown()
select x, index, x.getProtocol(index)

View File

@@ -0,0 +1,7 @@
// generated by codegen/codegen.py
import codeql.swift.elements
import TestUtils
from OpenedArchetypeType x
where toBeTested(x) and not x.isUnknown()
select x, x.getSuperclass()

View File

@@ -0,0 +1,25 @@
// code inspired by https://github.com/apple/swift-evolution/blob/main/proposals/0352-implicit-open-existentials.md
protocol P1 {}
func isFoo<T: P1>(_: T) -> Bool {
return true
}
protocol P2 {}
class C {}
// will be ok with swift 5.7
// func test(value: any P1 & P2 & C) -> Bool { return isFoo(value) }
extension P1 {
var isFooMember: Bool {
isFoo(self)
}
}
func testMember(value: any P1 & P2 & C) -> Bool {
return value.isFooMember // here the existential type is implicitly "opened"
}