@@ -35,12 +35,21 @@ ArrayRef<CustomAttr *> ValueDecl::getRuntimeDiscoverableAttrs() const {
35
35
nullptr );
36
36
}
37
37
38
- Expr *
38
+ std::pair<BraceStmt *, Type>
39
39
ValueDecl::getRuntimeDiscoverableAttributeGenerator (CustomAttr *attr) const {
40
40
auto *mutableSelf = const_cast <ValueDecl *>(this );
41
- return evaluateOrDefault (
41
+ auto *body = evaluateOrDefault (
42
+ getASTContext ().evaluator ,
43
+ SynthesizeRuntimeMetadataAttrGeneratorBody{attr, mutableSelf}, nullptr );
44
+ if (!body)
45
+ return std::make_pair (nullptr , Type ());
46
+
47
+ auto *init = evaluateOrDefault (
42
48
getASTContext ().evaluator ,
43
49
SynthesizeRuntimeMetadataAttrGenerator{attr, mutableSelf}, nullptr );
50
+ assert (init);
51
+
52
+ return std::make_pair (body, init->getType ()->mapTypeOutOfContext ());
44
53
}
45
54
46
55
Expr *SynthesizeRuntimeMetadataAttrGenerator::evaluate (
@@ -180,3 +189,88 @@ Expr *SynthesizeRuntimeMetadataAttrGenerator::evaluate(
180
189
181
190
return result;
182
191
}
192
+
193
+ BraceStmt *SynthesizeRuntimeMetadataAttrGeneratorBody::evaluate (
194
+ Evaluator &evaluator, CustomAttr *attr, ValueDecl *attachedTo) const {
195
+ auto &ctx = attachedTo->getASTContext ();
196
+
197
+ Expr *init = evaluateOrDefault (
198
+ ctx.evaluator , SynthesizeRuntimeMetadataAttrGenerator{attr, attachedTo},
199
+ nullptr );
200
+ if (!init)
201
+ return nullptr ;
202
+
203
+ auto resultTy = init->getType ();
204
+
205
+ SmallVector<ASTNode, 4 > body;
206
+
207
+ auto declAvailability = attachedTo->getAvailabilityForLinkage ();
208
+ auto attrAvailability = attachedTo->getRuntimeDiscoverableAttrTypeDecl (attr)
209
+ ->getAvailabilityForLinkage ();
210
+ declAvailability.intersectWith (attrAvailability);
211
+
212
+ if (!declAvailability.isAlwaysAvailable ()) {
213
+
214
+ // if #available(...) {
215
+ // return <#initializer call#>
216
+ // }
217
+ // return nil
218
+
219
+ auto availableOn = declAvailability.getOSVersion ().getLowerEndpoint ();
220
+ auto *platformSpec = new (ctx) PlatformVersionConstraintAvailabilitySpec (
221
+ targetPlatform (ctx.LangOpts ), /* PlatformLoc=*/ SourceLoc (), availableOn,
222
+ availableOn, /* VersionSrcRange=*/ SourceRange ());
223
+
224
+ auto *wildcardSpec =
225
+ new (ctx) OtherPlatformAvailabilitySpec (/* StarLoc=*/ SourceLoc ());
226
+
227
+ StmtConditionElement platformCond (PoundAvailableInfo::create (
228
+ ctx, /* PoundLoc=*/ SourceLoc (),
229
+ /* LParenLoc=*/ SourceLoc (), {platformSpec, wildcardSpec},
230
+ /* RParenLoc=*/ SourceLoc (),
231
+ /* isUnavailability=*/ false ));
232
+
233
+ NullablePtr<Stmt> thenStmt;
234
+ {
235
+ SmallVector<ASTNode, 4 > thenBody;
236
+
237
+ thenBody.push_back (new (ctx) ReturnStmt (/* loc=*/ SourceLoc (), init,
238
+ /* isImplicit=*/ true ));
239
+
240
+ thenStmt = BraceStmt::create (ctx, /* lbloc=*/ SourceLoc (), thenBody,
241
+ /* rbloc=*/ SourceLoc (), /* implicit=*/ true );
242
+ }
243
+
244
+ NullablePtr<Stmt> elseStmt;
245
+ {
246
+ // return nil as Optional<<#attribute type#>>
247
+ auto *nil =
248
+ new (ctx) NilLiteralExpr (/* Loc=*/ SourceLoc (), /* implicit=*/ true );
249
+ nil->setType (resultTy);
250
+
251
+ auto *returnNil = new (ctx) ReturnStmt (/* loc=*/ SourceLoc (), nil,
252
+ /* isImplicit=*/ true );
253
+
254
+ elseStmt = BraceStmt::create (ctx, /* lbloc=*/ SourceLoc (), {returnNil},
255
+ /* rbloc=*/ SourceLoc (), /* implicit=*/ true );
256
+ }
257
+
258
+ auto *ifStmt = new (ctx)
259
+ IfStmt (LabeledStmtInfo (), /* ifLoc=*/ SourceLoc (),
260
+ ctx.AllocateCopy (ArrayRef<StmtConditionElement>(platformCond)),
261
+ thenStmt.get (),
262
+ /* ElseLoc=*/ SourceLoc (), elseStmt.get (), /* Implicit=*/ true );
263
+
264
+ body.push_back (ifStmt);
265
+ } else {
266
+ // just `return <#initializer value#>`
267
+ body.push_back (new (ctx) ReturnStmt (/* loc=*/ SourceLoc (), init,
268
+ /* isImplicit=*/ true ));
269
+ }
270
+
271
+ ASTNode braceStmt =
272
+ BraceStmt::create (ctx, /* lbloc=*/ attr->getLocation (), body,
273
+ /* rbloc=*/ attr->getLocation (), /* implicit=*/ true );
274
+
275
+ return cast<BraceStmt>(braceStmt.get <Stmt *>());
276
+ }
0 commit comments