Skip to content

Commit 6de808e

Browse files
committed
[NFC] Make ObjCMethodConflicts a set
This allows us to stop using `vec.size() == 1` to prevent duplicate conflicts from being diagnosed, which will become untenable in the next commit.
1 parent a8ecfc9 commit 6de808e

File tree

3 files changed

+49
-19
lines changed

3 files changed

+49
-19
lines changed

include/swift/AST/SourceFile.h

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "swift/AST/Import.h"
1818
#include "swift/AST/SynthesizedFileUnit.h"
1919
#include "swift/Basic/Debug.h"
20+
#include "llvm/ADT/Hashing.h"
2021
#include "llvm/ADT/SetVector.h"
2122
#include "llvm/ADT/SmallPtrSet.h"
2223

@@ -243,11 +244,20 @@ class SourceFile final : public FileUnit {
243244
std::vector<ObjCUnsatisfiedOptReq> ObjCUnsatisfiedOptReqs;
244245

245246
/// A selector that is used by two different declarations in the same class.
246-
/// Fields: typeDecl, selector, isInstanceMethod.
247-
using ObjCMethodConflict = std::tuple<NominalTypeDecl *, ObjCSelector, bool>;
247+
struct ObjCMethodConflict {
248+
NominalTypeDecl *typeDecl;
249+
ObjCSelector selector;
250+
bool isInstanceMethod;
251+
252+
ObjCMethodConflict(NominalTypeDecl *typeDecl, ObjCSelector selector,
253+
bool isInstanceMethod)
254+
: typeDecl(typeDecl), selector(selector),
255+
isInstanceMethod(isInstanceMethod)
256+
{}
257+
};
248258

249259
/// List of Objective-C member conflicts we have found during type checking.
250-
std::vector<ObjCMethodConflict> ObjCMethodConflicts;
260+
llvm::SetVector<ObjCMethodConflict> ObjCMethodConflicts;
251261

252262
/// List of attributes added by access notes, used to emit remarks for valid
253263
/// ones.
@@ -636,4 +646,30 @@ inline void simple_display(llvm::raw_ostream &out, const SourceFile *SF) {
636646
}
637647
} // end namespace swift
638648

649+
namespace llvm {
650+
651+
template<>
652+
struct DenseMapInfo<swift::SourceFile::ObjCMethodConflict> {
653+
using ObjCMethodConflict = swift::SourceFile::ObjCMethodConflict;
654+
655+
static inline ObjCMethodConflict getEmptyKey() {
656+
return ObjCMethodConflict(nullptr, {}, false);
657+
}
658+
static inline ObjCMethodConflict getTombstoneKey() {
659+
return ObjCMethodConflict(nullptr, {}, true);
660+
}
661+
static inline unsigned getHashValue(ObjCMethodConflict a) {
662+
return hash_combine(hash_value(a.typeDecl),
663+
DenseMapInfo<swift::ObjCSelector>::getHashValue(a.selector),
664+
hash_value(a.isInstanceMethod));
665+
}
666+
static bool isEqual(ObjCMethodConflict a, ObjCMethodConflict b) {
667+
return a.typeDecl == b.typeDecl && a.selector == b.selector &&
668+
a.isInstanceMethod == b.isInstanceMethod;
669+
}
670+
};
671+
672+
}
673+
674+
639675
#endif

lib/AST/NameLookup.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1714,12 +1714,11 @@ void NominalTypeDecl::recordObjCMethod(AbstractFunctionDecl *method,
17141714
return;
17151715

17161716
if (auto *sf = method->getParentSourceFile()) {
1717-
if (vec.size() == 1) {
1718-
// We have a conflict.
1719-
sf->ObjCMethodConflicts.push_back(std::make_tuple(this, selector,
1720-
isInstanceMethod));
1721-
} if (vec.empty()) {
1717+
if (vec.empty()) {
17221718
sf->ObjCMethodList.push_back(method);
1719+
} else {
1720+
// We have a conflict.
1721+
sf->ObjCMethodConflicts.insert({ this, selector, isInstanceMethod });
17231722
}
17241723
}
17251724

lib/Sema/TypeCheckDeclObjC.cpp

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2422,11 +2422,8 @@ bool swift::diagnoseUnintendedObjCMethodOverrides(SourceFile &sf) {
24222422
/// Retrieve the source file for the given Objective-C member conflict.
24232423
static TinyPtrVector<AbstractFunctionDecl *>
24242424
getObjCMethodConflictDecls(const SourceFile::ObjCMethodConflict &conflict) {
2425-
NominalTypeDecl *typeDecl = std::get<0>(conflict);
2426-
ObjCSelector selector = std::get<1>(conflict);
2427-
bool isInstanceMethod = std::get<2>(conflict);
2428-
2429-
return typeDecl->lookupDirect(selector, isInstanceMethod);
2425+
return conflict.typeDecl->lookupDirect(conflict.selector,
2426+
conflict.isInstanceMethod);
24302427
}
24312428

24322429
static ObjCAttr *getObjCAttrIfFromAccessNote(ValueDecl *VD) {
@@ -2452,7 +2449,8 @@ bool swift::diagnoseObjCMethodConflicts(SourceFile &sf) {
24522449
// Sort the set of conflicts so we get a deterministic order for
24532450
// diagnostics. We use the first conflicting declaration in each set to
24542451
// perform the sort.
2455-
auto localConflicts = sf.ObjCMethodConflicts;
2452+
llvm::SmallVector<SourceFile::ObjCMethodConflict, 4> localConflicts;
2453+
llvm::copy(sf.ObjCMethodConflicts, std::back_inserter(localConflicts));
24562454
std::sort(localConflicts.begin(), localConflicts.end(),
24572455
[&](const SourceFile::ObjCMethodConflict &lhs,
24582456
const SourceFile::ObjCMethodConflict &rhs) {
@@ -2463,9 +2461,6 @@ bool swift::diagnoseObjCMethodConflicts(SourceFile &sf) {
24632461
// Diagnose each conflict.
24642462
bool anyConflicts = false;
24652463
for (const auto &conflict : localConflicts) {
2466-
NominalTypeDecl *tyDecl = std::get<0>(conflict);
2467-
ObjCSelector selector = std::get<1>(conflict);
2468-
24692464
auto methods = getObjCMethodConflictDecls(conflict);
24702465

24712466
// Erase any invalid or stub declarations. We don't want to complain about
@@ -2545,10 +2540,10 @@ bool swift::diagnoseObjCMethodConflicts(SourceFile &sf) {
25452540
: diag::objc_redecl,
25462541
diagInfo.first, diagInfo.second,
25472542
origDiagInfo.first, origDiagInfo.second,
2548-
selector);
2543+
conflict.selector);
25492544

25502545
// Protocols weren't checked for selector conflicts in 5.0.
2551-
diag.warnUntilSwiftVersionIf(!isa<ClassDecl>(tyDecl), 6);
2546+
diag.warnUntilSwiftVersionIf(!isa<ClassDecl>(conflict.typeDecl), 6);
25522547

25532548
auto objcAttr = getObjCAttrIfFromAccessNote(conflictingDecl);
25542549
swift::softenIfAccessNote(conflictingDecl, objcAttr, diag);

0 commit comments

Comments
 (0)