Merge pull request #12784 from github/sashabu/keypaths

Swift: Extract structured keypath components.
This commit is contained in:
Alexandre Boulgakov
2023-04-12 13:12:22 +01:00
committed by GitHub
51 changed files with 11384 additions and 34 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
description: Use unsafe parsed-path expression instead of component list in keypaths.
compatibility: partial
key_path_expr_components.rel: delete
key_path_components.rel: delete
key_path_component_subscript_arguments.rel: delete
key_path_component_tuple_indices.rel: delete
key_path_component_decl_refs.rel: delete

View File

@@ -1,3 +1,4 @@
#include <swift/AST/Expr.h>
#include <swift/AST/SourceFile.h>
#include <swift/Basic/SourceManager.h>
#include <swift/Parse/Token.h>
@@ -67,6 +68,13 @@ void SwiftLocationExtractor::attachLocation(const swift::SourceManager& sourceMa
locatableLabel);
}
void SwiftLocationExtractor::attachLocation(const swift::SourceManager& sourceManager,
const swift::KeyPathExpr::Component* component,
TrapLabel<LocatableTag> locatableLabel) {
attachLocation(sourceManager, component->getSourceRange().Start, component->getSourceRange().End,
locatableLabel);
}
void SwiftLocationExtractor::attachLocation(const swift::SourceManager& sourceManager,
swift::SourceLoc loc,
TrapLabel<LocatableTag> locatableLabel) {

View File

@@ -2,6 +2,7 @@
#include <swift/AST/ASTAllocated.h>
#include <swift/AST/AvailabilitySpec.h>
#include <swift/AST/Expr.h>
#include <swift/AST/SourceFile.h>
#include <swift/Basic/SourceManager.h>
#include <unordered_map>
@@ -74,6 +75,10 @@ class SwiftLocationExtractor {
swift::Token& token,
TrapLabel<LocatableTag> locatableLabel);
void attachLocation(const swift::SourceManager& sourceManager,
const swift::KeyPathExpr::Component* component,
TrapLabel<LocatableTag> locatableLabel);
private:
TrapLabel<FileTag> fetchFileLabel(const std::filesystem::path& file);
TrapDomain& trap;

View File

@@ -58,6 +58,7 @@ MAP(swift::Stmt, StmtTag)
MAP(swift::PoundAssertStmt, PoundAssertStmtTag)
MAP(swift::Argument, ArgumentTag)
MAP(swift::KeyPathExpr::Component, KeyPathComponentTag)
MAP(swift::Expr, ExprTag)
MAP(swift::ErrorExpr, ErrorExprTag)
MAP(swift::LiteralExpr, LiteralExprTag)

View File

@@ -378,10 +378,10 @@ codeql::MemberRefExpr ExprTranslator::translateMemberRefExpr(const swift::Member
codeql::KeyPathExpr ExprTranslator::translateKeyPathExpr(const swift::KeyPathExpr& expr) {
auto entry = createExprEntry(expr);
// TODO this should be completely redone, as we are using internal stuff here instead of
// extracting expr.getComponents()
if (!expr.isObjC()) {
entry.parsed_path = dispatcher.fetchOptionalLabel(expr.getParsedPath());
for (const auto& component : expr.getComponents()) {
entry.components.push_back(emitKeyPathComponent(component));
}
if (auto rootTypeRepr = expr.getRootType()) {
auto keyPathType = expr.getType()->getAs<swift::BoundGenericClassType>();
assert(keyPathType && "KeyPathExpr must have BoundGenericClassType");
@@ -488,6 +488,26 @@ TrapLabel<ArgumentTag> ExprTranslator::emitArgument(const swift::Argument& arg)
return entry.id;
}
TrapLabel<KeyPathComponentTag> ExprTranslator::emitKeyPathComponent(
const swift::KeyPathExpr::Component& component) {
auto entry = dispatcher.createUncachedEntry(component);
entry.kind = static_cast<int>(component.getKind());
if (auto subscript_args = component.getSubscriptArgs()) {
for (const auto& arg : *subscript_args) {
entry.subscript_arguments.push_back(emitArgument(arg));
}
}
if (component.getKind() == swift::KeyPathExpr::Component::Kind::TupleElement) {
entry.tuple_index = static_cast<int>(component.getTupleIndex());
}
if (component.hasDeclRef()) {
entry.decl_ref = dispatcher.fetchLabel(component.getDeclRef().getDecl());
}
entry.component_type = dispatcher.fetchLabel(component.getComponentType());
dispatcher.emit(entry);
return entry.id;
}
void ExprTranslator::fillExplicitCastExpr(const swift::ExplicitCastExpr& expr,
codeql::ExplicitCastExpr& entry) {
entry.sub_expr = dispatcher.fetchLabel(expr.getSubExpr());

View File

@@ -121,6 +121,7 @@ class ExprTranslator : public AstTranslatorBase<ExprTranslator> {
void fillAbstractClosureExpr(const swift::AbstractClosureExpr& expr,
codeql::AbstractClosureExpr& entry);
TrapLabel<ArgumentTag> emitArgument(const swift::Argument& arg);
TrapLabel<KeyPathComponentTag> emitKeyPathComponent(const swift::KeyPathExpr::Component& expr);
void fillExplicitCastExpr(const swift::ExplicitCastExpr& expr, codeql::ExplicitCastExpr& entry);
void fillIdentityExpr(const swift::IdentityExpr& expr, codeql::IdentityExpr& entry);
void fillAnyTryExpr(const swift::AnyTryExpr& expr, codeql::AnyTryExpr& entry);

View File

@@ -7,6 +7,7 @@ ql/lib/codeql/swift/elements/DbLocation.qll 2b07fe465cc6ea0e876892d8312bedca35d2
ql/lib/codeql/swift/elements/DbLocationConstructor.qll 88366e22ba40eaaee097f413130117925dda488f1bcbd3989e301e86dd394df3 c61b32994d403a8c4f85c26251e24ffb8c6ea34dbbe935872d868ccbfb6c1ff6
ql/lib/codeql/swift/elements/DiagnosticsConstructor.qll 6a3e312f3ed57465747c672cbb6d615eca89f42586519221d2973ac3e2ab052c a010ef546f9ed2a75b812ee47db00110056b3076b1f939efa2addb000c327427
ql/lib/codeql/swift/elements/ErrorElement.qll e054242b883bcc7fe1e2ee844268325a0a0b83486d5c7b4e334c73a5f8bd1d9f ab0028bab8a9ed14c6b4bfe0f8a10e4768ea1e21f86b495258021ab9b8e65aeb
ql/lib/codeql/swift/elements/KeyPathComponentConstructor.qll fa5fdff92a996add9aa79c320df011bf40ed50f83166c3c745bdb6c45bd22bb3 7afdff6d42b73c6968c486697daa0bc8dacb11815544c65c32f7fe9be3b05d2f
ql/lib/codeql/swift/elements/OtherAvailabilitySpecConstructor.qll fe03628ffbad9369e4b6bf325a58a3013b621090eecd9e01a76710e0d234d66a 0b7ffc7ed88d2b0da9aad86d83272daf124a4597c0fee1184f7d2f3511063afd
ql/lib/codeql/swift/elements/PlatformVersionAvailabilitySpecConstructor.qll ce9cc9b15eff28cf0f9ef94f1d7a9dbfbbb2fb64c0053c2b537046784fcd6ee6 8b776cb89ec44704babbce7ac69efb534bf0925ca43f04e7a7dc795435404393
ql/lib/codeql/swift/elements/UnspecifiedElementConstructor.qll 0d179f8189f6268916f88c78a2665f8d4e78dc71e71b6229354677e915ac505d e8f5c313b7d8b0e93cee84151a5f080013d2ca502f3facbbde4cdb0889bc7f8e
@@ -366,7 +367,7 @@ ql/lib/codeql/swift/elements/type/VariadicSequenceType.qll 325e4c4481e9ac07acdc6
ql/lib/codeql/swift/elements/type/VariadicSequenceTypeConstructor.qll 0d1d2328a3b5e503a883e7e6d7efd0ca5e7f2633abead9e4c94a9f98ed3cb223 69bff81c1b9413949eacb9298d2efb718ea808e68364569a1090c9878c4af856
ql/lib/codeql/swift/elements/type/WeakStorageType.qll 7c07739cfc1459f068f24fef74838428128054adf611504d22532e4a156073e7 9c968414d7cc8d672f3754bced5d4f83f43a6d7872d0d263d79ff60483e1f996
ql/lib/codeql/swift/elements/type/WeakStorageTypeConstructor.qll d88b031ef44d6de14b3ddcff2eb47b53dbd11550c37250ff2edb42e5d21ec3e9 26d855c33492cf7a118e439f7baeed0e5425cfaf058b1dcc007eca7ed765c897
ql/lib/codeql/swift/elements.qll 82b69a48b7afffeb97cafd9fdc57af96b672e21879580a6cfc3bae2a49bc2c40 82b69a48b7afffeb97cafd9fdc57af96b672e21879580a6cfc3bae2a49bc2c40
ql/lib/codeql/swift/elements.qll d4d76166fa8eb793973aa1c6862e0a4f9f44ca5ac364b0832f6edf4fd201110b d4d76166fa8eb793973aa1c6862e0a4f9f44ca5ac364b0832f6edf4fd201110b
ql/lib/codeql/swift/generated/AstNode.qll 02ca56d82801f942ae6265c6079d92ccafdf6b532f6bcebd98a04029ddf696e4 6216fda240e45bd4302fa0cf0f08f5f945418b144659264cdda84622b0420aa2
ql/lib/codeql/swift/generated/AvailabilityInfo.qll 996a5cfadf7ca049122a1d1a1a9eb680d6a625ce28ede5504b172eabe7640fd2 4fe6e0325ff021a576fcd004730115ffaa60a2d9020420c7d4a1baa498067b60
ql/lib/codeql/swift/generated/AvailabilitySpec.qll fb1255f91bb5e41ad4e9c675a2efbc50d0fb366ea2de68ab7eebd177b0795309 144e0c2e7d6c62ecee43325f7f26dcf437881edf0b75cc1bc898c6c4b61fdeaf
@@ -378,15 +379,16 @@ ql/lib/codeql/swift/generated/Diagnostics.qll d2ee2db55e932dcaee95fcc1164a51ffbe
ql/lib/codeql/swift/generated/Element.qll 9caf84a1da2509f5b01a22d6597126c573ae63ec3e8c6af6fd6fcc7ead0b4e82 70deb2238509d5ed660369bf763c796065d92efd732469088cdf67f68bacd796
ql/lib/codeql/swift/generated/ErrorElement.qll 4b032abe8ffb71376a29c63e470a52943ace2527bf7b433c97a8bf716f9ad102 4f2b1be162a5c275e3264dbc51bf98bce8846d251be8490a0d4b16cbc85f630f
ql/lib/codeql/swift/generated/File.qll f88c485883dd9b2b4a366080e098372912e03fb3177e5cae58aa4449c2b03399 0333c49e3a11c48e6146a7f492ee31ac022d80150fc3f8bfafc3c8f94d66ff76
ql/lib/codeql/swift/generated/KeyPathComponent.qll f8d62b8021936dc152538b52278a320d7e151cd24fcb602dab4d0169b328e0d4 aa0580990a97cf733bb90a2d68368ea10802213b2471425a82d7ea945a6595f4
ql/lib/codeql/swift/generated/Locatable.qll bdc98b9fb7788f44a4bf7e487ee5bd329473409950a8e9f116d61995615ad849 0b36b4fe45e2aa195e4bb70c50ea95f32f141b8e01e5f23466c6427dd9ab88fb
ql/lib/codeql/swift/generated/Location.qll 851766e474cdfdfa67da42e0031fc42dd60196ff5edd39d82f08d3e32deb84c1 b29b2c37672f5acff15f1d3c5727d902f193e51122327b31bd27ec5f877bca3b
ql/lib/codeql/swift/generated/OtherAvailabilitySpec.qll 0e26a203b26ff0581b7396b0c6d1606feec5cc32477f676585cdec4911af91c5 0e26a203b26ff0581b7396b0c6d1606feec5cc32477f676585cdec4911af91c5
ql/lib/codeql/swift/generated/ParentChild.qll 7d45d4e872e769f37a5b157ba422c48afe482552e44d94ff5f6a5a6449d672e7 6f7464ecd8ca04b6aa261139b36a162e5b0636237d514b8431ef4f97a1c603dc
ql/lib/codeql/swift/generated/ParentChild.qll 3998d73048297cf2df42176b0060c025e57d409d56f3fbfab9c202bd46c07b5e 425b01328baf38bd5e46403e11b25b0e17cd5bc40731dbf64a46e01604611e15
ql/lib/codeql/swift/generated/PlatformVersionAvailabilitySpec.qll f82d9ca416fe8bd59b5531b65b1c74c9f317b3297a6101544a11339a1cffce38 7f5c6d3309e66c134107afe55bae76dfc9a72cb7cdd6d4c3706b6b34cee09fa0
ql/lib/codeql/swift/generated/PureSynthConstructors.qll 173c0dd59396a1de26fe870e3bc2766c46de689da2a4d8807cb62023bbce1a98 173c0dd59396a1de26fe870e3bc2766c46de689da2a4d8807cb62023bbce1a98
ql/lib/codeql/swift/generated/Raw.qll 60bce9edc4af395d7c64959e1fb8abd6d0a79ea4920417e978783c3d357ef087 69d97b1a3a7e32834057fb95e9015fadbae4358af4f76b7e0c646f254c62f0ad
ql/lib/codeql/swift/generated/Synth.qll af02e0b49fe7b488592687996cc74d9525d4e3fbc9d324820b310b356f4d2612 5c740a660721173e9e4e45eb701d373ca19ff14d61cdaea309b65871e0deea90
ql/lib/codeql/swift/generated/SynthConstructors.qll a1b3ca33017f82124286ccad317a05484fee144fb9c3cdd2e500ce38e5efcec4 a1b3ca33017f82124286ccad317a05484fee144fb9c3cdd2e500ce38e5efcec4
ql/lib/codeql/swift/generated/Raw.qll 16ef0c379f1b3ceb73df393a34b8d2c5c4fb180e337fb3b8f33078fa9d827b7e 4b608cd9fc3f425fc568322ae17036e6407a54d0a6a30ff03fe04942f4ef897f
ql/lib/codeql/swift/generated/Synth.qll 1b60c8eab214c8f9a3a1fb39a8785979bc3d86f2615ba0a580c35e17fd496851 052940a87ffb32214b1b3c774bc643aa5d4f31c484d3121b4da384c2839cb10b
ql/lib/codeql/swift/generated/SynthConstructors.qll bb0c69cea79a06ec3cc0e176fc6e63cfe125107a45373e41083fc4de056133b8 bb0c69cea79a06ec3cc0e176fc6e63cfe125107a45373e41083fc4de056133b8
ql/lib/codeql/swift/generated/UnknownFile.qll 0fcf9beb8de79440bcdfff4bb6ab3dd139bd273e6c32754e05e6a632651e85f6 0fcf9beb8de79440bcdfff4bb6ab3dd139bd273e6c32754e05e6a632651e85f6
ql/lib/codeql/swift/generated/UnknownLocation.qll e50efefa02a0ec1ff635a00951b5924602fc8cab57e5756e4a039382c69d3882 e50efefa02a0ec1ff635a00951b5924602fc8cab57e5756e4a039382c69d3882
ql/lib/codeql/swift/generated/UnspecifiedElement.qll dbc6ca4018012977b26ca184a88044c55b0661e3998cd14d46295b62a8d69625 184c9a0ce18c2ac881943b0fb400613d1401ed1d5564f90716b6c310ba5afe71
@@ -502,7 +504,7 @@ ql/lib/codeql/swift/generated/expr/InterpolatedStringLiteralExpr.qll 35f79ec9d44
ql/lib/codeql/swift/generated/expr/IsExpr.qll b5ca50490cae8ac590b68a1a51b7039a54280d606b42c444808a04fa26c7e1b6 b5ca50490cae8ac590b68a1a51b7039a54280d606b42c444808a04fa26c7e1b6
ql/lib/codeql/swift/generated/expr/KeyPathApplicationExpr.qll 232e204a06b8fad3247040d47a1aa34c6736b764ab1ebca6c5dc74c3d4fc0c9b 6b823c483ee33cd6419f0a61a543cfce0cecfd0c90df72e60d01f5df8b3da3c0
ql/lib/codeql/swift/generated/expr/KeyPathDotExpr.qll ea73a462801fbe5e27b2f47bca4b39f6936d326d15d6de3f18b7afa6ace35878 ea73a462801fbe5e27b2f47bca4b39f6936d326d15d6de3f18b7afa6ace35878
ql/lib/codeql/swift/generated/expr/KeyPathExpr.qll e44b9d2a7a6c046d2e61b40192c878e37bd9391c03c8277d92dfba05d9040228 e32c4f6fc35f4e7ada95e82b8dd2cd3eb1912406d3604066f2d183f1311f8c0d
ql/lib/codeql/swift/generated/expr/KeyPathExpr.qll d78eb3a2805f7a98b23b8cb16aa66308e7a131284b4cd148a96e0b8c600e1db3 9f05ace69b0de3cdd9e9a1a6aafeb4478cd15423d2fa9e818dd049ddb2adfeb9
ql/lib/codeql/swift/generated/expr/LazyInitializerExpr.qll d8e93dcfa7fa8a00005f30b4aaa426f50d5040db11bef0c3b56558419b6cc110 3ca7d7ca9e52a025c38d7605c509d6758a4d5ceb0543192074c901f5935d4453
ql/lib/codeql/swift/generated/expr/LinearFunctionExpr.qll cd4c31bed9d0beb09fdfc57069d28adb3a661c064d9c6f52bb250011d8e212a7 cd4c31bed9d0beb09fdfc57069d28adb3a661c064d9c6f52bb250011d8e212a7
ql/lib/codeql/swift/generated/expr/LinearFunctionExtractOriginalExpr.qll ee7d3e025815b5af392ffc006ec91e3150130f2bd708ab92dbe80f2efa9e6792 bcf9ed64cca2dcf5bb544f6347de3d6faa059a1900042a36555e11dfbe0a6013
@@ -661,6 +663,10 @@ ql/test/extractor-tests/generated/AvailabilityInfo/AvailabilityInfo_getSpec.ql 4
ql/test/extractor-tests/generated/Comment/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7
ql/test/extractor-tests/generated/Diagnostics/Diagnostics.ql 6a4a9480cc929381e0337b181e5ac519a7abc6d597ebe24fb6701acf79ced86f 199c5bf8bd38e161d989e0e4db1ea1d3ddcb4d7cf571afd9112ce3ed8d9b8d2a
ql/test/extractor-tests/generated/File/File.ql 17a26e4f8aeaf3d4a38e6eb18f5d965cd62b63671b84edcd068808b4f3a999df 009a1338750bf95f715b303ac3e6a6e827c82aec2068299a97b0585ce76e9239
ql/test/extractor-tests/generated/KeyPathComponent/KeyPathComponent.ql 3d34d994ab5d6fada0d8acfb0dc514ba5315f094cb0a94dadfef12afebed9496 82c4d91df2a32f46b7aedb6570fd4e63871f32317b2d3e8dd5d2a396dbd92254
ql/test/extractor-tests/generated/KeyPathComponent/KeyPathComponent_getDeclRef.ql 1f51b17a6f7fdd0a6559ce0b3d8ee408a3ccf441f13f7b94bfba14e73ad6e357 24fd64ad77942909ea82a309bb6f56081363beaa7f557547b5b3b199dd79a69b
ql/test/extractor-tests/generated/KeyPathComponent/KeyPathComponent_getSubscriptArgument.ql c062b22dd4f705db394a07b6d274dc019baaed619cbcc31eebda8e3583bcda97 48542483f9b3b2a5993036845a640711ef50c3b359202feedd69a9e1bd0b19b8
ql/test/extractor-tests/generated/KeyPathComponent/KeyPathComponent_getTupleIndex.ql b7a60a79a6368f410298d6a00c9ccefae47875c540b668a924ebb37d331564a5 798760446f64d552669c87c5c377d41dcdbcbcdbcc20f9c4b58bd15248e3fb0b
ql/test/extractor-tests/generated/OtherAvailabilitySpec/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7
ql/test/extractor-tests/generated/PlatformVersionAvailabilitySpec/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7
ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl.ql 5c017af7e6b16ee68990eec12affe81eb114338bac4d445f4b231fe0f110eccc db86c828a892b0acd150a780914e7e48c280cad473d3680a453bdee03aee1e9d
@@ -798,7 +804,10 @@ ql/test/extractor-tests/generated/expr/InterpolatedStringLiteralExpr/MISSING_SOU
ql/test/extractor-tests/generated/expr/IsExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7
ql/test/extractor-tests/generated/expr/KeyPathApplicationExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7
ql/test/extractor-tests/generated/expr/KeyPathDotExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7
ql/test/extractor-tests/generated/expr/KeyPathExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7
ql/test/extractor-tests/generated/expr/KeyPathExpr/KeyPathExpr.ql 3eddbfac203a76910d234572f51092b097d4cc948f42843a4532e772853451ba 1d1cf6f11c8221de9f07a789af788a473915b0e714502561f60c4b1d4e6dcd1e
ql/test/extractor-tests/generated/expr/KeyPathExpr/KeyPathExpr_getComponent.ql ce38c747737e13f80a212576ae943f0a770fc87a15dabcb0d730515aeb530a3f a50138c47e61e9eab4131a03e1b3e065ed0fca1452c6a3d4f8f48a6124d445be
ql/test/extractor-tests/generated/expr/KeyPathExpr/KeyPathExpr_getRoot.ql 61d8d0f50c62e6bdf98005609861f6f4fd16e59c439706abf03ba27f87ed3cb1 403ee884bb83b7a4207993afbda7964e676f5f64923ce11e65a0cf8bd199e01d
ql/test/extractor-tests/generated/expr/KeyPathExpr/KeyPathExpr_getType.ql 992497671107be454ffe1f42b513a5bca37bd31849587ad55f6bd87d8ac5d4a7 b51109f0d9e5e6238d8ab9e67f24d435a873a7884308c4f01ec4ecad51ed031d
ql/test/extractor-tests/generated/expr/LazyInitializerExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7
ql/test/extractor-tests/generated/expr/MagicIdentifierLiteralExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7
ql/test/extractor-tests/generated/expr/MakeTemporarilyEscapableExpr/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7

View File

@@ -10,6 +10,7 @@ import codeql.swift.elements.Diagnostics
import codeql.swift.elements.Element
import codeql.swift.elements.ErrorElement
import codeql.swift.elements.File
import codeql.swift.elements.KeyPathComponent
import codeql.swift.elements.Locatable
import codeql.swift.elements.Location
import codeql.swift.elements.OtherAvailabilitySpec

View File

@@ -0,0 +1,38 @@
private import codeql.swift.generated.KeyPathComponent
class KeyPathComponent extends Generated::KeyPathComponent {
/**
* Property access like `.bar` in `\Foo.bar`.
*/
predicate isProperty() { getKind() = 3 }
/**
* Array or dictionary subscript like `[1]` or `["a", "b"]`.
*/
predicate isSubscript() { getKind() = 4 }
/**
* Optional forcing `!`.
*/
predicate isOptionalForcing() { getKind() = 5 }
/**
* Optional chaining `?`.
*/
predicate isOptionalChaining() { getKind() = 6 }
/**
* Implicit optional wrapping component inserted by the compiler when an optional chain ends in a non-optional value.
*/
predicate isOptionalWrapping() { getKind() = 7 }
/**
* Reference to the entire object; the `self` in `\Foo.self`.
*/
predicate isSelf() { getKind() = 8 }
/**
* Tuple indexing like `.1`.
*/
predicate isTupleIndexing() { getKind() = 9 }
}

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.Raw
predicate constructKeyPathComponent(Raw::KeyPathComponent id) { any() }

View File

@@ -0,0 +1,122 @@
// generated by codegen/codegen.py
private import codeql.swift.generated.Synth
private import codeql.swift.generated.Raw
import codeql.swift.elements.expr.Argument
import codeql.swift.elements.AstNode
import codeql.swift.elements.type.Type
import codeql.swift.elements.decl.ValueDecl
module Generated {
/**
* A component of a `KeyPathExpr`.
*/
class KeyPathComponent extends Synth::TKeyPathComponent, AstNode {
override string getAPrimaryQlClass() { result = "KeyPathComponent" }
/**
* Gets the kind of key path component.
*
* INTERNAL: Do not use.
*
* This is 3 for properties, 4 for array and dictionary subscripts, 5 for optional forcing
* (`!`), 6 for optional chaining (`?`), 7 for implicit optional wrapping, 8 for `self`,
* and 9 for tuple element indexing.
*
* The following values should not appear: 0 for invalid components, 1 for unresolved
* properties, 2 for unresolved subscripts, 10 for #keyPath dictionary keys, and 11 for
* implicit IDE code completion data.
*/
int getKind() {
result = Synth::convertKeyPathComponentToRaw(this).(Raw::KeyPathComponent).getKind()
}
/**
* Gets the `index`th argument to an array or dictionary subscript expression (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.
*/
Argument getImmediateSubscriptArgument(int index) {
result =
Synth::convertArgumentFromRaw(Synth::convertKeyPathComponentToRaw(this)
.(Raw::KeyPathComponent)
.getSubscriptArgument(index))
}
/**
* Gets the `index`th argument to an array or dictionary subscript expression (0-based).
*/
final Argument getSubscriptArgument(int index) {
result = getImmediateSubscriptArgument(index).resolve()
}
/**
* Gets any of the arguments to an array or dictionary subscript expression.
*/
final Argument getASubscriptArgument() { result = getSubscriptArgument(_) }
/**
* Gets the number of arguments to an array or dictionary subscript expression.
*/
final int getNumberOfSubscriptArguments() {
result = count(int i | exists(getSubscriptArgument(i)))
}
/**
* Gets the tuple index of this key path component, if it exists.
*/
int getTupleIndex() {
result = Synth::convertKeyPathComponentToRaw(this).(Raw::KeyPathComponent).getTupleIndex()
}
/**
* Holds if `getTupleIndex()` exists.
*/
final predicate hasTupleIndex() { exists(getTupleIndex()) }
/**
* Gets the property or subscript operator, if it exists.
*
* 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 getImmediateDeclRef() {
result =
Synth::convertValueDeclFromRaw(Synth::convertKeyPathComponentToRaw(this)
.(Raw::KeyPathComponent)
.getDeclRef())
}
/**
* Gets the property or subscript operator, if it exists.
*/
final ValueDecl getDeclRef() { result = getImmediateDeclRef().resolve() }
/**
* Holds if `getDeclRef()` exists.
*/
final predicate hasDeclRef() { exists(getDeclRef()) }
/**
* Gets the return type of this component application.
*
* 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.
*/
Type getImmediateComponentType() {
result =
Synth::convertTypeFromRaw(Synth::convertKeyPathComponentToRaw(this)
.(Raw::KeyPathComponent)
.getComponentType())
}
/**
* Gets the return type of this component application.
*
* An optional-chaining component has a non-optional type to feed into the rest of the key
* path; an optional-wrapping component is inserted if required to produce an optional type
* as the final output.
*/
final Type getComponentType() { result = getImmediateComponentType().resolve() }
}
}

View File

@@ -219,6 +219,26 @@ private module Impl {
)
}
private Element getImmediateChildOfKeyPathComponent(
KeyPathComponent e, int index, string partialPredicateCall
) {
exists(int b, int bAstNode, int n, int nSubscriptArgument |
b = 0 and
bAstNode = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAstNode(e, i, _)) | i) and
n = bAstNode and
nSubscriptArgument =
n + 1 + max(int i | i = -1 or exists(e.getImmediateSubscriptArgument(i)) | i) and
(
none()
or
result = getImmediateChildOfAstNode(e, index - b, partialPredicateCall)
or
result = e.getImmediateSubscriptArgument(index - n) and
partialPredicateCall = "SubscriptArgument(" + (index - n).toString() + ")"
)
)
}
private Element getImmediateChildOfUnspecifiedElement(
UnspecifiedElement e, int index, string partialPredicateCall
) {
@@ -1443,12 +1463,12 @@ private module Impl {
private Element getImmediateChildOfKeyPathExpr(
KeyPathExpr e, int index, string partialPredicateCall
) {
exists(int b, int bExpr, int n, int nRoot, int nParsedPath |
exists(int b, int bExpr, int n, int nRoot, int nComponent |
b = 0 and
bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and
n = bExpr and
nRoot = n + 1 and
nParsedPath = nRoot + 1 and
nComponent = nRoot + 1 + max(int i | i = -1 or exists(e.getImmediateComponent(i)) | i) and
(
none()
or
@@ -1456,9 +1476,8 @@ private module Impl {
or
index = n and result = e.getImmediateRoot() and partialPredicateCall = "Root()"
or
index = nRoot and
result = e.getImmediateParsedPath() and
partialPredicateCall = "ParsedPath()"
result = e.getImmediateComponent(index - nRoot) and
partialPredicateCall = "Component(" + (index - nRoot).toString() + ")"
)
)
}
@@ -4830,6 +4849,8 @@ private module Impl {
or
result = getImmediateChildOfAvailabilityInfo(e, index, partialAccessor)
or
result = getImmediateChildOfKeyPathComponent(e, index, partialAccessor)
or
result = getImmediateChildOfUnspecifiedElement(e, index, partialAccessor)
or
result = getImmediateChildOfOtherAvailabilitySpec(e, index, partialAccessor)

View File

@@ -134,6 +134,51 @@ module Raw {
class AvailabilitySpec extends @availability_spec, AstNode { }
class KeyPathComponent extends @key_path_component, AstNode {
override string toString() { result = "KeyPathComponent" }
/**
* Gets the kind of key path component.
*
* INTERNAL: Do not use.
*
* This is 3 for properties, 4 for array and dictionary subscripts, 5 for optional forcing
* (`!`), 6 for optional chaining (`?`), 7 for implicit optional wrapping, 8 for `self`,
* and 9 for tuple element indexing.
*
* The following values should not appear: 0 for invalid components, 1 for unresolved
* properties, 2 for unresolved subscripts, 10 for #keyPath dictionary keys, and 11 for
* implicit IDE code completion data.
*/
int getKind() { key_path_components(this, result, _) }
/**
* Gets the `index`th argument to an array or dictionary subscript expression (0-based).
*/
Argument getSubscriptArgument(int index) {
key_path_component_subscript_arguments(this, index, result)
}
/**
* Gets the tuple index of this key path component, if it exists.
*/
int getTupleIndex() { key_path_component_tuple_indices(this, result) }
/**
* Gets the property or subscript operator, if it exists.
*/
ValueDecl getDeclRef() { key_path_component_decl_refs(this, result) }
/**
* Gets the return type of this component application.
*
* An optional-chaining component has a non-optional type to feed into the rest of the key
* path; an optional-wrapping component is inserted if required to produce an optional type
* as the final output.
*/
Type getComponentType() { key_path_components(this, _, result) }
}
class UnspecifiedElement extends @unspecified_element, ErrorElement {
override string toString() { result = "UnspecifiedElement" }
@@ -981,9 +1026,9 @@ module Raw {
TypeRepr getRoot() { key_path_expr_roots(this, result) }
/**
* Gets the parsed path of this key path expression, if it exists.
* Gets the `index`th component of this key path expression (0-based).
*/
Expr getParsedPath() { key_path_expr_parsed_paths(this, result) }
KeyPathComponent getComponent(int index) { key_path_expr_components(this, index, result) }
}
class LazyInitializerExpr extends @lazy_initializer_expr, Expr {

View File

@@ -10,6 +10,7 @@ module Synth {
TDbFile(Raw::DbFile id) { constructDbFile(id) } or
TDbLocation(Raw::DbLocation id) { constructDbLocation(id) } or
TDiagnostics(Raw::Diagnostics id) { constructDiagnostics(id) } or
TKeyPathComponent(Raw::KeyPathComponent id) { constructKeyPathComponent(id) } or
TOtherAvailabilitySpec(Raw::OtherAvailabilitySpec id) { constructOtherAvailabilitySpec(id) } or
TPlatformVersionAvailabilitySpec(Raw::PlatformVersionAvailabilitySpec id) {
constructPlatformVersionAvailabilitySpec(id)
@@ -310,7 +311,7 @@ module Synth {
class TAstNode =
TAvailabilityInfo or TAvailabilitySpec or TCaseLabelItem or TConditionElement or TDecl or
TExpr or TPattern or TStmt or TStmtCondition or TTypeRepr;
TExpr or TKeyPathComponent or TPattern or TStmt or TStmtCondition or TTypeRepr;
class TAvailabilitySpec = TOtherAvailabilitySpec or TPlatformVersionAvailabilitySpec;
@@ -486,6 +487,9 @@ module Synth {
cached
TDiagnostics convertDiagnosticsFromRaw(Raw::Element e) { result = TDiagnostics(e) }
cached
TKeyPathComponent convertKeyPathComponentFromRaw(Raw::Element e) { result = TKeyPathComponent(e) }
cached
TOtherAvailabilitySpec convertOtherAvailabilitySpecFromRaw(Raw::Element e) {
result = TOtherAvailabilitySpec(e)
@@ -1383,6 +1387,8 @@ module Synth {
or
result = convertExprFromRaw(e)
or
result = convertKeyPathComponentFromRaw(e)
or
result = convertPatternFromRaw(e)
or
result = convertStmtFromRaw(e)
@@ -2146,6 +2152,9 @@ module Synth {
cached
Raw::Element convertDiagnosticsToRaw(TDiagnostics e) { e = TDiagnostics(result) }
cached
Raw::Element convertKeyPathComponentToRaw(TKeyPathComponent e) { e = TKeyPathComponent(result) }
cached
Raw::Element convertOtherAvailabilitySpecToRaw(TOtherAvailabilitySpec e) {
e = TOtherAvailabilitySpec(result)
@@ -3041,6 +3050,8 @@ module Synth {
or
result = convertExprToRaw(e)
or
result = convertKeyPathComponentToRaw(e)
or
result = convertPatternToRaw(e)
or
result = convertStmtToRaw(e)

View File

@@ -4,6 +4,7 @@ import codeql.swift.elements.CommentConstructor
import codeql.swift.elements.DbFileConstructor
import codeql.swift.elements.DbLocationConstructor
import codeql.swift.elements.DiagnosticsConstructor
import codeql.swift.elements.KeyPathComponentConstructor
import codeql.swift.elements.OtherAvailabilitySpecConstructor
import codeql.swift.elements.PlatformVersionAvailabilitySpecConstructor
import codeql.swift.elements.UnspecifiedElementConstructor

View File

@@ -2,9 +2,13 @@
private import codeql.swift.generated.Synth
private import codeql.swift.generated.Raw
import codeql.swift.elements.expr.Expr
import codeql.swift.elements.KeyPathComponent
import codeql.swift.elements.type.TypeRepr
module Generated {
/**
* A key-path expression.
*/
class KeyPathExpr extends Synth::TKeyPathExpr, Expr {
override string getAPrimaryQlClass() { result = "KeyPathExpr" }
@@ -32,26 +36,33 @@ module Generated {
final predicate hasRoot() { exists(getRoot()) }
/**
* Gets the parsed path of this key path expression, if it exists.
* Gets the `index`th component of this key path expression (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.
*/
Expr getImmediateParsedPath() {
KeyPathComponent getImmediateComponent(int index) {
result =
Synth::convertExprFromRaw(Synth::convertKeyPathExprToRaw(this)
Synth::convertKeyPathComponentFromRaw(Synth::convertKeyPathExprToRaw(this)
.(Raw::KeyPathExpr)
.getParsedPath())
.getComponent(index))
}
/**
* Gets the parsed path of this key path expression, if it exists.
* Gets the `index`th component of this key path expression (0-based).
*/
final Expr getParsedPath() { result = getImmediateParsedPath().resolve() }
final KeyPathComponent getComponent(int index) {
result = getImmediateComponent(index).resolve()
}
/**
* Holds if `getParsedPath()` exists.
* Gets any of the components of this key path expression.
*/
final predicate hasParsedPath() { exists(getParsedPath()) }
final KeyPathComponent getAComponent() { result = getComponent(_) }
/**
* Gets the number of components of this key path expression.
*/
final int getNumberOfComponents() { result = count(int i | exists(getComponent(i))) }
}
}

View File

@@ -112,6 +112,7 @@ locations(
| @condition_element
| @decl
| @expr
| @key_path_component
| @pattern
| @stmt
| @stmt_condition
@@ -173,6 +174,31 @@ availability_info_specs(
| @platform_version_availability_spec
;
key_path_components(
unique int id: @key_path_component,
int kind: int ref,
int component_type: @type_or_none ref
);
#keyset[id, index]
key_path_component_subscript_arguments(
int id: @key_path_component ref,
int index: int ref,
int subscript_argument: @argument_or_none ref
);
#keyset[id]
key_path_component_tuple_indices(
int id: @key_path_component ref,
int tuple_index: int ref
);
#keyset[id]
key_path_component_decl_refs(
int id: @key_path_component ref,
int decl_ref: @value_decl_or_none ref
);
unspecified_elements(
unique int id: @unspecified_element,
string property: string ref,
@@ -994,10 +1020,11 @@ key_path_expr_roots( //dir=expr
int root: @type_repr_or_none ref
);
#keyset[id]
key_path_expr_parsed_paths( //dir=expr
#keyset[id, index]
key_path_expr_components( //dir=expr
int id: @key_path_expr ref,
int parsed_path: @expr_or_none ref
int index: int ref,
int component: @key_path_component_or_none ref
);
lazy_initializer_exprs( //dir=expr
@@ -2497,6 +2524,11 @@ variadic_sequence_types( //dir=type
| @unspecified_element
;
@key_path_component_or_none =
@key_path_component
| @unspecified_element
;
@location_or_none =
@location
| @unspecified_element

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,4 @@
description: Use component list instead of unsafe parsed-path expression in keypaths.
compatibility: partial
key_path_expr_parsed_paths.rel: delete

View File

@@ -287,3 +287,13 @@
| expressions.swift:163:9:163:9 | >>(_:_:) | DeclRefExpr |
| expressions.swift:163:9:163:9 | Int.Type | TypeExpr |
| expressions.swift:163:12:163:12 | 0 | IntegerLiteralExpr |
| expressions.swift:176:12:176:17 | #keyPath(...) | KeyPathExpr |
| expressions.swift:177:18:177:26 | #keyPath(...) | KeyPathExpr |
| expressions.swift:177:25:177:25 | 0 | IntegerLiteralExpr |
| expressions.swift:178:19:178:38 | #keyPath(...) | KeyPathExpr |
| expressions.swift:178:35:178:35 | a | StringLiteralExpr |
| expressions.swift:179:16:179:35 | #keyPath(...) | KeyPathExpr |
| expressions.swift:180:16:180:26 | #keyPath(...) | KeyPathExpr |
| expressions.swift:181:20:181:30 | #keyPath(...) | KeyPathExpr |
| expressions.swift:182:11:182:16 | #keyPath(...) | KeyPathExpr |
| expressions.swift:183:20:183:32 | #keyPath(...) | KeyPathExpr |

View File

@@ -162,3 +162,22 @@ func bitwise() {
_ = 1 << 0
_ = 1 >> 0
}
struct Bar {
var value : Int
var opt : Int?
}
struct Foo {
var value : Int
var opt : Bar?
}
let prop = \Foo.value
let arrElement = \[Int][0]
let dictElement = \[String : Int]["a"]
let optForce = \Optional<Int>.self!
let optChain = \Foo.opt?.opt
let optChainWrap = \Foo.opt?.value
let slf = \Int.self
let tupleElement = \(Int, Int).0

View File

@@ -0,0 +1,14 @@
| file://:0:0:0:0 | KeyPathComponent | getKind: | 7 | getNumberOfSubscriptArguments: | 0 | hasTupleIndex: | no | hasDeclRef: | no | getComponentType: | Int? |
| key_path_expr.swift:11:17:11:17 | KeyPathComponent | getKind: | 3 | getNumberOfSubscriptArguments: | 0 | hasTupleIndex: | no | hasDeclRef: | yes | getComponentType: | Int |
| key_path_expr.swift:12:24:12:26 | KeyPathComponent | getKind: | 4 | getNumberOfSubscriptArguments: | 1 | hasTupleIndex: | no | hasDeclRef: | yes | getComponentType: | Int |
| key_path_expr.swift:13:34:13:38 | KeyPathComponent | getKind: | 4 | getNumberOfSubscriptArguments: | 1 | hasTupleIndex: | no | hasDeclRef: | yes | getComponentType: | Int? |
| key_path_expr.swift:14:31:14:31 | KeyPathComponent | getKind: | 5 | getNumberOfSubscriptArguments: | 0 | hasTupleIndex: | no | hasDeclRef: | no | getComponentType: | Int |
| key_path_expr.swift:14:31:14:31 | KeyPathComponent | getKind: | 8 | getNumberOfSubscriptArguments: | 0 | hasTupleIndex: | no | hasDeclRef: | no | getComponentType: | Int? |
| key_path_expr.swift:15:21:15:21 | KeyPathComponent | getKind: | 3 | getNumberOfSubscriptArguments: | 0 | hasTupleIndex: | no | hasDeclRef: | yes | getComponentType: | Bar? |
| key_path_expr.swift:15:24:15:24 | KeyPathComponent | getKind: | 6 | getNumberOfSubscriptArguments: | 0 | hasTupleIndex: | no | hasDeclRef: | no | getComponentType: | Bar |
| key_path_expr.swift:15:26:15:26 | KeyPathComponent | getKind: | 3 | getNumberOfSubscriptArguments: | 0 | hasTupleIndex: | no | hasDeclRef: | yes | getComponentType: | Int? |
| key_path_expr.swift:16:25:16:25 | KeyPathComponent | getKind: | 3 | getNumberOfSubscriptArguments: | 0 | hasTupleIndex: | no | hasDeclRef: | yes | getComponentType: | Bar? |
| key_path_expr.swift:16:28:16:28 | KeyPathComponent | getKind: | 6 | getNumberOfSubscriptArguments: | 0 | hasTupleIndex: | no | hasDeclRef: | no | getComponentType: | Bar |
| key_path_expr.swift:16:30:16:30 | KeyPathComponent | getKind: | 3 | getNumberOfSubscriptArguments: | 0 | hasTupleIndex: | no | hasDeclRef: | yes | getComponentType: | Int |
| key_path_expr.swift:17:16:17:16 | KeyPathComponent | getKind: | 8 | getNumberOfSubscriptArguments: | 0 | hasTupleIndex: | no | hasDeclRef: | no | getComponentType: | Int |
| key_path_expr.swift:18:32:18:32 | KeyPathComponent | getKind: | 9 | getNumberOfSubscriptArguments: | 0 | hasTupleIndex: | yes | hasDeclRef: | no | getComponentType: | Int |

View File

@@ -0,0 +1,17 @@
// generated by codegen/codegen.py
import codeql.swift.elements
import TestUtils
from
KeyPathComponent x, int getKind, int getNumberOfSubscriptArguments, string hasTupleIndex,
string hasDeclRef, Type getComponentType
where
toBeTested(x) and
not x.isUnknown() and
getKind = x.getKind() and
getNumberOfSubscriptArguments = x.getNumberOfSubscriptArguments() and
(if x.hasTupleIndex() then hasTupleIndex = "yes" else hasTupleIndex = "no") and
(if x.hasDeclRef() then hasDeclRef = "yes" else hasDeclRef = "no") and
getComponentType = x.getComponentType()
select x, "getKind:", getKind, "getNumberOfSubscriptArguments:", getNumberOfSubscriptArguments,
"hasTupleIndex:", hasTupleIndex, "hasDeclRef:", hasDeclRef, "getComponentType:", getComponentType

View File

@@ -0,0 +1,7 @@
| key_path_expr.swift:11:17:11:17 | KeyPathComponent | key_path_expr.swift:7:9:7:9 | value |
| key_path_expr.swift:12:24:12:26 | KeyPathComponent | file://:0:0:0:0 | subscript ... |
| key_path_expr.swift:13:34:13:38 | KeyPathComponent | file://:0:0:0:0 | subscript ... |
| key_path_expr.swift:15:21:15:21 | KeyPathComponent | key_path_expr.swift:8:9:8:9 | opt |
| key_path_expr.swift:15:26:15:26 | KeyPathComponent | key_path_expr.swift:3:9:3:9 | opt |
| key_path_expr.swift:16:25:16:25 | KeyPathComponent | key_path_expr.swift:8:9:8:9 | opt |
| key_path_expr.swift:16:30:16:30 | KeyPathComponent | key_path_expr.swift:2:9:2:9 | value |

View File

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

View File

@@ -0,0 +1,2 @@
| key_path_expr.swift:12:24:12:26 | KeyPathComponent | 0 | key_path_expr.swift:12:25:12:25 | : 0 |
| key_path_expr.swift:13:34:13:38 | KeyPathComponent | 0 | key_path_expr.swift:13:35:13:35 | : a |

View File

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

View File

@@ -0,0 +1 @@
| key_path_expr.swift:18:32:18:32 | KeyPathComponent | 0 |

View File

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

View File

@@ -0,0 +1,18 @@
struct Bar {
var value : Int
var opt : Int?
}
struct Foo {
var value : Int
var opt : Bar?
}
let prop = \Foo.value
let arrElement = \[Int][0]
let dictElement = \[String : Int]["a"]
let optForce = \Optional<Int>.self!
let optChain = \Foo.opt?.opt
let optChainWrap = \Foo.opt?.value
let slf = \Int.self
let tupleElement = \(Int, Int).0

View File

@@ -0,0 +1,8 @@
| key_path_expr.swift:11:12:11:17 | #keyPath(...) | hasType: | yes | hasRoot: | yes | getNumberOfComponents: | 1 |
| key_path_expr.swift:12:18:12:26 | #keyPath(...) | hasType: | yes | hasRoot: | yes | getNumberOfComponents: | 1 |
| key_path_expr.swift:13:19:13:38 | #keyPath(...) | hasType: | yes | hasRoot: | yes | getNumberOfComponents: | 1 |
| key_path_expr.swift:14:16:14:35 | #keyPath(...) | hasType: | yes | hasRoot: | yes | getNumberOfComponents: | 2 |
| key_path_expr.swift:15:16:15:26 | #keyPath(...) | hasType: | yes | hasRoot: | yes | getNumberOfComponents: | 3 |
| key_path_expr.swift:16:20:16:30 | #keyPath(...) | hasType: | yes | hasRoot: | yes | getNumberOfComponents: | 4 |
| key_path_expr.swift:17:11:17:16 | #keyPath(...) | hasType: | yes | hasRoot: | yes | getNumberOfComponents: | 1 |
| key_path_expr.swift:18:20:18:32 | #keyPath(...) | hasType: | yes | hasRoot: | yes | getNumberOfComponents: | 1 |

View File

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

View File

@@ -0,0 +1,14 @@
| key_path_expr.swift:11:12:11:17 | #keyPath(...) | 0 | key_path_expr.swift:11:17:11:17 | KeyPathComponent |
| key_path_expr.swift:12:18:12:26 | #keyPath(...) | 0 | key_path_expr.swift:12:24:12:26 | KeyPathComponent |
| key_path_expr.swift:13:19:13:38 | #keyPath(...) | 0 | key_path_expr.swift:13:34:13:38 | KeyPathComponent |
| key_path_expr.swift:14:16:14:35 | #keyPath(...) | 0 | key_path_expr.swift:14:31:14:31 | KeyPathComponent |
| key_path_expr.swift:14:16:14:35 | #keyPath(...) | 1 | key_path_expr.swift:14:31:14:31 | KeyPathComponent |
| key_path_expr.swift:15:16:15:26 | #keyPath(...) | 0 | key_path_expr.swift:15:21:15:21 | KeyPathComponent |
| key_path_expr.swift:15:16:15:26 | #keyPath(...) | 1 | key_path_expr.swift:15:24:15:24 | KeyPathComponent |
| key_path_expr.swift:15:16:15:26 | #keyPath(...) | 2 | key_path_expr.swift:15:26:15:26 | KeyPathComponent |
| key_path_expr.swift:16:20:16:30 | #keyPath(...) | 0 | key_path_expr.swift:16:25:16:25 | KeyPathComponent |
| key_path_expr.swift:16:20:16:30 | #keyPath(...) | 1 | key_path_expr.swift:16:28:16:28 | KeyPathComponent |
| key_path_expr.swift:16:20:16:30 | #keyPath(...) | 2 | key_path_expr.swift:16:30:16:30 | KeyPathComponent |
| key_path_expr.swift:16:20:16:30 | #keyPath(...) | 3 | file://:0:0:0:0 | KeyPathComponent |
| key_path_expr.swift:17:11:17:16 | #keyPath(...) | 0 | key_path_expr.swift:17:16:17:16 | KeyPathComponent |
| key_path_expr.swift:18:20:18:32 | #keyPath(...) | 0 | key_path_expr.swift:18:32:18:32 | KeyPathComponent |

View File

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

View File

@@ -0,0 +1,8 @@
| key_path_expr.swift:11:12:11:17 | #keyPath(...) | key_path_expr.swift:11:13:11:13 | Foo |
| key_path_expr.swift:12:18:12:26 | #keyPath(...) | key_path_expr.swift:12:19:12:23 | [Int] |
| key_path_expr.swift:13:19:13:38 | #keyPath(...) | key_path_expr.swift:13:20:13:33 | [String : Int] |
| key_path_expr.swift:14:16:14:35 | #keyPath(...) | key_path_expr.swift:14:17:14:29 | Int? |
| key_path_expr.swift:15:16:15:26 | #keyPath(...) | key_path_expr.swift:15:17:15:17 | Foo |
| key_path_expr.swift:16:20:16:30 | #keyPath(...) | key_path_expr.swift:16:21:16:21 | Foo |
| key_path_expr.swift:17:11:17:16 | #keyPath(...) | key_path_expr.swift:17:12:17:12 | Int |
| key_path_expr.swift:18:20:18:32 | #keyPath(...) | key_path_expr.swift:18:21:18:30 | (Int, Int) |

View File

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

View File

@@ -0,0 +1,8 @@
| key_path_expr.swift:11:12:11:17 | #keyPath(...) | WritableKeyPath<Foo, Int> |
| key_path_expr.swift:12:18:12:26 | #keyPath(...) | WritableKeyPath<[Int], Int> |
| key_path_expr.swift:13:19:13:38 | #keyPath(...) | WritableKeyPath<[String : Int], Int?> |
| key_path_expr.swift:14:16:14:35 | #keyPath(...) | WritableKeyPath<Int?, Int> |
| key_path_expr.swift:15:16:15:26 | #keyPath(...) | KeyPath<Foo, Int?> |
| key_path_expr.swift:16:20:16:30 | #keyPath(...) | KeyPath<Foo, Int?> |
| key_path_expr.swift:17:11:17:16 | #keyPath(...) | WritableKeyPath<Int, Int> |
| key_path_expr.swift:18:20:18:32 | #keyPath(...) | WritableKeyPath<(Int, Int), Int> |

View File

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

View File

@@ -1,4 +0,0 @@
// generated by codegen/codegen.py
After a 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,18 @@
struct Bar {
var value : Int
var opt : Int?
}
struct Foo {
var value : Int
var opt : Bar?
}
let prop = \Foo.value
let arrElement = \[Int][0]
let dictElement = \[String : Int]["a"]
let optForce = \Optional<Int>.self!
let optChain = \Foo.opt?.opt
let optChainWrap = \Foo.opt?.value
let slf = \Int.self
let tupleElement = \(Int, Int).0

View File

@@ -0,0 +1,5 @@
| file://:0:0:0:0 | ... .combine(_:) | UnresolvedDotExpr |
| file://:0:0:0:0 | ... .combine(_:) | UnresolvedDotExpr |
| file://:0:0:0:0 | ... .combine(_:) | UnresolvedDotExpr |
| file://:0:0:0:0 | ... .combine(_:) | UnresolvedDotExpr |
| patterns.swift:16:12:16:12 | OverloadedDeclRefExpr | OverloadedDeclRefExpr |

View File

@@ -0,0 +1 @@
extractor-tests/errors/Errors.ql

View File

@@ -3005,24 +3005,38 @@ cfg.swift:
# 456| getElement(0): [PatternBindingDecl] var ... = ...
# 456| getInit(0): [KeyPathExpr] #keyPath(...)
# 456| getRoot(): [TypeRepr] A
# 456| getComponent(0): [KeyPathComponent] KeyPathComponent
# 456| getComponent(1): [KeyPathComponent] KeyPathComponent
# 456| getPattern(0): [NamedPattern] kpGet_b_x
# 456| getElement(1): [ConcreteVarDecl] kpGet_b_x
# 456| Type = WritableKeyPath<A, Int>
# 457| getElement(2): [PatternBindingDecl] var ... = ...
# 457| getInit(0): [KeyPathExpr] #keyPath(...)
# 457| getRoot(): [TypeRepr] A
# 457| getComponent(0): [KeyPathComponent] KeyPathComponent
# 457| getComponent(1): [KeyPathComponent] KeyPathComponent
# 457| getSubscriptArgument(0): [Argument] : 0
# 457| getExpr(): [IntegerLiteralExpr] 0
# 457| getComponent(2): [KeyPathComponent] KeyPathComponent
# 457| getPattern(0): [NamedPattern] kpGet_bs_0_x
# 457| getElement(3): [ConcreteVarDecl] kpGet_bs_0_x
# 457| Type = WritableKeyPath<A, Int>
# 458| getElement(4): [PatternBindingDecl] var ... = ...
# 458| getInit(0): [KeyPathExpr] #keyPath(...)
# 458| getRoot(): [TypeRepr] A
# 458| getComponent(0): [KeyPathComponent] KeyPathComponent
# 458| getComponent(1): [KeyPathComponent] KeyPathComponent
# 458| getComponent(2): [KeyPathComponent] KeyPathComponent
# 458| getPattern(0): [NamedPattern] kpGet_mayB_force_x
# 458| getElement(5): [ConcreteVarDecl] kpGet_mayB_force_x
# 458| Type = WritableKeyPath<A, Int>
# 459| getElement(6): [PatternBindingDecl] var ... = ...
# 459| getInit(0): [KeyPathExpr] #keyPath(...)
# 459| getRoot(): [TypeRepr] A
# 459| getComponent(0): [KeyPathComponent] KeyPathComponent
# 459| getComponent(1): [KeyPathComponent] KeyPathComponent
# 459| getComponent(2): [KeyPathComponent] KeyPathComponent
#-----| getComponent(3): [KeyPathComponent] KeyPathComponent
# 459| getPattern(0): [NamedPattern] kpGet_mayB_x
# 459| getElement(7): [ConcreteVarDecl] kpGet_mayB_x
# 459| Type = KeyPath<A, Int?>
@@ -4642,6 +4656,7 @@ expressions.swift:
# 54| getDest(): [DiscardAssignmentExpr] _
# 54| getSource(): [KeyPathExpr] #keyPath(...)
# 54| getRoot(): [TypeRepr] S
# 54| getComponent(0): [KeyPathComponent] KeyPathComponent
# 56| [ConcreteFuncDecl] unsafeFunction(pointer:)
# 56| InterfaceType = (UnsafePointer<Int>) -> ()
# 56| getParam(0): [ParamDecl] pointer
@@ -5252,6 +5267,7 @@ expressions.swift:
# 154| getKeyPath(): [DeclRefExpr] keyPathB
# 154| getKeyPath(): [KeyPathExpr] #keyPath(...)
# 154| getRoot(): [TypeRepr] B
# 154| getComponent(0): [KeyPathComponent] KeyPathComponent
# 154| getPattern(0): [NamedPattern] nested_apply
# 154| getElement(5): [ConcreteVarDecl] nested_apply
# 154| Type = Int
@@ -5322,6 +5338,244 @@ expressions.swift:
# 163| getExpr(): [IntegerLiteralExpr] 1
# 163| getArgument(1): [Argument] : 0
# 163| getExpr(): [IntegerLiteralExpr] 0
# 166| [StructDecl] Bar
# 167| getMember(0): [PatternBindingDecl] var ... = ...
# 167| getPattern(0): [TypedPattern] ... as ...
# 167| getSubPattern(): [NamedPattern] value
# 167| getTypeRepr(): [TypeRepr] Int
# 167| getMember(1): [ConcreteVarDecl] value
# 167| Type = Int
# 167| getAccessorDecl(0): [AccessorDecl] get
# 167| InterfaceType = (Bar) -> () -> Int
# 167| getSelfParam(): [ParamDecl] self
# 167| Type = Bar
# 167| getBody(): [BraceStmt] { ... }
#-----| getElement(0): [ReturnStmt] return ...
#-----| getResult(): [MemberRefExpr] .value
#-----| getBase(): [DeclRefExpr] self
# 167| getAccessorDecl(1): [AccessorDecl] set
# 167| InterfaceType = (inout Bar) -> (Int) -> ()
# 167| getSelfParam(): [ParamDecl] self
# 167| Type = Bar
# 167| getParam(0): [ParamDecl] value
# 167| Type = Int
# 167| getBody(): [BraceStmt] { ... }
#-----| getElement(0): [AssignExpr] ... = ...
#-----| getDest(): [MemberRefExpr] .value
#-----| getBase(): [DeclRefExpr] self
#-----| getSource(): [DeclRefExpr] value
# 167| getAccessorDecl(2): [AccessorDecl] _modify
# 167| InterfaceType = (inout Bar) -> () -> ()
# 167| getSelfParam(): [ParamDecl] self
# 167| Type = Bar
# 167| getBody(): [BraceStmt] { ... }
# 167| getElement(0): [YieldStmt] yield ...
#-----| getResult(0): [InOutExpr] &...
#-----| getSubExpr(): [MemberRefExpr] .value
#-----| getBase(): [DeclRefExpr] self
# 168| getMember(2): [PatternBindingDecl] var ... = ...
#-----| getInit(0): [NilLiteralExpr] nil
# 168| getPattern(0): [TypedPattern] ... as ...
# 168| getSubPattern(): [NamedPattern] opt
# 168| getTypeRepr(): [TypeRepr] Int?
# 168| getMember(3): [ConcreteVarDecl] opt
# 168| Type = Int?
# 168| getAccessorDecl(0): [AccessorDecl] get
# 168| InterfaceType = (Bar) -> () -> Int?
# 168| getSelfParam(): [ParamDecl] self
# 168| Type = Bar
# 168| getBody(): [BraceStmt] { ... }
#-----| getElement(0): [ReturnStmt] return ...
#-----| getResult(): [MemberRefExpr] .opt
#-----| getBase(): [DeclRefExpr] self
# 168| getAccessorDecl(1): [AccessorDecl] set
# 168| InterfaceType = (inout Bar) -> (Int?) -> ()
# 168| getSelfParam(): [ParamDecl] self
# 168| Type = Bar
# 168| getParam(0): [ParamDecl] value
# 168| Type = Int?
# 168| getBody(): [BraceStmt] { ... }
#-----| getElement(0): [AssignExpr] ... = ...
#-----| getDest(): [MemberRefExpr] .opt
#-----| getBase(): [DeclRefExpr] self
#-----| getSource(): [DeclRefExpr] value
# 168| getAccessorDecl(2): [AccessorDecl] _modify
# 168| InterfaceType = (inout Bar) -> () -> ()
# 168| getSelfParam(): [ParamDecl] self
# 168| Type = Bar
# 168| getBody(): [BraceStmt] { ... }
# 168| getElement(0): [YieldStmt] yield ...
#-----| getResult(0): [InOutExpr] &...
#-----| getSubExpr(): [MemberRefExpr] .opt
#-----| getBase(): [DeclRefExpr] self
# 166| getMember(4): [ConstructorDecl] Bar.init(value:opt:)
# 166| InterfaceType = (Bar.Type) -> (Int, Int?) -> Bar
# 166| getSelfParam(): [ParamDecl] self
# 166| Type = Bar
# 166| getParam(0): [ParamDecl] value
# 166| Type = Int
# 166| getParam(1): [ParamDecl] opt
# 166| Type = Int?
# 171| [StructDecl] Foo
# 172| getMember(0): [PatternBindingDecl] var ... = ...
# 172| getPattern(0): [TypedPattern] ... as ...
# 172| getSubPattern(): [NamedPattern] value
# 172| getTypeRepr(): [TypeRepr] Int
# 172| getMember(1): [ConcreteVarDecl] value
# 172| Type = Int
# 172| getAccessorDecl(0): [AccessorDecl] get
# 172| InterfaceType = (Foo) -> () -> Int
# 172| getSelfParam(): [ParamDecl] self
# 172| Type = Foo
# 172| getBody(): [BraceStmt] { ... }
#-----| getElement(0): [ReturnStmt] return ...
#-----| getResult(): [MemberRefExpr] .value
#-----| getBase(): [DeclRefExpr] self
# 172| getAccessorDecl(1): [AccessorDecl] set
# 172| InterfaceType = (inout Foo) -> (Int) -> ()
# 172| getSelfParam(): [ParamDecl] self
# 172| Type = Foo
# 172| getParam(0): [ParamDecl] value
# 172| Type = Int
# 172| getBody(): [BraceStmt] { ... }
#-----| getElement(0): [AssignExpr] ... = ...
#-----| getDest(): [MemberRefExpr] .value
#-----| getBase(): [DeclRefExpr] self
#-----| getSource(): [DeclRefExpr] value
# 172| getAccessorDecl(2): [AccessorDecl] _modify
# 172| InterfaceType = (inout Foo) -> () -> ()
# 172| getSelfParam(): [ParamDecl] self
# 172| Type = Foo
# 172| getBody(): [BraceStmt] { ... }
# 172| getElement(0): [YieldStmt] yield ...
#-----| getResult(0): [InOutExpr] &...
#-----| getSubExpr(): [MemberRefExpr] .value
#-----| getBase(): [DeclRefExpr] self
# 173| getMember(2): [PatternBindingDecl] var ... = ...
#-----| getInit(0): [NilLiteralExpr] nil
# 173| getPattern(0): [TypedPattern] ... as ...
# 173| getSubPattern(): [NamedPattern] opt
# 173| getTypeRepr(): [TypeRepr] Bar?
# 173| getMember(3): [ConcreteVarDecl] opt
# 173| Type = Bar?
# 173| getAccessorDecl(0): [AccessorDecl] get
# 173| InterfaceType = (Foo) -> () -> Bar?
# 173| getSelfParam(): [ParamDecl] self
# 173| Type = Foo
# 173| getBody(): [BraceStmt] { ... }
#-----| getElement(0): [ReturnStmt] return ...
#-----| getResult(): [MemberRefExpr] .opt
#-----| getBase(): [DeclRefExpr] self
# 173| getAccessorDecl(1): [AccessorDecl] set
# 173| InterfaceType = (inout Foo) -> (Bar?) -> ()
# 173| getSelfParam(): [ParamDecl] self
# 173| Type = Foo
# 173| getParam(0): [ParamDecl] value
# 173| Type = Bar?
# 173| getBody(): [BraceStmt] { ... }
#-----| getElement(0): [AssignExpr] ... = ...
#-----| getDest(): [MemberRefExpr] .opt
#-----| getBase(): [DeclRefExpr] self
#-----| getSource(): [DeclRefExpr] value
# 173| getAccessorDecl(2): [AccessorDecl] _modify
# 173| InterfaceType = (inout Foo) -> () -> ()
# 173| getSelfParam(): [ParamDecl] self
# 173| Type = Foo
# 173| getBody(): [BraceStmt] { ... }
# 173| getElement(0): [YieldStmt] yield ...
#-----| getResult(0): [InOutExpr] &...
#-----| getSubExpr(): [MemberRefExpr] .opt
#-----| getBase(): [DeclRefExpr] self
# 171| getMember(4): [ConstructorDecl] Foo.init(value:opt:)
# 171| InterfaceType = (Foo.Type) -> (Int, Bar?) -> Foo
# 171| getSelfParam(): [ParamDecl] self
# 171| Type = Foo
# 171| getParam(0): [ParamDecl] value
# 171| Type = Int
# 171| getParam(1): [ParamDecl] opt
# 171| Type = Bar?
# 176| [TopLevelCodeDecl] { ... }
# 176| getBody(): [BraceStmt] { ... }
# 176| getElement(0): [PatternBindingDecl] var ... = ...
# 176| getInit(0): [KeyPathExpr] #keyPath(...)
# 176| getRoot(): [TypeRepr] Foo
# 176| getComponent(0): [KeyPathComponent] KeyPathComponent
# 176| getPattern(0): [NamedPattern] prop
# 176| [ConcreteVarDecl] prop
# 176| Type = WritableKeyPath<Foo, Int>
# 177| [TopLevelCodeDecl] { ... }
# 177| getBody(): [BraceStmt] { ... }
# 177| getElement(0): [PatternBindingDecl] var ... = ...
# 177| getInit(0): [KeyPathExpr] #keyPath(...)
# 177| getRoot(): [TypeRepr] [Int]
# 177| getComponent(0): [KeyPathComponent] KeyPathComponent
# 177| getSubscriptArgument(0): [Argument] : 0
# 177| getExpr(): [IntegerLiteralExpr] 0
# 177| getPattern(0): [NamedPattern] arrElement
# 177| [ConcreteVarDecl] arrElement
# 177| Type = WritableKeyPath<[Int], Int>
# 178| [TopLevelCodeDecl] { ... }
# 178| getBody(): [BraceStmt] { ... }
# 178| getElement(0): [PatternBindingDecl] var ... = ...
# 178| getInit(0): [KeyPathExpr] #keyPath(...)
# 178| getRoot(): [TypeRepr] [String : Int]
# 178| getComponent(0): [KeyPathComponent] KeyPathComponent
# 178| getSubscriptArgument(0): [Argument] : a
# 178| getExpr(): [StringLiteralExpr] a
# 178| getPattern(0): [NamedPattern] dictElement
# 178| [ConcreteVarDecl] dictElement
# 178| Type = WritableKeyPath<[String : Int], Int?>
# 179| [TopLevelCodeDecl] { ... }
# 179| getBody(): [BraceStmt] { ... }
# 179| getElement(0): [PatternBindingDecl] var ... = ...
# 179| getInit(0): [KeyPathExpr] #keyPath(...)
# 179| getRoot(): [TypeRepr] Int?
# 179| getComponent(0): [KeyPathComponent] KeyPathComponent
# 179| getComponent(1): [KeyPathComponent] KeyPathComponent
# 179| getPattern(0): [NamedPattern] optForce
# 179| [ConcreteVarDecl] optForce
# 179| Type = WritableKeyPath<Int?, Int>
# 180| [TopLevelCodeDecl] { ... }
# 180| getBody(): [BraceStmt] { ... }
# 180| getElement(0): [PatternBindingDecl] var ... = ...
# 180| getInit(0): [KeyPathExpr] #keyPath(...)
# 180| getRoot(): [TypeRepr] Foo
# 180| getComponent(0): [KeyPathComponent] KeyPathComponent
# 180| getComponent(1): [KeyPathComponent] KeyPathComponent
# 180| getComponent(2): [KeyPathComponent] KeyPathComponent
# 180| getPattern(0): [NamedPattern] optChain
# 180| [ConcreteVarDecl] optChain
# 180| Type = KeyPath<Foo, Int?>
# 181| [TopLevelCodeDecl] { ... }
# 181| getBody(): [BraceStmt] { ... }
# 181| getElement(0): [PatternBindingDecl] var ... = ...
# 181| getInit(0): [KeyPathExpr] #keyPath(...)
# 181| getRoot(): [TypeRepr] Foo
# 181| getComponent(0): [KeyPathComponent] KeyPathComponent
# 181| getComponent(1): [KeyPathComponent] KeyPathComponent
# 181| getComponent(2): [KeyPathComponent] KeyPathComponent
#-----| getComponent(3): [KeyPathComponent] KeyPathComponent
# 181| getPattern(0): [NamedPattern] optChainWrap
# 181| [ConcreteVarDecl] optChainWrap
# 181| Type = KeyPath<Foo, Int?>
# 182| [TopLevelCodeDecl] { ... }
# 182| getBody(): [BraceStmt] { ... }
# 182| getElement(0): [PatternBindingDecl] var ... = ...
# 182| getInit(0): [KeyPathExpr] #keyPath(...)
# 182| getRoot(): [TypeRepr] Int
# 182| getComponent(0): [KeyPathComponent] KeyPathComponent
# 182| getPattern(0): [NamedPattern] slf
# 182| [ConcreteVarDecl] slf
# 182| Type = WritableKeyPath<Int, Int>
# 183| [TopLevelCodeDecl] { ... }
# 183| getBody(): [BraceStmt] { ... }
# 183| getElement(0): [PatternBindingDecl] var ... = ...
# 183| getInit(0): [KeyPathExpr] #keyPath(...)
# 183| getRoot(): [TypeRepr] (Int, Int)
# 183| getComponent(0): [KeyPathComponent] KeyPathComponent
# 183| getPattern(0): [NamedPattern] tupleElement
# 183| [ConcreteVarDecl] tupleElement
# 183| Type = WritableKeyPath<(Int, Int), Int>
patterns.swift:
# 1| [ConcreteFuncDecl] basic_patterns()
# 1| InterfaceType = () -> ()

View File

@@ -162,3 +162,22 @@ func bitwise() {
_ = 1 << 0
_ = 1 >> 0
}
struct Bar {
var value : Int
var opt : Int?
}
struct Foo {
var value : Int
var opt : Bar?
}
let prop = \Foo.value
let arrElement = \[Int][0]
let dictElement = \[String : Int]["a"]
let optForce = \Optional<Int>.self!
let optChain = \Foo.opt?.opt
let optChainWrap = \Foo.opt?.value
let slf = \Int.self
let tupleElement = \(Int, Int).0

View File

@@ -0,0 +1,14 @@
| file://:0:0:0:0 | KeyPathComponent | getKind: | 7 | | | | | optional wrapping | | |
| key_path_expr.swift:11:17:11:17 | KeyPathComponent | getKind: | 3 | property | | | | | | |
| key_path_expr.swift:12:24:12:26 | KeyPathComponent | getKind: | 4 | | subscript | | | | | |
| key_path_expr.swift:13:34:13:38 | KeyPathComponent | getKind: | 4 | | subscript | | | | | |
| key_path_expr.swift:14:31:14:31 | KeyPathComponent | getKind: | 5 | | | optional forcing | | | | |
| key_path_expr.swift:14:31:14:31 | KeyPathComponent | getKind: | 8 | | | | | | self | |
| key_path_expr.swift:15:21:15:21 | KeyPathComponent | getKind: | 3 | property | | | | | | |
| key_path_expr.swift:15:24:15:24 | KeyPathComponent | getKind: | 6 | | | | optional chaining | | | |
| key_path_expr.swift:15:26:15:26 | KeyPathComponent | getKind: | 3 | property | | | | | | |
| key_path_expr.swift:16:25:16:25 | KeyPathComponent | getKind: | 3 | property | | | | | | |
| key_path_expr.swift:16:28:16:28 | KeyPathComponent | getKind: | 6 | | | | optional chaining | | | |
| key_path_expr.swift:16:30:16:30 | KeyPathComponent | getKind: | 3 | property | | | | | | |
| key_path_expr.swift:17:16:17:16 | KeyPathComponent | getKind: | 8 | | | | | | self | |
| key_path_expr.swift:18:32:18:32 | KeyPathComponent | getKind: | 9 | | | | | | | tuple indexing |

View File

@@ -0,0 +1,18 @@
import codeql.swift.elements
import TestUtils
from
KeyPathComponent x, string property, string subscript, string opt_forcing, string opt_chaining,
string opt_wrapping, string self, string tuple_indexing
where
toBeTested(x) and
not x.isUnknown() and
(if x.isProperty() then property = "property" else property = "") and
(if x.isSubscript() then subscript = "subscript" else subscript = "") and
(if x.isOptionalForcing() then opt_forcing = "optional forcing" else opt_forcing = "") and
(if x.isOptionalChaining() then opt_chaining = "optional chaining" else opt_chaining = "") and
(if x.isOptionalWrapping() then opt_wrapping = "optional wrapping" else opt_wrapping = "") and
(if x.isSelf() then self = "self" else self = "") and
if x.isTupleIndexing() then tuple_indexing = "tuple indexing" else tuple_indexing = ""
select x, "getKind:", x.getKind(), property, subscript, opt_forcing, opt_chaining, opt_wrapping,
self, tuple_indexing

View File

@@ -0,0 +1,18 @@
struct Bar {
var value : Int
var opt : Int?
}
struct Foo {
var value : Int
var opt : Bar?
}
let prop = \Foo.value
let arrElement = \[Int][0]
let dictElement = \[String : Int]["a"]
let optForce = \Optional<Int>.self!
let optChain = \Foo.opt?.opt
let optChainWrap = \Foo.opt?.value
let slf = \Int.self
let tupleElement = \(Int, Int).0

View File

@@ -449,9 +449,38 @@ class KeyPathApplicationExpr(Expr):
class KeyPathDotExpr(Expr):
pass
class KeyPathComponent(AstNode):
"""
A component of a `KeyPathExpr`.
"""
kind: int | doc("kind of key path component") | desc("""
INTERNAL: Do not use.
This is 3 for properties, 4 for array and dictionary subscripts, 5 for optional forcing
(`!`), 6 for optional chaining (`?`), 7 for implicit optional wrapping, 8 for `self`,
and 9 for tuple element indexing.
The following values should not appear: 0 for invalid components, 1 for unresolved
properties, 2 for unresolved subscripts, 10 for #keyPath dictionary keys, and 11 for
implicit IDE code completion data.
""")
subscript_arguments : list[Argument] | child | doc(
"arguments to an array or dictionary subscript expression")
tuple_index : optional[int]
decl_ref : optional[ValueDecl] | doc("property or subscript operator")
component_type : Type | doc("return type of this component application") | desc("""
An optional-chaining component has a non-optional type to feed into the rest of the key
path; an optional-wrapping component is inserted if required to produce an optional type
as the final output.
""")
class KeyPathExpr(Expr):
"""
A key-path expression.
"""
root: optional["TypeRepr"] | child
parsed_path: optional[Expr] | child
components: list[KeyPathComponent] | child
class LazyInitializerExpr(Expr):
sub_expr: Expr | child