@@ -1977,8 +1977,8 @@ void AttributeChecker::visitDiscardableResultAttr(DiscardableResultAttr *attr) {
1977
1977
1978
1978
// / Lookup the replaced decl in the replacments scope.
1979
1979
void lookupReplacedDecl (DeclName replacedDeclName,
1980
- DynamicReplacementAttr *attr,
1981
- AbstractFunctionDecl *replacement,
1980
+ const DynamicReplacementAttr *attr,
1981
+ const ValueDecl *replacement,
1982
1982
SmallVectorImpl<ValueDecl *> &results) {
1983
1983
auto *declCtxt = replacement->getDeclContext ();
1984
1984
@@ -1988,9 +1988,9 @@ void lookupReplacedDecl(DeclName replacedDeclName,
1988
1988
declCtxt = storage->getDeclContext ();
1989
1989
}
1990
1990
1991
+ auto *moduleScopeCtxt = declCtxt->getModuleScopeContext ();
1991
1992
if (isa<FileUnit>(declCtxt)) {
1992
- UnqualifiedLookup lookup (replacedDeclName,
1993
- replacement->getModuleScopeContext (), nullptr ,
1993
+ UnqualifiedLookup lookup (replacedDeclName, moduleScopeCtxt, nullptr ,
1994
1994
attr->getLocation ());
1995
1995
if (lookup.isSuccess ()) {
1996
1996
for (auto entry : lookup.Results ) {
@@ -2005,8 +2005,8 @@ void lookupReplacedDecl(DeclName replacedDeclName,
2005
2005
if (!typeCtx)
2006
2006
typeCtx = cast<ExtensionDecl>(declCtxt->getAsDecl ())->getExtendedNominal ();
2007
2007
2008
- replacement-> getModuleScopeContext ()-> lookupQualified (
2009
- {typeCtx}, replacedDeclName, NL_QualifiedDefault, results);
2008
+ moduleScopeCtxt-> lookupQualified ({typeCtx}, replacedDeclName,
2009
+ NL_QualifiedDefault, results);
2010
2010
}
2011
2011
2012
2012
// / Remove any argument labels from the interface type of the given value that
@@ -2124,51 +2124,107 @@ static FuncDecl *findReplacedAccessor(DeclName replacedVarName,
2124
2124
2125
2125
static AbstractFunctionDecl *
2126
2126
findReplacedFunction (DeclName replacedFunctionName,
2127
- AbstractFunctionDecl *replacement,
2128
- DynamicReplacementAttr *attr, TypeChecker & TC) {
2127
+ const AbstractFunctionDecl *replacement,
2128
+ DynamicReplacementAttr *attr, TypeChecker * TC) {
2129
2129
2130
+ // Note: we might pass a constant attribute when typechecker is nullptr.
2131
+ // Any modification to attr must be guarded by a null check on TC.
2132
+ //
2130
2133
SmallVector<ValueDecl *, 4 > results;
2131
2134
lookupReplacedDecl (replacedFunctionName, attr, replacement, results);
2132
2135
2133
2136
for (auto *result : results) {
2134
2137
// Check for static/instance mismatch.
2135
2138
if (result->isStatic () != replacement->isStatic ())
2136
2139
continue ;
2137
-
2138
- TC. validateDecl (result);
2140
+ if (TC)
2141
+ TC-> validateDecl (result);
2139
2142
if (result->getInterfaceType ()->getCanonicalType ()->matches (
2140
2143
replacement->getInterfaceType ()->getCanonicalType (),
2141
2144
TypeMatchFlags::AllowABICompatible)) {
2142
2145
if (!result->isDynamic ()) {
2143
- TC.diagnose (attr->getLocation (),
2144
- diag::dynamic_replacement_function_not_dynamic,
2145
- replacedFunctionName);
2146
- attr->setInvalid ();
2146
+ if (TC) {
2147
+ TC->diagnose (attr->getLocation (),
2148
+ diag::dynamic_replacement_function_not_dynamic,
2149
+ replacedFunctionName);
2150
+ attr->setInvalid ();
2151
+ }
2147
2152
return nullptr ;
2148
2153
}
2149
2154
return cast<AbstractFunctionDecl>(result);
2150
2155
}
2151
2156
}
2152
- if (results.empty ())
2153
- TC.diagnose (attr->getLocation (),
2154
- diag::dynamic_replacement_function_not_found,
2155
- attr->getReplacedFunctionName ());
2156
- else {
2157
- TC.diagnose (attr->getLocation (),
2158
- diag::dynamic_replacement_function_of_type_not_found,
2159
- attr->getReplacedFunctionName (),
2160
- replacement->getInterfaceType ()->getCanonicalType ());
2157
+
2158
+ if (!TC)
2159
+ return nullptr ;
2160
+
2161
+ if (results.empty ()) {
2162
+ TC->diagnose (attr->getLocation (),
2163
+ diag::dynamic_replacement_function_not_found,
2164
+ attr->getReplacedFunctionName ());
2165
+ } else {
2166
+ TC->diagnose (attr->getLocation (),
2167
+ diag::dynamic_replacement_function_of_type_not_found,
2168
+ attr->getReplacedFunctionName (),
2169
+ replacement->getInterfaceType ()->getCanonicalType ());
2161
2170
2162
2171
for (auto *result : results) {
2163
- TC.diagnose (SourceLoc (), diag::dynamic_replacement_found_function_of_type,
2164
- attr->getReplacedFunctionName (),
2165
- result->getInterfaceType ()->getCanonicalType ());
2172
+ TC->diagnose (SourceLoc (),
2173
+ diag::dynamic_replacement_found_function_of_type,
2174
+ attr->getReplacedFunctionName (),
2175
+ result->getInterfaceType ()->getCanonicalType ());
2166
2176
}
2167
2177
}
2168
2178
attr->setInvalid ();
2169
2179
return nullptr ;
2170
2180
}
2171
2181
2182
+ static AbstractStorageDecl *
2183
+ findReplacedStorageDecl (DeclName replacedFunctionName,
2184
+ const AbstractStorageDecl *replacement,
2185
+ const DynamicReplacementAttr *attr) {
2186
+
2187
+ SmallVector<ValueDecl *, 4 > results;
2188
+ lookupReplacedDecl (replacedFunctionName, attr, replacement, results);
2189
+
2190
+ for (auto *result : results) {
2191
+ // Check for static/instance mismatch.
2192
+ if (result->isStatic () != replacement->isStatic ())
2193
+ continue ;
2194
+ if (result->getInterfaceType ()->getCanonicalType ()->matches (
2195
+ replacement->getInterfaceType ()->getCanonicalType (),
2196
+ TypeMatchFlags::AllowABICompatible)) {
2197
+ if (!result->isDynamic ()) {
2198
+ return nullptr ;
2199
+ }
2200
+ return cast<AbstractStorageDecl>(result);
2201
+ }
2202
+ }
2203
+ return nullptr ;
2204
+ }
2205
+
2206
+ ValueDecl *TypeChecker::findReplacedDynamicFunction (const ValueDecl *vd) {
2207
+ assert (isa<AbstractFunctionDecl>(vd) || isa<AbstractStorageDecl>(vd));
2208
+ if (isa<AccessorDecl>(vd))
2209
+ return nullptr ;
2210
+
2211
+ auto *attr = vd->getAttrs ().getAttribute <DynamicReplacementAttr>();
2212
+ if (!attr)
2213
+ return nullptr ;
2214
+
2215
+ auto *afd = dyn_cast<AbstractFunctionDecl>(vd);
2216
+ if (afd) {
2217
+ // When we pass nullptr as the type checker argument attr is truely const.
2218
+ return findReplacedFunction (attr->getReplacedFunctionName (), afd,
2219
+ const_cast <DynamicReplacementAttr *>(attr),
2220
+ nullptr );
2221
+ }
2222
+ auto *storageDecl = dyn_cast<AbstractStorageDecl>(vd);
2223
+ if (!storageDecl)
2224
+ return nullptr ;
2225
+ return findReplacedStorageDecl (attr->getReplacedFunctionName (), storageDecl, attr);
2226
+ }
2227
+
2172
2228
void TypeChecker::checkDynamicReplacementAttribute (ValueDecl *D) {
2173
2229
assert (isa<AbstractFunctionDecl>(D) || isa<AbstractStorageDecl>(D));
2174
2230
@@ -2217,7 +2273,7 @@ void TypeChecker::checkDynamicReplacementAttribute(ValueDecl *D) {
2217
2273
// Otherwise, find the matching function.
2218
2274
auto *fun = cast<AbstractFunctionDecl>(D);
2219
2275
if (auto *orig = findReplacedFunction (attr->getReplacedFunctionName (), fun,
2220
- attr, * this )) {
2276
+ attr, this )) {
2221
2277
origs.push_back (orig);
2222
2278
replacements.push_back (fun);
2223
2279
} else
0 commit comments