|
25 | 25 | #include "TypeCheckType.h"
|
26 | 26 | #include "MiscDiagnostics.h"
|
27 | 27 | #include "swift/AST/AccessScope.h"
|
| 28 | +#include "swift/AST/ASTMangler.h" |
28 | 29 | #include "swift/AST/ASTPrinter.h"
|
29 | 30 | #include "swift/AST/ASTVisitor.h"
|
30 | 31 | #include "swift/AST/ASTWalker.h"
|
@@ -2417,6 +2418,53 @@ NamingPatternRequest::evaluate(Evaluator &evaluator, VarDecl *VD) const {
|
2417 | 2418 | return namingPattern;
|
2418 | 2419 | }
|
2419 | 2420 |
|
| 2421 | +namespace { |
| 2422 | + |
| 2423 | +// Utility class for deterministically ordering vtable entries for |
| 2424 | +// synthesized methods. |
| 2425 | +struct SortedFuncList { |
| 2426 | + using Entry = std::pair<std::string, AbstractFunctionDecl *>; |
| 2427 | + SmallVector<Entry, 2> elts; |
| 2428 | + bool sorted = false; |
| 2429 | + |
| 2430 | + void add(AbstractFunctionDecl *afd) { |
| 2431 | + Mangle::ASTMangler mangler; |
| 2432 | + std::string mangledName; |
| 2433 | + if (auto *cd = dyn_cast<ConstructorDecl>(afd)) |
| 2434 | + mangledName = mangler.mangleConstructorEntity(cd, /*allocator=*/false); |
| 2435 | + else if (auto *dd = dyn_cast<DestructorDecl>(afd)) |
| 2436 | + mangledName = mangler.mangleDestructorEntity(dd, /*deallocating=*/false); |
| 2437 | + else |
| 2438 | + mangledName = mangler.mangleEntity(afd); |
| 2439 | + |
| 2440 | + elts.push_back(std::make_pair(mangledName, afd)); |
| 2441 | + } |
| 2442 | + |
| 2443 | + bool empty() { return elts.empty(); } |
| 2444 | + |
| 2445 | + void sort() { |
| 2446 | + assert(!sorted); |
| 2447 | + sorted = true; |
| 2448 | + std::sort(elts.begin(), |
| 2449 | + elts.end(), |
| 2450 | + [](const Entry &lhs, const Entry &rhs) -> bool { |
| 2451 | + return lhs.first < rhs.first; |
| 2452 | + }); |
| 2453 | + } |
| 2454 | + |
| 2455 | + decltype(elts)::const_iterator begin() const { |
| 2456 | + assert(sorted); |
| 2457 | + return elts.begin(); |
| 2458 | + } |
| 2459 | + |
| 2460 | + decltype(elts)::const_iterator end() const { |
| 2461 | + assert(sorted); |
| 2462 | + return elts.end(); |
| 2463 | + } |
| 2464 | +}; |
| 2465 | + |
| 2466 | +} // end namespace |
| 2467 | + |
2420 | 2468 | ArrayRef<Decl *>
|
2421 | 2469 | EmittedMembersRequest::evaluate(Evaluator &evaluator,
|
2422 | 2470 | ClassDecl *CD) const {
|
@@ -2457,16 +2505,37 @@ EmittedMembersRequest::evaluate(Evaluator &evaluator,
|
2457 | 2505 | forceConformance(Context.getProtocol(KnownProtocolKind::Hashable));
|
2458 | 2506 | forceConformance(Context.getProtocol(KnownProtocolKind::Differentiable));
|
2459 | 2507 |
|
2460 |
| - // The projected storage wrapper ($foo) might have dynamically-dispatched |
2461 |
| - // accessors, so force them to be synthesized. |
2462 | 2508 | for (auto *member : CD->getMembers()) {
|
2463 |
| - if (auto *var = dyn_cast<VarDecl>(member)) |
| 2509 | + if (auto *var = dyn_cast<VarDecl>(member)) { |
| 2510 | + // The projected storage wrapper ($foo) might have dynamically-dispatched |
| 2511 | + // accessors, so force them to be synthesized. |
2464 | 2512 | if (var->hasAttachedPropertyWrapper())
|
2465 | 2513 | (void) var->getPropertyWrapperBackingProperty();
|
| 2514 | + } |
| 2515 | + } |
| 2516 | + |
| 2517 | + SortedFuncList synthesizedMembers; |
| 2518 | + |
| 2519 | + for (auto *member : CD->getMembers()) { |
| 2520 | + if (auto *afd = dyn_cast<AbstractFunctionDecl>(member)) { |
| 2521 | + // Add synthesized members to a side table and sort them by their mangled |
| 2522 | + // name, since they could have been added to the class in any order. |
| 2523 | + if (afd->isSynthesized()) { |
| 2524 | + synthesizedMembers.add(afd); |
| 2525 | + continue; |
| 2526 | + } |
| 2527 | + } |
| 2528 | + |
| 2529 | + result.push_back(member); |
| 2530 | + } |
| 2531 | + |
| 2532 | + if (!synthesizedMembers.empty()) { |
| 2533 | + synthesizedMembers.sort(); |
| 2534 | + |
| 2535 | + for (const auto &pair : synthesizedMembers) |
| 2536 | + result.push_back(pair.second); |
2466 | 2537 | }
|
2467 | 2538 |
|
2468 |
| - auto members = CD->getMembers(); |
2469 |
| - result.append(members.begin(), members.end()); |
2470 | 2539 | return Context.AllocateCopy(result);
|
2471 | 2540 | }
|
2472 | 2541 |
|
|
0 commit comments