Swift: extract availability info

This commit is contained in:
Alex Denisov
2023-02-07 12:42:14 +01:00
parent 984729f9b0
commit 712c25e6f4
35 changed files with 603 additions and 13 deletions

View File

@@ -30,7 +30,9 @@ class SwiftDispatcher {
const swift::Pattern*,
const swift::TypeRepr*,
const swift::TypeBase*,
const swift::CapturedValue*>;
const swift::CapturedValue*,
const swift::PoundAvailableInfo*,
const swift::AvailabilitySpec*>;
template <typename E>
static constexpr bool IsStorable = std::is_constructible_v<Store::Handle, const E&>;
@@ -227,6 +229,10 @@ class SwiftDispatcher {
attachLocation(clause->Loc, clause->Loc, locatableLabel);
}
void attachLocation(swift::AvailabilitySpec* spec, TrapLabel<LocatableTag> locatableLabel) {
attachLocation(spec->getSourceRange().Start, spec->getSourceRange().End, 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);
@@ -364,6 +370,8 @@ class SwiftDispatcher {
virtual void visit(const swift::Stmt* stmt) = 0;
virtual void visit(const swift::StmtCondition* cond) = 0;
virtual void visit(const swift::StmtConditionElement* cond) = 0;
virtual void visit(const swift::PoundAvailableInfo* availability) = 0;
virtual void visit(const swift::AvailabilitySpec* spec) = 0;
virtual void visit(const swift::CaseLabelItem* item) = 0;
virtual void visit(const swift::Expr* expr) = 0;
virtual void visit(const swift::Pattern* pattern) = 0;

View File

@@ -315,6 +315,13 @@ MAP(swift::TypeBase, TypeTag)
MAP(swift::OptionalType, OptionalTypeTag)
MAP(swift::VariadicSequenceType, VariadicSequenceTypeTag)
MAP(swift::DictionaryType, DictionaryTypeTag)
MAP(swift::AvailabilitySpec, AvailabilitySpecTag)
MAP(swift::PlatformVersionConstraintAvailabilitySpec, PlatformVersionAvailabilitySpecTag)
MAP(swift::OtherPlatformAvailabilitySpec, OtherAvailabilitySpecTag)
MAP(swift::PoundAvailableInfo, AvailabilityInfoTag)
// clang-format on
#undef MAP
#undef MAP_CONCRETE

View File

@@ -15,6 +15,8 @@ void StmtTranslator::translateAndEmit(const swift::StmtConditionElement& element
} else if (auto pattern = element.getPatternOrNull()) {
entry.pattern = dispatcher.fetchLabel(pattern);
entry.initializer = dispatcher.fetchLabel(element.getInitializer());
} else if (auto availability = element.getAvailability()) {
entry.availability = dispatcher.fetchLabel(availability);
}
dispatcher.emit(entry);
}
@@ -26,6 +28,33 @@ void StmtTranslator::translateAndEmit(const swift::CaseLabelItem& labelItem) {
dispatcher.emit(entry);
}
void StmtTranslator::translateAndEmit(const swift::PoundAvailableInfo& availability) {
auto entry = dispatcher.createEntry(availability);
entry.is_unavailable = availability.isUnavailability();
entry.specs = dispatcher.fetchRepeatedLabels(availability.getQueries());
dispatcher.emit(entry);
}
void StmtTranslator::translateAndEmit(const swift::AvailabilitySpec& spec) {
if (llvm::isa<swift::PlatformVersionConstraintAvailabilitySpec>(spec)) {
translateAndEmit(llvm::cast<swift::PlatformVersionConstraintAvailabilitySpec>(spec));
} else if (llvm::isa<swift::OtherPlatformAvailabilitySpec>(spec)) {
translateAndEmit(llvm::cast<swift::OtherPlatformAvailabilitySpec>(spec));
}
}
void StmtTranslator::translateAndEmit(
const swift::PlatformVersionConstraintAvailabilitySpec& spec) {
auto entry = dispatcher.createEntry(spec);
entry.platform = swift::platformString(spec.getPlatform()).str();
entry.version = spec.getVersion().getAsString();
dispatcher.emit(entry);
}
void StmtTranslator::translateAndEmit(const swift::OtherPlatformAvailabilitySpec& spec) {
dispatcher.emit(dispatcher.createEntry(spec));
}
codeql::BraceStmt StmtTranslator::translateBraceStmt(const swift::BraceStmt& stmt) {
auto entry = dispatcher.createEntry(stmt);
entry.elements = dispatcher.fetchRepeatedLabels(stmt.getElements());

View File

@@ -13,6 +13,10 @@ class StmtTranslator : public AstTranslatorBase<StmtTranslator> {
void translateAndEmit(const swift::StmtCondition& cond);
void translateAndEmit(const swift::StmtConditionElement& element);
void translateAndEmit(const swift::CaseLabelItem& labelItem);
void translateAndEmit(const swift::PoundAvailableInfo& availability);
void translateAndEmit(const swift::AvailabilitySpec& spec);
void translateAndEmit(const swift::PlatformVersionConstraintAvailabilitySpec& spec);
void translateAndEmit(const swift::OtherPlatformAvailabilitySpec& spec);
codeql::BraceStmt translateBraceStmt(const swift::BraceStmt& stmt);
codeql::ReturnStmt translateReturnStmt(const swift::ReturnStmt& stmt);

View File

@@ -27,6 +27,12 @@ class SwiftVisitor : private SwiftDispatcher {
void visit(const swift::StmtConditionElement* element) override {
stmtTranslator.translateAndEmit(*element);
}
void visit(const swift::PoundAvailableInfo* availability) override {
stmtTranslator.translateAndEmit(*availability);
}
void visit(const swift::AvailabilitySpec* spec) override {
stmtTranslator.translateAndEmit(*spec);
}
void visit(const swift::CaseLabelItem* item) override { stmtTranslator.translateAndEmit(*item); }
void visit(const swift::Expr* expr) override { exprTranslator.translateAndEmit(*expr); }

View File

@@ -1,3 +1,5 @@
ql/lib/codeql/swift/elements/AvailabilityInfoConstructor.qll 15100f8446c961ca57871ac296c854a19678a84ebaa8faac0b6eb1377a3e0f77 f079769d6e7f9e38995e196863e11108fc1bc42e8f037d6f6bb51cfd351a3465
ql/lib/codeql/swift/elements/AvailabilitySpec.qll 1e885dc834114454ee7dc1c7127cabcf4af1cb7d8ce634d60bb60f20e630de53 893fc1c2f8317af35dc9039e4c43c4554c4502993d9f0bb0debf8e0e760670bb
ql/lib/codeql/swift/elements/CommentConstructor.qll c5a4c55fb26e57a9b4efcff329b428f7de22406b35198d99290b6e646794777a 326365475f2fda857ffa00e1c7841089660eca02d739400b6d62ed6f39ea4d03
ql/lib/codeql/swift/elements/DbFile.qll 9e0f3c54075f75af82a9c917777755f47cb04a5777b064f5cba4a951414ac004 a3b08dd6ccd18d1a5f6f29b829da473c28a921e8d626b264b4b73515a49164f9
ql/lib/codeql/swift/elements/DbFileConstructor.qll 2913b16780f4369b405a088bb70f3b0f941b2978e8827ed30745f2ab7ba0cd8e c21b21b100d0b245bb1d498b4c3696db73dd710a5be211c6b825ebf733681da7
@@ -5,6 +7,8 @@ ql/lib/codeql/swift/elements/DbLocation.qll e3e7bf56c7857329e250a44e9df1ccb31f6c
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 6b6be3731a2fd178e5093ddebb7cd519ecc5fbbd549bd4dbd5f69687791c3630 ab0028bab8a9ed14c6b4bfe0f8a10e4768ea1e21f86b495258021ab9b8e65aeb
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
ql/lib/codeql/swift/elements/decl/AbstractStorageDecl.qll 6196ecc35d358e6fe1c34b0478c0479acd0f0de67a64daac4d814af90a87d514 74a74330a953d16ce1cc19b2dbabdf8c8ff0fc3d250d101b8108a6597844e179
ql/lib/codeql/swift/elements/decl/AbstractTypeParamDecl.qll 83950437007703c0f35ef154f46577d8754fb191c93772ff718b29107ce8852e 737ad9c857c079605e84dc7ebaecbafa86fe129283756b98e6e574ac9e24c22c
@@ -364,8 +368,10 @@ ql/lib/codeql/swift/elements/type/VariadicSequenceType.qll 5bca77dd661d3b2653d31
ql/lib/codeql/swift/elements/type/VariadicSequenceTypeConstructor.qll 0d1d2328a3b5e503a883e7e6d7efd0ca5e7f2633abead9e4c94a9f98ed3cb223 69bff81c1b9413949eacb9298d2efb718ea808e68364569a1090c9878c4af856
ql/lib/codeql/swift/elements/type/WeakStorageType.qll 87a28616eea3600fb0156fffcd65eeddc1ea74ce9c0ba5886c6365b9359e00ce 9c968414d7cc8d672f3754bced5d4f83f43a6d7872d0d263d79ff60483e1f996
ql/lib/codeql/swift/elements/type/WeakStorageTypeConstructor.qll d88b031ef44d6de14b3ddcff2eb47b53dbd11550c37250ff2edb42e5d21ec3e9 26d855c33492cf7a118e439f7baeed0e5425cfaf058b1dcc007eca7ed765c897
ql/lib/codeql/swift/elements.qll 3d387d94fce53782d0729062e3b4f0235e8a92365371410bfd4850b0b5bf2972 3d387d94fce53782d0729062e3b4f0235e8a92365371410bfd4850b0b5bf2972
ql/lib/codeql/swift/elements.qll 82b69a48b7afffeb97cafd9fdc57af96b672e21879580a6cfc3bae2a49bc2c40 82b69a48b7afffeb97cafd9fdc57af96b672e21879580a6cfc3bae2a49bc2c40
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 b7b1d14410927b80d11c80a507b6dfec72da01c403ee5db8ed2fe62efb821187 3aa96ba7cc7d8bf26a0c622130dcb79d24fcd346f9a3134afb08862c0fc18a64
ql/lib/codeql/swift/generated/Callable.qll 042b4f975f1e416c48b5bf26bee257549eec13fb262f11025375560f75a73582 0434788243bc54e48fec49e4cce93509b9a2333f2079dacb6ffc12c972853540
ql/lib/codeql/swift/generated/Comment.qll f58b49f6e68c21f87c51e2ff84c8a64b09286d733e86f70d67d3a98fe6260bd6 975bbb599a2a7adc35179f6ae06d9cbc56ea8a03b972ef2ee87604834bc6deb1
ql/lib/codeql/swift/generated/DbFile.qll a49b2a2cb2788cb49c861ebcd458b8daead7b15adb19c3a9f4db3bf39a0051fc a49b2a2cb2788cb49c861ebcd458b8daead7b15adb19c3a9f4db3bf39a0051fc
@@ -376,11 +382,13 @@ ql/lib/codeql/swift/generated/ErrorElement.qll 4b032abe8ffb71376a29c63e470a52943
ql/lib/codeql/swift/generated/File.qll 61454459f5f1ae378bd4970ad1da4f39f3e696bac8a5eebdd162f131995c5316 3e6805f8858cd55dd0e0d0e5aeab923d6a55292dbf98b0029db1ae0208efe684
ql/lib/codeql/swift/generated/Locatable.qll bdc98b9fb7788f44a4bf7e487ee5bd329473409950a8e9f116d61995615ad849 0b36b4fe45e2aa195e4bb70c50ea95f32f141b8e01e5f23466c6427dd9ab88fb
ql/lib/codeql/swift/generated/Location.qll 851766e474cdfdfa67da42e0031fc42dd60196ff5edd39d82f08d3e32deb84c1 b29b2c37672f5acff15f1d3c5727d902f193e51122327b31bd27ec5f877bca3b
ql/lib/codeql/swift/generated/ParentChild.qll 0fd3bb2a1264144804434314ec09ffba6e095a862d075437e8c02ef20dc974c3 a945a9b8a1790587d7926062799fe51af60f53db159a9bf4d86bbfd5910e5c58
ql/lib/codeql/swift/generated/OtherAvailabilitySpec.qll 0e26a203b26ff0581b7396b0c6d1606feec5cc32477f676585cdec4911af91c5 0e26a203b26ff0581b7396b0c6d1606feec5cc32477f676585cdec4911af91c5
ql/lib/codeql/swift/generated/ParentChild.qll adf8af53ce18086eb28e5fe204ad2089f2ab516622c16055ccfdd1335f5ac72b 6f7464ecd8ca04b6aa261139b36a162e5b0636237d514b8431ef4f97a1c603dc
ql/lib/codeql/swift/generated/PlatformVersionAvailabilitySpec.qll f82d9ca416fe8bd59b5531b65b1c74c9f317b3297a6101544a11339a1cffce38 d21d5bfb136fe8a8bcbd39321632f52c63e62747eb831b900c23d8af3155942d
ql/lib/codeql/swift/generated/PureSynthConstructors.qll 173c0dd59396a1de26fe870e3bc2766c46de689da2a4d8807cb62023bbce1a98 173c0dd59396a1de26fe870e3bc2766c46de689da2a4d8807cb62023bbce1a98
ql/lib/codeql/swift/generated/Raw.qll 786b9cfeace7dca3f8183f6e425cb15b8bf056d817bd9e3893f708b00df05415 51cd6a521e6109e7006faa74da2d6d2b1e3d457f46c1f2d28e2a76d1fa8b16f7
ql/lib/codeql/swift/generated/Synth.qll 51621505f034f24980e7a940062970b82a74dbf1cd1df507dd50fb00876f6b7c 2ab724386c2eff89cf3894b7dbe91fad27f828eabc01455b9ac2f4b6b44c881e
ql/lib/codeql/swift/generated/SynthConstructors.qll 79e4ffbc85a80b1d2c74c45449cd077fbf33d4498ccf93a51351ad0c7cc461ea 79e4ffbc85a80b1d2c74c45449cd077fbf33d4498ccf93a51351ad0c7cc461ea
ql/lib/codeql/swift/generated/Raw.qll 6fe6560ff3533df93afa67dd98494ce985f1e8e402c0a608b7c163d0473f87e8 e38f3a09f7a64e2c025d05cbc502c74655c38d50bc28540fb3dc7000225b8779
ql/lib/codeql/swift/generated/Synth.qll af02e0b49fe7b488592687996cc74d9525d4e3fbc9d324820b310b356f4d2612 5c740a660721173e9e4e45eb701d373ca19ff14d61cdaea309b65871e0deea90
ql/lib/codeql/swift/generated/SynthConstructors.qll a1b3ca33017f82124286ccad317a05484fee144fb9c3cdd2e500ce38e5efcec4 a1b3ca33017f82124286ccad317a05484fee144fb9c3cdd2e500ce38e5efcec4
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
@@ -565,7 +573,7 @@ ql/lib/codeql/swift/generated/stmt/BraceStmt.qll 121c669fc98bf5ed1f17e98fdfc36ae
ql/lib/codeql/swift/generated/stmt/BreakStmt.qll 31d6b2969a919062c46e7bf0203f91c3489ee3c364e73fc2788f0e06ac109b25 7fca57698a821e81903204f271d0a220adfdd50ff144eafd6868286aa6aefa33
ql/lib/codeql/swift/generated/stmt/CaseLabelItem.qll 0755fabf3ca7a5ee9a553dec0a6d8af3c8abdc99015c229ce1c4b154a3af80d9 b3c9b88610a3dc729a5eb4f9667710d84a5ac0f3acddcda3031e744309265c68
ql/lib/codeql/swift/generated/stmt/CaseStmt.qll 3cbb4e5e1e04931489adf252d809e0f153bfd32fb32cf05917ded5c418e78695 c80f22ce4915073e787634e015f7461b4b64cf100ad7705f4b1507cef1e88ea7
ql/lib/codeql/swift/generated/stmt/ConditionElement.qll fd53a99d1af1e16412424c0c48eae7c866db4fd491f2de6d5a5271f227a96275 599db45ed78be3943b76c1ff4ae24cd8a9ff8d1f875d1718ab884e4507843995
ql/lib/codeql/swift/generated/stmt/ConditionElement.qll 46fe0a39e64765f32f5dd58bcd6c54f161806754fdac5579e89a91bc7d498abf aaedd5410971aeb875a4fbcb1464c5e84341fafcbdaacbd4d9d3c69b4a25bcc2
ql/lib/codeql/swift/generated/stmt/ContinueStmt.qll 3213c4ede9c8240bcb1d1c02ee6171821cdfbf89056f1e5c607428dcfaf464f6 00756c533dfd9ee5402e739f360dfe5203ee2043e20fc1982d7782ca7a249f9a
ql/lib/codeql/swift/generated/stmt/DeferStmt.qll 69a8e04618569b61ce680bae1d20cda299eea6064f50433fa8a5787114a6cf5e 12c4f66fc74803f276bbb65e8a696f9bd47cc2a8edfebb286f5c3b2a5b6efce7
ql/lib/codeql/swift/generated/stmt/DoCatchStmt.qll f8d2e7366524518933bd59eb66f0ac13266c4483ec4e71c6c4e4e890374787a1 31529884d5c49f119491f8add3bc06dd47ca0a094c4db6b3d84693db6a9cc489
@@ -650,9 +658,13 @@ ql/lib/codeql/swift/generated/type/UnownedStorageType.qll 062fd6e902ecbde78a7b8a
ql/lib/codeql/swift/generated/type/UnresolvedType.qll 4bdb583cf2bf654a6a37486d06a14fd631b715f47f7e8aea314d939143c5c6c9 4bdb583cf2bf654a6a37486d06a14fd631b715f47f7e8aea314d939143c5c6c9
ql/lib/codeql/swift/generated/type/VariadicSequenceType.qll 796537097d8e32eda38be55adde9ec935e25c74ff7450f7ce8cd687c50c0ba89 796537097d8e32eda38be55adde9ec935e25c74ff7450f7ce8cd687c50c0ba89
ql/lib/codeql/swift/generated/type/WeakStorageType.qll dda4397a49f537ec44117a86dc09705a07d281e31bf4643738b15219053ed380 dda4397a49f537ec44117a86dc09705a07d281e31bf4643738b15219053ed380
ql/test/extractor-tests/generated/AvailabilityInfo/AvailabilityInfo.ql 6e06e222636d5e3451afdce4d5e1b801206a0abf060cc5714350d25e784f8eda 3274ca1b3d85142037d0f12ecf9e15f77c3eeb285621adc9312a6691806d08c8
ql/test/extractor-tests/generated/AvailabilityInfo/AvailabilityInfo_getSpec.ql 44ccccad28d8648aa3349d9290bd1478bb021797c26bc2f8c1e3de14a42be3bd aefab61b6fa1c06c5c79d337cffb61335dca74ef9906deba12f7eaea42f9ac14
ql/test/extractor-tests/generated/Comment/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd
ql/test/extractor-tests/generated/Diagnostics/Diagnostics.ql 6a4a9480cc929381e0337b181e5ac519a7abc6d597ebe24fb6701acf79ced86f 199c5bf8bd38e161d989e0e4db1ea1d3ddcb4d7cf571afd9112ce3ed8d9b8d2a
ql/test/extractor-tests/generated/File/File.ql ab0968ae31b749da2b66462bd04e4dfb30604dba405a84594b575abfc4fa4c35 bcc0ff648b28c5ecd567e196e700272883756bbcc65296bbb880a979e3162628
ql/test/extractor-tests/generated/OtherAvailabilitySpec/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd
ql/test/extractor-tests/generated/PlatformVersionAvailabilitySpec/MISSING_SOURCE.txt 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd 7e714762ffb48c436102027d560fb5addc1f7dc6dd6936b06e0d3cca031d67fd
ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl.ql 5c017af7e6b16ee68990eec12affe81eb114338bac4d445f4b231fe0f110eccc db86c828a892b0acd150a780914e7e48c280cad473d3680a453bdee03aee1e9d
ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getBody.ql 1d42eb1a5b832cfaf1949b61a01a6a11448a6d4369a44f2511bb31d1d7fc10a8 b326a6743121353f8a66410d3d9151ca969939abcbbe5c411872ca290da45123
ql/test/extractor-tests/generated/decl/AccessorDecl/AccessorDecl_getCapture.ql 17f9903978c9a8fc607d970532270090cea030ff57c2f6699c37672707ce5c70 cdd7ce47691a84aa5402a8946d4027f7b9dbce930057dfd62c14b470a5710cb0

View File

@@ -1,5 +1,7 @@
// generated by codegen/codegen.py
import codeql.swift.elements.AstNode
import codeql.swift.elements.AvailabilityInfo
import codeql.swift.elements.AvailabilitySpec
import codeql.swift.elements.Callable
import codeql.swift.elements.Comment
import codeql.swift.elements.DbFile
@@ -10,6 +12,8 @@ import codeql.swift.elements.ErrorElement
import codeql.swift.elements.File
import codeql.swift.elements.Locatable
import codeql.swift.elements.Location
import codeql.swift.elements.OtherAvailabilitySpec
import codeql.swift.elements.PlatformVersionAvailabilitySpec
import codeql.swift.elements.UnknownFile
import codeql.swift.elements.UnknownLocation
import codeql.swift.elements.UnspecifiedElement

View File

@@ -0,0 +1,9 @@
private import codeql.swift.generated.AvailabilityInfo
class AvailabilityInfo extends Generated::AvailabilityInfo {
override string toString() {
result = "#available" and not isUnavailable()
or
result = "#unavailable" and isUnavailable()
}
}

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 constructAvailabilityInfo(Raw::AvailabilityInfo id) { any() }

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.AvailabilitySpec
class AvailabilitySpec extends Generated::AvailabilitySpec { }

View File

@@ -0,0 +1,5 @@
private import codeql.swift.generated.OtherAvailabilitySpec
class OtherAvailabilitySpec extends Generated::OtherAvailabilitySpec {
override string toString() { result = "*" }
}

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 constructOtherAvailabilitySpec(Raw::OtherAvailabilitySpec id) { any() }

View File

@@ -0,0 +1,5 @@
private import codeql.swift.generated.PlatformVersionAvailabilitySpec
class PlatformVersionAvailabilitySpec extends Generated::PlatformVersionAvailabilitySpec {
override string toString() { result = getPlatform() + " " + getVersion() }
}

View File

@@ -0,0 +1,6 @@
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
private import codeql.swift.generated.Raw
predicate constructPlatformVersionAvailabilitySpec(Raw::PlatformVersionAvailabilitySpec id) {
any()
}

View File

@@ -0,0 +1,61 @@
// generated by codegen/codegen.py
private import codeql.swift.generated.Synth
private import codeql.swift.generated.Raw
import codeql.swift.elements.AstNode
import codeql.swift.elements.AvailabilitySpec
module Generated {
/**
* An availability condition of an `if`, `while`, or `guard` statements.
*
* Examples:
* ```
* if #available(iOS 12, *) {
* // Runs on iOS 12 and above
* } else {
* // Runs only anything below iOS 12
* }
* if #unavailable(macOS 10.14, *) {
* // Runs only on macOS 10 and below
* }
* ```
*/
class AvailabilityInfo extends Synth::TAvailabilityInfo, AstNode {
override string getAPrimaryQlClass() { result = "AvailabilityInfo" }
/**
* Holds if it is #unavailable as opposed to #available.
*/
predicate isUnavailable() {
Synth::convertAvailabilityInfoToRaw(this).(Raw::AvailabilityInfo).isUnavailable()
}
/**
* Gets the `index`th spec of this availability info (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.
*/
AvailabilitySpec getImmediateSpec(int index) {
result =
Synth::convertAvailabilitySpecFromRaw(Synth::convertAvailabilityInfoToRaw(this)
.(Raw::AvailabilityInfo)
.getSpec(index))
}
/**
* Gets the `index`th spec of this availability info (0-based).
*/
final AvailabilitySpec getSpec(int index) { result = getImmediateSpec(index).resolve() }
/**
* Gets any of the specs of this availability info.
*/
final AvailabilitySpec getASpec() { result = getSpec(_) }
/**
* Gets the number of specs of this availability info.
*/
final int getNumberOfSpecs() { result = count(int i | exists(getSpec(i))) }
}
}

View File

@@ -0,0 +1,8 @@
// generated by codegen/codegen.py
private import codeql.swift.generated.Synth
private import codeql.swift.generated.Raw
import codeql.swift.elements.AstNode
module Generated {
class AvailabilitySpec extends Synth::TAvailabilitySpec, AstNode { }
}

View File

@@ -0,0 +1,13 @@
// generated by codegen/codegen.py
private import codeql.swift.generated.Synth
private import codeql.swift.generated.Raw
import codeql.swift.elements.AvailabilitySpec
module Generated {
/**
* A wildcard availability spec `*`
*/
class OtherAvailabilitySpec extends Synth::TOtherAvailabilitySpec, AvailabilitySpec {
override string getAPrimaryQlClass() { result = "OtherAvailabilitySpec" }
}
}

View File

@@ -185,6 +185,40 @@ private module Impl {
)
}
private Element getImmediateChildOfAvailabilityInfo(
AvailabilityInfo e, int index, string partialPredicateCall
) {
exists(int b, int bAstNode, int n, int nSpec |
b = 0 and
bAstNode = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAstNode(e, i, _)) | i) and
n = bAstNode and
nSpec = n + 1 + max(int i | i = -1 or exists(e.getImmediateSpec(i)) | i) and
(
none()
or
result = getImmediateChildOfAstNode(e, index - b, partialPredicateCall)
or
result = e.getImmediateSpec(index - n) and
partialPredicateCall = "Spec(" + (index - n).toString() + ")"
)
)
}
private Element getImmediateChildOfAvailabilitySpec(
AvailabilitySpec e, int index, string partialPredicateCall
) {
exists(int b, int bAstNode, int n |
b = 0 and
bAstNode = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAstNode(e, i, _)) | i) and
n = bAstNode and
(
none()
or
result = getImmediateChildOfAstNode(e, index - b, partialPredicateCall)
)
)
}
private Element getImmediateChildOfUnspecifiedElement(
UnspecifiedElement e, int index, string partialPredicateCall
) {
@@ -201,6 +235,38 @@ private module Impl {
)
}
private Element getImmediateChildOfOtherAvailabilitySpec(
OtherAvailabilitySpec e, int index, string partialPredicateCall
) {
exists(int b, int bAvailabilitySpec, int n |
b = 0 and
bAvailabilitySpec =
b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAvailabilitySpec(e, i, _)) | i) and
n = bAvailabilitySpec and
(
none()
or
result = getImmediateChildOfAvailabilitySpec(e, index - b, partialPredicateCall)
)
)
}
private Element getImmediateChildOfPlatformVersionAvailabilitySpec(
PlatformVersionAvailabilitySpec e, int index, string partialPredicateCall
) {
exists(int b, int bAvailabilitySpec, int n |
b = 0 and
bAvailabilitySpec =
b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAvailabilitySpec(e, i, _)) | i) and
n = bAvailabilitySpec and
(
none()
or
result = getImmediateChildOfAvailabilitySpec(e, index - b, partialPredicateCall)
)
)
}
private Element getImmediateChildOfDecl(Decl e, int index, string partialPredicateCall) {
exists(int b, int bAstNode, int n, int nMember |
b = 0 and
@@ -3308,13 +3374,16 @@ private module Impl {
private Element getImmediateChildOfConditionElement(
ConditionElement e, int index, string partialPredicateCall
) {
exists(int b, int bAstNode, int n, int nBoolean, int nPattern, int nInitializer |
exists(
int b, int bAstNode, int n, int nBoolean, int nPattern, int nInitializer, int nAvailability
|
b = 0 and
bAstNode = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAstNode(e, i, _)) | i) and
n = bAstNode and
nBoolean = n + 1 and
nPattern = nBoolean + 1 and
nInitializer = nPattern + 1 and
nAvailability = nInitializer + 1 and
(
none()
or
@@ -3327,6 +3396,10 @@ private module Impl {
index = nPattern and
result = e.getImmediateInitializer() and
partialPredicateCall = "Initializer()"
or
index = nInitializer and
result = e.getImmediateAvailability() and
partialPredicateCall = "Availability()"
)
)
}
@@ -4755,8 +4828,14 @@ private module Impl {
or
result = getImmediateChildOfUnknownLocation(e, index, partialAccessor)
or
result = getImmediateChildOfAvailabilityInfo(e, index, partialAccessor)
or
result = getImmediateChildOfUnspecifiedElement(e, index, partialAccessor)
or
result = getImmediateChildOfOtherAvailabilitySpec(e, index, partialAccessor)
or
result = getImmediateChildOfPlatformVersionAvailabilitySpec(e, index, partialAccessor)
or
result = getImmediateChildOfCapturedDecl(e, index, partialAccessor)
or
result = getImmediateChildOfEnumCaseDecl(e, index, partialAccessor)

View File

@@ -0,0 +1,34 @@
// generated by codegen/codegen.py
private import codeql.swift.generated.Synth
private import codeql.swift.generated.Raw
import codeql.swift.elements.AvailabilitySpec
module Generated {
/**
* An availability spec based on platform and version, for example `macOS 12` or `watchOS 14`
*/
class PlatformVersionAvailabilitySpec extends Synth::TPlatformVersionAvailabilitySpec,
AvailabilitySpec {
override string getAPrimaryQlClass() { result = "PlatformVersionAvailabilitySpec" }
/**
* Gets the platform of this platform version availability spec.
*/
string getPlatform() {
result =
Synth::convertPlatformVersionAvailabilitySpecToRaw(this)
.(Raw::PlatformVersionAvailabilitySpec)
.getPlatform()
}
/**
* Gets the version of this platform version availability spec.
*/
string getVersion() {
result =
Synth::convertPlatformVersionAvailabilitySpecToRaw(this)
.(Raw::PlatformVersionAvailabilitySpec)
.getVersion()
}
}
}

View File

@@ -63,6 +63,16 @@ module Raw {
class ErrorElement extends @error_element, Locatable { }
class AvailabilityInfo extends @availability_info, AstNode {
override string toString() { result = "AvailabilityInfo" }
predicate isUnavailable() { availability_info_is_unavailable(this) }
AvailabilitySpec getSpec(int index) { availability_info_specs(this, index, result) }
}
class AvailabilitySpec extends @availability_spec, AstNode { }
class UnspecifiedElement extends @unspecified_element, ErrorElement {
override string toString() { result = "UnspecifiedElement" }
@@ -75,6 +85,19 @@ module Raw {
string getError() { unspecified_elements(this, _, result) }
}
class OtherAvailabilitySpec extends @other_availability_spec, AvailabilitySpec {
override string toString() { result = "OtherAvailabilitySpec" }
}
class PlatformVersionAvailabilitySpec extends @platform_version_availability_spec,
AvailabilitySpec {
override string toString() { result = "PlatformVersionAvailabilitySpec" }
string getPlatform() { platform_version_availability_specs(this, result, _) }
string getVersion() { platform_version_availability_specs(this, _, result) }
}
class Decl extends @decl, AstNode {
ModuleDecl getModule() { decls(this, result) }
@@ -1129,6 +1152,8 @@ module Raw {
Pattern getPattern() { condition_element_patterns(this, result) }
Expr getInitializer() { condition_element_initializers(this, result) }
AvailabilityInfo getAvailability() { condition_element_availabilities(this, result) }
}
class Stmt extends @stmt, AstNode { }

View File

@@ -5,10 +5,15 @@ cached
module Synth {
cached
newtype TElement =
TAvailabilityInfo(Raw::AvailabilityInfo id) { constructAvailabilityInfo(id) } or
TComment(Raw::Comment id) { constructComment(id) } or
TDbFile(Raw::DbFile id) { constructDbFile(id) } or
TDbLocation(Raw::DbLocation id) { constructDbLocation(id) } or
TDiagnostics(Raw::Diagnostics id) { constructDiagnostics(id) } or
TOtherAvailabilitySpec(Raw::OtherAvailabilitySpec id) { constructOtherAvailabilitySpec(id) } or
TPlatformVersionAvailabilitySpec(Raw::PlatformVersionAvailabilitySpec id) {
constructPlatformVersionAvailabilitySpec(id)
} or
TUnknownFile() or
TUnknownLocation() or
TUnspecifiedElement(Raw::UnspecifiedElement id) { constructUnspecifiedElement(id) } or
@@ -304,8 +309,10 @@ module Synth {
TWeakStorageType(Raw::WeakStorageType id) { constructWeakStorageType(id) }
class TAstNode =
TCaseLabelItem or TConditionElement or TDecl or TExpr or TPattern or TStmt or TStmtCondition or
TTypeRepr;
TAvailabilityInfo or TAvailabilitySpec or TCaseLabelItem or TConditionElement or TDecl or
TExpr or TPattern or TStmt or TStmtCondition or TTypeRepr;
class TAvailabilitySpec = TOtherAvailabilitySpec or TPlatformVersionAvailabilitySpec;
class TCallable = TAbstractClosureExpr or TAbstractFunctionDecl;
@@ -464,6 +471,9 @@ module Synth {
class TUnarySyntaxSugarType = TArraySliceType or TOptionalType or TVariadicSequenceType;
cached
TAvailabilityInfo convertAvailabilityInfoFromRaw(Raw::Element e) { result = TAvailabilityInfo(e) }
cached
TComment convertCommentFromRaw(Raw::Element e) { result = TComment(e) }
@@ -476,6 +486,16 @@ module Synth {
cached
TDiagnostics convertDiagnosticsFromRaw(Raw::Element e) { result = TDiagnostics(e) }
cached
TOtherAvailabilitySpec convertOtherAvailabilitySpecFromRaw(Raw::Element e) {
result = TOtherAvailabilitySpec(e)
}
cached
TPlatformVersionAvailabilitySpec convertPlatformVersionAvailabilitySpecFromRaw(Raw::Element e) {
result = TPlatformVersionAvailabilitySpec(e)
}
cached
TUnknownFile convertUnknownFileFromRaw(Raw::Element e) { none() }
@@ -1351,6 +1371,10 @@ module Synth {
cached
TAstNode convertAstNodeFromRaw(Raw::Element e) {
result = convertAvailabilityInfoFromRaw(e)
or
result = convertAvailabilitySpecFromRaw(e)
or
result = convertCaseLabelItemFromRaw(e)
or
result = convertConditionElementFromRaw(e)
@@ -1368,6 +1392,13 @@ module Synth {
result = convertTypeReprFromRaw(e)
}
cached
TAvailabilitySpec convertAvailabilitySpecFromRaw(Raw::Element e) {
result = convertOtherAvailabilitySpecFromRaw(e)
or
result = convertPlatformVersionAvailabilitySpecFromRaw(e)
}
cached
TCallable convertCallableFromRaw(Raw::Element e) {
result = convertAbstractClosureExprFromRaw(e)
@@ -2100,6 +2131,9 @@ module Synth {
result = convertVariadicSequenceTypeFromRaw(e)
}
cached
Raw::Element convertAvailabilityInfoToRaw(TAvailabilityInfo e) { e = TAvailabilityInfo(result) }
cached
Raw::Element convertCommentToRaw(TComment e) { e = TComment(result) }
@@ -2112,6 +2146,16 @@ module Synth {
cached
Raw::Element convertDiagnosticsToRaw(TDiagnostics e) { e = TDiagnostics(result) }
cached
Raw::Element convertOtherAvailabilitySpecToRaw(TOtherAvailabilitySpec e) {
e = TOtherAvailabilitySpec(result)
}
cached
Raw::Element convertPlatformVersionAvailabilitySpecToRaw(TPlatformVersionAvailabilitySpec e) {
e = TPlatformVersionAvailabilitySpec(result)
}
cached
Raw::Element convertUnknownFileToRaw(TUnknownFile e) { none() }
@@ -2985,6 +3029,10 @@ module Synth {
cached
Raw::Element convertAstNodeToRaw(TAstNode e) {
result = convertAvailabilityInfoToRaw(e)
or
result = convertAvailabilitySpecToRaw(e)
or
result = convertCaseLabelItemToRaw(e)
or
result = convertConditionElementToRaw(e)
@@ -3002,6 +3050,13 @@ module Synth {
result = convertTypeReprToRaw(e)
}
cached
Raw::Element convertAvailabilitySpecToRaw(TAvailabilitySpec e) {
result = convertOtherAvailabilitySpecToRaw(e)
or
result = convertPlatformVersionAvailabilitySpecToRaw(e)
}
cached
Raw::Element convertCallableToRaw(TCallable e) {
result = convertAbstractClosureExprToRaw(e)

View File

@@ -1,8 +1,11 @@
// generated by codegen/codegen.py
import codeql.swift.elements.AvailabilityInfoConstructor
import codeql.swift.elements.CommentConstructor
import codeql.swift.elements.DbFileConstructor
import codeql.swift.elements.DbLocationConstructor
import codeql.swift.elements.DiagnosticsConstructor
import codeql.swift.elements.OtherAvailabilitySpecConstructor
import codeql.swift.elements.PlatformVersionAvailabilitySpecConstructor
import codeql.swift.elements.UnspecifiedElementConstructor
import codeql.swift.elements.decl.AccessorDeclConstructor
import codeql.swift.elements.decl.AssociatedTypeDeclConstructor

View File

@@ -2,6 +2,7 @@
private import codeql.swift.generated.Synth
private import codeql.swift.generated.Raw
import codeql.swift.elements.AstNode
import codeql.swift.elements.AvailabilityInfo
import codeql.swift.elements.expr.Expr
import codeql.swift.elements.pattern.Pattern
@@ -77,5 +78,28 @@ module Generated {
* Holds if `getInitializer()` exists.
*/
final predicate hasInitializer() { exists(getInitializer()) }
/**
* Gets the availability of this condition element, 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.
*/
AvailabilityInfo getImmediateAvailability() {
result =
Synth::convertAvailabilityInfoFromRaw(Synth::convertConditionElementToRaw(this)
.(Raw::ConditionElement)
.getAvailability())
}
/**
* Gets the availability of this condition element, if it exists.
*/
final AvailabilityInfo getAvailability() { result = getImmediateAvailability().resolve() }
/**
* Holds if `getAvailability()` exists.
*/
final predicate hasAvailability() { exists(getAvailability()) }
}
}

View File

@@ -101,7 +101,9 @@ locations(
);
@ast_node =
@case_label_item
@availability_info
| @availability_spec
| @case_label_item
| @condition_element
| @decl
| @expr
@@ -145,6 +147,27 @@ diagnostics(
| @unspecified_element
;
availability_infos(
unique int id: @availability_info
);
#keyset[id]
availability_info_is_unavailable(
int id: @availability_info ref
);
#keyset[id, index]
availability_info_specs(
int id: @availability_info ref,
int index: int ref,
int spec: @availability_spec_or_none ref
);
@availability_spec =
@other_availability_spec
| @platform_version_availability_spec
;
unspecified_elements(
unique int id: @unspecified_element,
string property: string ref,
@@ -163,6 +186,16 @@ unspecified_element_indices(
int index: int ref
);
other_availability_specs(
unique int id: @other_availability_spec
);
platform_version_availability_specs(
unique int id: @platform_version_availability_spec,
string platform: string ref,
string version: string ref
);
@decl =
@captured_decl
| @enum_case_decl
@@ -1682,6 +1715,12 @@ condition_element_initializers( //dir=stmt
int initializer: @expr_or_none ref
);
#keyset[id]
condition_element_availabilities( //dir=stmt
int id: @condition_element ref,
int availability: @availability_info_or_none ref
);
@stmt =
@brace_stmt
| @break_stmt
@@ -2383,6 +2422,16 @@ variadic_sequence_types( //dir=type
| @unspecified_element
;
@availability_info_or_none =
@availability_info
| @unspecified_element
;
@availability_spec_or_none =
@availability_spec
| @unspecified_element
;
@brace_stmt_or_none =
@brace_stmt
| @unspecified_element

View File

@@ -0,0 +1,2 @@
| test.swift:1:4:1:27 | #available | isUnavailable: | no | getNumberOfSpecs: | 2 |
| test.swift:5:4:5:45 | #unavailable | isUnavailable: | yes | getNumberOfSpecs: | 3 |

View File

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

View File

@@ -0,0 +1,5 @@
| test.swift:1:4:1:27 | #available | 0 | test.swift:1:15:1:21 | macOS 142 |
| test.swift:1:4:1:27 | #available | 1 | test.swift:1:26:1:26 | * |
| test.swift:5:4:5:45 | #unavailable | 0 | test.swift:5:17:5:21 | iOS 10 |
| test.swift:5:4:5:45 | #unavailable | 1 | test.swift:5:25:5:33 | watchOS 10 |
| test.swift:5:4:5:45 | #unavailable | 2 | test.swift:5:37:5:43 | macOS 10 |

View File

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

View File

@@ -0,0 +1,8 @@
if #available(macOS 142, *) {
print(1)
}
if #unavailable(iOS 10, watchOS 10, macOS 10) {
print(2)
}

View File

@@ -2,4 +2,6 @@
| IfStmt | statements.swift:3:8:3:13 | StmtCondition |
| IfStmt | statements.swift:65:4:65:19 | StmtCondition |
| IfStmt | statements.swift:67:4:67:20 | StmtCondition |
| IfStmt | statements.swift:87:4:87:27 | StmtCondition |
| IfStmt | statements.swift:91:4:91:25 | StmtCondition |
| WhileStmt | statements.swift:10:17:10:24 | StmtCondition |

View File

@@ -10,3 +10,5 @@
| statements.swift:65:1:66:1 | if ... then { ... } |
| statements.swift:67:1:68:1 | if ... then { ... } |
| statements.swift:71:1:72:1 | for ... in ... where ... { ... } |
| statements.swift:87:1:89:1 | if ... then { ... } |
| statements.swift:91:1:93:1 | if ... then { ... } |

View File

@@ -82,4 +82,14 @@ struct HasModifyAccessorDecl {
return 0
}
}
}
}
if #available(macOS 155, *) {
print(155)
}
if #unavailable(macOS 42) {
print(42)
}

View File

@@ -5894,3 +5894,42 @@ statements.swift:
# 74| Type = HasModifyAccessorDecl
# 74| getParam(0): [ParamDecl] x
# 74| Type = Int
# 87| [TopLevelCodeDecl] { ... }
# 87| getBody(): [BraceStmt] { ... }
# 87| getElement(0): [IfStmt] if ... then { ... }
# 87| getCondition(): [StmtCondition] StmtCondition
# 87| getElement(0): (no string representation)
# 87| getAvailability(): [AvailabilityInfo] #available
# 87| getSpec(0): [PlatformVersionAvailabilitySpec] macOS 155
# 87| getSpec(1): [OtherAvailabilitySpec] *
# 87| getThen(): [BraceStmt] { ... }
# 88| getElement(0): [CallExpr] call to print(_:separator:terminator:)
# 88| getFunction(): [DeclRefExpr] print(_:separator:terminator:)
# 88| getArgument(0): [Argument] : [...]
# 88| getExpr(): [VarargExpansionExpr] [...]
# 88| getSubExpr(): [ArrayExpr] [...]
# 88| getElement(0): [IntegerLiteralExpr] 155
# 88| getElement(0).getFullyConverted(): [ErasureExpr] (Any) ...
# 88| getArgument(1): [Argument] separator: default separator
# 88| getExpr(): [DefaultArgumentExpr] default separator
# 88| getArgument(2): [Argument] terminator: default terminator
# 88| getExpr(): [DefaultArgumentExpr] default terminator
# 91| [TopLevelCodeDecl] { ... }
# 91| getBody(): [BraceStmt] { ... }
# 91| getElement(0): [IfStmt] if ... then { ... }
# 91| getCondition(): [StmtCondition] StmtCondition
# 91| getElement(0): (no string representation)
# 91| getAvailability(): [AvailabilityInfo] #unavailable
# 91| getSpec(0): [PlatformVersionAvailabilitySpec] macOS 42
# 91| getThen(): [BraceStmt] { ... }
# 92| getElement(0): [CallExpr] call to print(_:separator:terminator:)
# 92| getFunction(): [DeclRefExpr] print(_:separator:terminator:)
# 92| getArgument(0): [Argument] : [...]
# 92| getExpr(): [VarargExpansionExpr] [...]
# 92| getSubExpr(): [ArrayExpr] [...]
# 92| getElement(0): [IntegerLiteralExpr] 42
# 92| getElement(0).getFullyConverted(): [ErasureExpr] (Any) ...
# 92| getArgument(1): [Argument] separator: default separator
# 92| getExpr(): [DefaultArgumentExpr] default separator
# 92| getArgument(2): [Argument] terminator: default terminator
# 92| getExpr(): [DefaultArgumentExpr] default terminator

View File

@@ -82,4 +82,14 @@ struct HasModifyAccessorDecl {
return 0
}
}
}
}
if #available(macOS 155, *) {
print(155)
}
if #unavailable(macOS 42) {
print(42)
}

View File

@@ -811,11 +811,47 @@ class CaseLabelItem(AstNode):
pattern: Pattern | child
guard: optional[Expr] | child
class AvailabilitySpec(AstNode):
pass
class PlatformVersionAvailabilitySpec(AvailabilitySpec):
"""
An availability spec based on platform and version, for example `macOS 12` or `watchOS 14`
"""
platform: string
version: string
class OtherAvailabilitySpec(AvailabilitySpec):
"""
A wildcard availability spec `*`
"""
pass
class AvailabilityInfo(AstNode):
"""
An availability condition of an `if`, `while`, or `guard` statements.
Examples:
```
if #available(iOS 12, *) {
// Runs on iOS 12 and above
} else {
// Runs only anything below iOS 12
}
if #unavailable(macOS 10.14, *) {
// Runs only on macOS 10 and below
}
```
"""
is_unavailable: predicate | doc("it is #unavailable as opposed to #available")
specs: list[AvailabilitySpec] | child
@group("stmt")
class ConditionElement(AstNode):
boolean: optional[Expr] | child
pattern: optional[Pattern] | child
initializer: optional[Expr] | child
availability: optional[AvailabilityInfo] | child
@group("stmt")
class StmtCondition(AstNode):