@@ -88,8 +88,6 @@ llvm::StringRef swift::getProtocolName(KnownProtocolKind kind) {
88
88
}
89
89
90
90
namespace {
91
- typedef std::tuple<ClassDecl *, ObjCSelector, bool > ObjCMethodConflict;
92
-
93
91
enum class SearchPathKind : uint8_t {
94
92
Import = 1 << 0 ,
95
93
Framework = 1 << 1
@@ -375,9 +373,6 @@ FOR_KNOWN_FOUNDATION_TYPES(CACHE_FOUNDATION_DECL)
375
373
llvm::FoldingSet<DeclName::CompoundDeclName> CompoundNames;
376
374
llvm::DenseMap<UUID, OpenedArchetypeType *> OpenedExistentialArchetypes;
377
375
378
- // / List of Objective-C member conflicts we have found during type checking.
379
- std::vector<ObjCMethodConflict> ObjCMethodConflicts;
380
-
381
376
// / A cache of information about whether particular nominal types
382
377
// / are representable in a foreign language.
383
378
llvm::DenseMap<NominalTypeDecl *, ForeignRepresentationInfo>
@@ -2070,40 +2065,6 @@ namespace {
2070
2065
return lhs->getFullName () < rhs->getFullName ();
2071
2066
}
2072
2067
};
2073
-
2074
- // / Produce a deterministic ordering of the given declarations with
2075
- // / a bias that favors declarations in the given source file and
2076
- // / members of a class.
2077
- class OrderDeclarationsWithSourceFileAndClassBias {
2078
- SourceManager &SrcMgr;
2079
- SourceFile &SF;
2080
-
2081
- public:
2082
- OrderDeclarationsWithSourceFileAndClassBias (SourceManager &srcMgr,
2083
- SourceFile &sf)
2084
- : SrcMgr(srcMgr), SF(sf) { }
2085
-
2086
- bool operator ()(ValueDecl *lhs, ValueDecl *rhs) const {
2087
- // Check whether the declarations are in a class.
2088
- bool lhsInClass = isa<ClassDecl>(lhs->getDeclContext ());
2089
- bool rhsInClass = isa<ClassDecl>(rhs->getDeclContext ());
2090
- if (lhsInClass != rhsInClass)
2091
- return lhsInClass;
2092
-
2093
- // If the two declarations are in different source files, and one of those
2094
- // source files is the source file we're biasing toward, prefer that
2095
- // declaration.
2096
- SourceFile *lhsSF = lhs->getDeclContext ()->getParentSourceFile ();
2097
- SourceFile *rhsSF = rhs->getDeclContext ()->getParentSourceFile ();
2098
- if (lhsSF != rhsSF) {
2099
- if (lhsSF == &SF) return true ;
2100
- if (rhsSF == &SF) return false ;
2101
- }
2102
-
2103
- // Fall back to the normal deterministic ordering.
2104
- return OrderDeclarations (SrcMgr)(lhs, rhs);
2105
- }
2106
- };
2107
2068
} // end anonymous namespace
2108
2069
2109
2070
// / Compute the information used to describe an Objective-C redeclaration.
@@ -2478,16 +2439,9 @@ bool ASTContext::diagnoseUnintendedObjCMethodOverrides(SourceFile &sf) {
2478
2439
return diagnosedAny;
2479
2440
}
2480
2441
2481
- void ASTContext::recordObjCMethodConflict (ClassDecl *classDecl,
2482
- ObjCSelector selector,
2483
- bool isInstance) {
2484
- getImpl ().ObjCMethodConflicts .push_back (std::make_tuple (classDecl, selector,
2485
- isInstance));
2486
- }
2487
-
2488
2442
// / Retrieve the source file for the given Objective-C member conflict.
2489
2443
static MutableArrayRef<AbstractFunctionDecl *>
2490
- getObjCMethodConflictDecls (const ObjCMethodConflict &conflict) {
2444
+ getObjCMethodConflictDecls (const SourceFile:: ObjCMethodConflict &conflict) {
2491
2445
ClassDecl *classDecl = std::get<0 >(conflict);
2492
2446
ObjCSelector selector = std::get<1 >(conflict);
2493
2447
bool isInstanceMethod = std::get<2 >(conflict);
@@ -2526,80 +2480,27 @@ static void removeValidObjCConflictingMethods(
2526
2480
methods = methods.slice (0 , newEnd - methods.begin ());
2527
2481
}
2528
2482
2529
- // / Determine whether we should associate a conflict among the given
2530
- // / set of methods with the specified source file.
2531
- static bool shouldAssociateConflictWithSourceFile (
2532
- SourceFile &sf,
2533
- ArrayRef<AbstractFunctionDecl *> methods) {
2534
- bool anyInSourceFile = false ;
2535
- bool anyInOtherSourceFile = false ;
2536
- bool anyClassMethodsInSourceFile = false ;
2537
- for (auto method : methods) {
2538
- // Skip methods in the class itself; we want to only diagnose
2539
- // those if there is a conflict within that file.
2540
- if (isa<ClassDecl>(method->getDeclContext ())) {
2541
- if (method->getParentSourceFile () == &sf)
2542
- anyClassMethodsInSourceFile = true ;
2543
- continue ;
2544
- }
2545
-
2546
- if (method->getParentSourceFile () == &sf)
2547
- anyInSourceFile = true ;
2548
- else
2549
- anyInOtherSourceFile = true ;
2550
- }
2551
-
2552
- return anyInSourceFile ||
2553
- (!anyInOtherSourceFile && anyClassMethodsInSourceFile);
2554
- }
2555
-
2556
2483
bool ASTContext::diagnoseObjCMethodConflicts (SourceFile &sf) {
2557
2484
// If there were no conflicts, we're done.
2558
- if (getImpl () .ObjCMethodConflicts .empty ())
2485
+ if (sf .ObjCMethodConflicts .empty ())
2559
2486
return false ;
2560
2487
2561
- // Partition the set of conflicts to put the conflicts that involve
2562
- // this source file at the end.
2563
- auto firstLocalConflict
2564
- = std::partition (getImpl ().ObjCMethodConflicts .begin (),
2565
- getImpl ().ObjCMethodConflicts .end (),
2566
- [&](const ObjCMethodConflict &conflict) -> bool {
2567
- auto decls = getObjCMethodConflictDecls (conflict);
2568
- if (shouldAssociateConflictWithSourceFile (sf, decls)) {
2569
- // It's in this source file. Sort the conflict
2570
- // declarations. We'll use this later.
2571
- std::sort (
2572
- decls.begin (), decls.end (),
2573
- OrderDeclarationsWithSourceFileAndClassBias (
2574
- SourceMgr, sf));
2575
-
2576
- return false ;
2577
- }
2578
-
2579
- return true ;
2580
- });
2581
-
2582
- // If there were no local conflicts, we're done.
2583
- unsigned numLocalConflicts
2584
- = getImpl ().ObjCMethodConflicts .end () - firstLocalConflict;
2585
- if (numLocalConflicts == 0 )
2586
- return false ;
2488
+ OrderDeclarations ordering (SourceMgr);
2587
2489
2588
2490
// Sort the set of conflicts so we get a deterministic order for
2589
2491
// diagnostics. We use the first conflicting declaration in each set to
2590
2492
// perform the sort.
2591
- MutableArrayRef<ObjCMethodConflict> localConflicts (&*firstLocalConflict,
2592
- numLocalConflicts);
2493
+ auto localConflicts = sf.ObjCMethodConflicts ;
2593
2494
std::sort (localConflicts.begin (), localConflicts.end (),
2594
- [&](const ObjCMethodConflict &lhs, const ObjCMethodConflict &rhs) {
2595
- OrderDeclarations ordering (SourceMgr);
2495
+ [&](const SourceFile:: ObjCMethodConflict &lhs,
2496
+ const SourceFile::ObjCMethodConflict &rhs) {
2596
2497
return ordering (getObjCMethodConflictDecls (lhs)[1 ],
2597
2498
getObjCMethodConflictDecls (rhs)[1 ]);
2598
2499
});
2599
2500
2600
2501
// Diagnose each conflict.
2601
2502
bool anyConflicts = false ;
2602
- for (const ObjCMethodConflict &conflict : localConflicts) {
2503
+ for (const auto &conflict : localConflicts) {
2603
2504
ObjCSelector selector = std::get<1 >(conflict);
2604
2505
2605
2506
auto methods = getObjCMethodConflictDecls (conflict);
@@ -2612,13 +2513,22 @@ bool ASTContext::diagnoseObjCMethodConflicts(SourceFile &sf) {
2612
2513
// Diagnose the conflict.
2613
2514
anyConflicts = true ;
2614
2515
2615
- // If the first method has a valid source location but the first conflicting
2616
- // declaration does not, swap them so the primary diagnostic has a useful
2617
- // source location.
2618
- if (methods[1 ]->getLoc ().isInvalid () && methods[0 ]->getLoc ().isValid ()) {
2516
+ // If the first method is in an extension and the second is not, swap them
2517
+ // so the primary diagnostic is on the extension method.
2518
+ if (isa<ExtensionDecl>(methods[0 ]->getDeclContext ()) &&
2519
+ !isa<ExtensionDecl>(methods[1 ]->getDeclContext ())) {
2520
+ std::swap (methods[0 ], methods[1 ]);
2521
+
2522
+ // Within a source file, use our canonical ordering.
2523
+ } else if (methods[0 ]->getParentSourceFile () ==
2524
+ methods[1 ]->getParentSourceFile () &&
2525
+ !ordering (methods[0 ], methods[1 ])) {
2619
2526
std::swap (methods[0 ], methods[1 ]);
2620
2527
}
2621
2528
2529
+ // Otherwise, fall back to the order in which the declarations were type
2530
+ // checked.
2531
+
2622
2532
auto originalMethod = methods.front ();
2623
2533
auto conflictingMethods = methods.slice (1 );
2624
2534
@@ -2649,10 +2559,6 @@ bool ASTContext::diagnoseObjCMethodConflicts(SourceFile &sf) {
2649
2559
}
2650
2560
}
2651
2561
2652
- // Erase the local conflicts from the list of conflicts.
2653
- getImpl ().ObjCMethodConflicts .erase (firstLocalConflict,
2654
- getImpl ().ObjCMethodConflicts .end ());
2655
-
2656
2562
return anyConflicts;
2657
2563
}
2658
2564
@@ -2667,15 +2573,15 @@ static SourceLoc getDeclContextLoc(DeclContext *dc) {
2667
2573
2668
2574
bool ASTContext::diagnoseObjCUnsatisfiedOptReqConflicts (SourceFile &sf) {
2669
2575
// If there are no unsatisfied, optional @objc requirements, we're done.
2670
- if (sf-> ObjCUnsatisfiedOptReqs .empty ())
2576
+ if (sf. ObjCUnsatisfiedOptReqs .empty ())
2671
2577
return false ;
2672
2578
2673
2579
// Sort the set of local unsatisfied requirements, so we get a
2674
2580
// deterministic order for diagnostics.
2675
- auto &localReqs = sf-> ObjCUnsatisfiedOptReqs ;
2581
+ auto &localReqs = sf. ObjCUnsatisfiedOptReqs ;
2676
2582
std::sort (localReqs.begin (), localReqs.end (),
2677
- [&](const ObjCUnsatisfiedOptReq &lhs,
2678
- const ObjCUnsatisfiedOptReq &rhs) -> bool {
2583
+ [&](const SourceFile:: ObjCUnsatisfiedOptReq &lhs,
2584
+ const SourceFile:: ObjCUnsatisfiedOptReq &rhs) -> bool {
2679
2585
return SourceMgr.isBeforeInBuffer (getDeclContextLoc (lhs.first ),
2680
2586
getDeclContextLoc (rhs.first ));
2681
2587
});
0 commit comments