@@ -2036,8 +2036,8 @@ void AttributeChecker::visitDiscardableResultAttr(DiscardableResultAttr *attr) {
2036
2036
2037
2037
// / Lookup the replaced decl in the replacments scope.
2038
2038
void lookupReplacedDecl (DeclName replacedDeclName,
2039
- DynamicReplacementAttr *attr,
2040
- AbstractFunctionDecl *replacement,
2039
+ const DynamicReplacementAttr *attr,
2040
+ const ValueDecl *replacement,
2041
2041
SmallVectorImpl<ValueDecl *> &results) {
2042
2042
auto *declCtxt = replacement->getDeclContext ();
2043
2043
@@ -2047,9 +2047,9 @@ void lookupReplacedDecl(DeclName replacedDeclName,
2047
2047
declCtxt = storage->getDeclContext ();
2048
2048
}
2049
2049
2050
+ auto *moduleScopeCtxt = declCtxt->getModuleScopeContext ();
2050
2051
if (isa<FileUnit>(declCtxt)) {
2051
- UnqualifiedLookup lookup (replacedDeclName,
2052
- replacement->getModuleScopeContext (), nullptr ,
2052
+ UnqualifiedLookup lookup (replacedDeclName, moduleScopeCtxt, nullptr ,
2053
2053
attr->getLocation ());
2054
2054
if (lookup.isSuccess ()) {
2055
2055
for (auto entry : lookup.Results ) {
@@ -2064,8 +2064,8 @@ void lookupReplacedDecl(DeclName replacedDeclName,
2064
2064
if (!typeCtx)
2065
2065
typeCtx = cast<ExtensionDecl>(declCtxt->getAsDecl ())->getExtendedNominal ();
2066
2066
2067
- replacement-> getModuleScopeContext ()-> lookupQualified (
2068
- {typeCtx}, replacedDeclName, NL_QualifiedDefault, results);
2067
+ moduleScopeCtxt-> lookupQualified ({typeCtx}, replacedDeclName,
2068
+ NL_QualifiedDefault, results);
2069
2069
}
2070
2070
2071
2071
// / Remove any argument labels from the interface type of the given value that
@@ -2183,51 +2183,107 @@ static FuncDecl *findReplacedAccessor(DeclName replacedVarName,
2183
2183
2184
2184
static AbstractFunctionDecl *
2185
2185
findReplacedFunction (DeclName replacedFunctionName,
2186
- AbstractFunctionDecl *replacement,
2187
- DynamicReplacementAttr *attr, TypeChecker & TC) {
2186
+ const AbstractFunctionDecl *replacement,
2187
+ DynamicReplacementAttr *attr, TypeChecker * TC) {
2188
2188
2189
+ // Note: we might pass a constant attribute when typechecker is nullptr.
2190
+ // Any modification to attr must be guarded by a null check on TC.
2191
+ //
2189
2192
SmallVector<ValueDecl *, 4 > results;
2190
2193
lookupReplacedDecl (replacedFunctionName, attr, replacement, results);
2191
2194
2192
2195
for (auto *result : results) {
2193
2196
// Check for static/instance mismatch.
2194
2197
if (result->isStatic () != replacement->isStatic ())
2195
2198
continue ;
2196
-
2197
- TC. validateDecl (result);
2199
+ if (TC)
2200
+ TC-> validateDecl (result);
2198
2201
if (result->getInterfaceType ()->getCanonicalType ()->matches (
2199
2202
replacement->getInterfaceType ()->getCanonicalType (),
2200
2203
TypeMatchFlags::AllowABICompatible)) {
2201
2204
if (!result->isDynamic ()) {
2202
- TC.diagnose (attr->getLocation (),
2203
- diag::dynamic_replacement_function_not_dynamic,
2204
- replacedFunctionName);
2205
- attr->setInvalid ();
2205
+ if (TC) {
2206
+ TC->diagnose (attr->getLocation (),
2207
+ diag::dynamic_replacement_function_not_dynamic,
2208
+ replacedFunctionName);
2209
+ attr->setInvalid ();
2210
+ }
2206
2211
return nullptr ;
2207
2212
}
2208
2213
return cast<AbstractFunctionDecl>(result);
2209
2214
}
2210
2215
}
2211
- if (results.empty ())
2212
- TC.diagnose (attr->getLocation (),
2213
- diag::dynamic_replacement_function_not_found,
2214
- attr->getReplacedFunctionName ());
2215
- else {
2216
- TC.diagnose (attr->getLocation (),
2217
- diag::dynamic_replacement_function_of_type_not_found,
2218
- attr->getReplacedFunctionName (),
2219
- replacement->getInterfaceType ()->getCanonicalType ());
2216
+
2217
+ if (!TC)
2218
+ return nullptr ;
2219
+
2220
+ if (results.empty ()) {
2221
+ TC->diagnose (attr->getLocation (),
2222
+ diag::dynamic_replacement_function_not_found,
2223
+ attr->getReplacedFunctionName ());
2224
+ } else {
2225
+ TC->diagnose (attr->getLocation (),
2226
+ diag::dynamic_replacement_function_of_type_not_found,
2227
+ attr->getReplacedFunctionName (),
2228
+ replacement->getInterfaceType ()->getCanonicalType ());
2220
2229
2221
2230
for (auto *result : results) {
2222
- TC.diagnose (SourceLoc (), diag::dynamic_replacement_found_function_of_type,
2223
- attr->getReplacedFunctionName (),
2224
- result->getInterfaceType ()->getCanonicalType ());
2231
+ TC->diagnose (SourceLoc (),
2232
+ diag::dynamic_replacement_found_function_of_type,
2233
+ attr->getReplacedFunctionName (),
2234
+ result->getInterfaceType ()->getCanonicalType ());
2225
2235
}
2226
2236
}
2227
2237
attr->setInvalid ();
2228
2238
return nullptr ;
2229
2239
}
2230
2240
2241
+ static AbstractStorageDecl *
2242
+ findReplacedStorageDecl (DeclName replacedFunctionName,
2243
+ const AbstractStorageDecl *replacement,
2244
+ const DynamicReplacementAttr *attr) {
2245
+
2246
+ SmallVector<ValueDecl *, 4 > results;
2247
+ lookupReplacedDecl (replacedFunctionName, attr, replacement, results);
2248
+
2249
+ for (auto *result : results) {
2250
+ // Check for static/instance mismatch.
2251
+ if (result->isStatic () != replacement->isStatic ())
2252
+ continue ;
2253
+ if (result->getInterfaceType ()->getCanonicalType ()->matches (
2254
+ replacement->getInterfaceType ()->getCanonicalType (),
2255
+ TypeMatchFlags::AllowABICompatible)) {
2256
+ if (!result->isDynamic ()) {
2257
+ return nullptr ;
2258
+ }
2259
+ return cast<AbstractStorageDecl>(result);
2260
+ }
2261
+ }
2262
+ return nullptr ;
2263
+ }
2264
+
2265
+ ValueDecl *TypeChecker::findReplacedDynamicFunction (const ValueDecl *vd) {
2266
+ assert (isa<AbstractFunctionDecl>(vd) || isa<AbstractStorageDecl>(vd));
2267
+ if (isa<AccessorDecl>(vd))
2268
+ return nullptr ;
2269
+
2270
+ auto *attr = vd->getAttrs ().getAttribute <DynamicReplacementAttr>();
2271
+ if (!attr)
2272
+ return nullptr ;
2273
+
2274
+ auto *afd = dyn_cast<AbstractFunctionDecl>(vd);
2275
+ if (afd) {
2276
+ // When we pass nullptr as the type checker argument attr is truely const.
2277
+ return findReplacedFunction (attr->getReplacedFunctionName (), afd,
2278
+ const_cast <DynamicReplacementAttr *>(attr),
2279
+ nullptr );
2280
+ }
2281
+ auto *storageDecl = dyn_cast<AbstractStorageDecl>(vd);
2282
+ if (!storageDecl)
2283
+ return nullptr ;
2284
+ return findReplacedStorageDecl (attr->getReplacedFunctionName (), storageDecl, attr);
2285
+ }
2286
+
2231
2287
void TypeChecker::checkDynamicReplacementAttribute (ValueDecl *D) {
2232
2288
assert (isa<AbstractFunctionDecl>(D) || isa<AbstractStorageDecl>(D));
2233
2289
@@ -2276,7 +2332,7 @@ void TypeChecker::checkDynamicReplacementAttribute(ValueDecl *D) {
2276
2332
// Otherwise, find the matching function.
2277
2333
auto *fun = cast<AbstractFunctionDecl>(D);
2278
2334
if (auto *orig = findReplacedFunction (attr->getReplacedFunctionName (), fun,
2279
- attr, * this )) {
2335
+ attr, this )) {
2280
2336
origs.push_back (orig);
2281
2337
replacements.push_back (fun);
2282
2338
} else
@@ -2288,14 +2344,46 @@ void TypeChecker::checkDynamicReplacementAttribute(ValueDecl *D) {
2288
2344
if (auto *attr = replacements[index]
2289
2345
->getAttrs ()
2290
2346
.getAttribute <DynamicReplacementAttr>()) {
2291
- attr->setReplacedFunction (origs[index]);
2347
+ auto *replacedFun = origs[index];
2348
+ auto *replacement = replacements[index];
2349
+ if (replacedFun->isObjC () && !replacement->isObjC ()) {
2350
+ diagnose (attr->getLocation (),
2351
+ diag::dynamic_replacement_replacement_not_objc_dynamic,
2352
+ attr->getReplacedFunctionName ());
2353
+ attr->setInvalid ();
2354
+ return ;
2355
+ }
2356
+ if (!replacedFun->isObjC () && replacement->isObjC ()) {
2357
+ diagnose (attr->getLocation (),
2358
+ diag::dynamic_replacement_replaced_not_objc_dynamic,
2359
+ attr->getReplacedFunctionName ());
2360
+ attr->setInvalid ();
2361
+ return ;
2362
+ }
2363
+ attr->setReplacedFunction (replacedFun);
2292
2364
continue ;
2293
2365
}
2294
2366
auto *newAttr = DynamicReplacementAttr::create (
2295
2367
D->getASTContext (), attr->getReplacedFunctionName (), origs[index]);
2296
2368
DeclAttributes &attrs = replacements[index]->getAttrs ();
2297
2369
attrs.add (newAttr);
2298
2370
}
2371
+ if (auto *CD = dyn_cast<ConstructorDecl>(D)) {
2372
+ auto *attr = CD->getAttrs ().getAttribute <DynamicReplacementAttr>();
2373
+ auto replacedIsConvenienceInit =
2374
+ cast<ConstructorDecl>(attr->getReplacedFunction ())->isConvenienceInit ();
2375
+ if (replacedIsConvenienceInit &&!CD->isConvenienceInit ()) {
2376
+ diagnose (attr->getLocation (),
2377
+ diag::dynamic_replacement_replaced_constructor_is_convenience,
2378
+ attr->getReplacedFunctionName ());
2379
+ } else if (!replacedIsConvenienceInit && CD->isConvenienceInit ()) {
2380
+ diagnose (
2381
+ attr->getLocation (),
2382
+ diag::dynamic_replacement_replaced_constructor_is_not_convenience,
2383
+ attr->getReplacedFunctionName ());
2384
+ }
2385
+ }
2386
+
2299
2387
2300
2388
// Remove the attribute on the abstract storage (we have moved it to the
2301
2389
// accessor decl).
0 commit comments