65
65
#include " llvm/ADT/Twine.h"
66
66
#include " llvm/Support/Compiler.h"
67
67
#include " llvm/Support/DJB.h"
68
+ #include < unordered_map>
68
69
69
70
using namespace swift ;
70
71
@@ -96,6 +97,13 @@ static void checkSuppressedEntries(
96
97
ASTContext &ctx = typeDecl->getASTContext ();
97
98
auto &diags = ctx.Diags ;
98
99
100
+ using EntryTracker = std::unordered_map<KnownProtocolKind,
101
+ SuppressedEntry const *>;
102
+ EntryTracker seenEntries;
103
+
104
+ bool haveMoveOnlyClasses =
105
+ typeDecl->getASTContext ().LangOpts .hasFeature (Feature::MoveOnlyClasses);
106
+
99
107
ArrayRef<SuppressedEntry> suppressedEntries = typeDecl->getSuppressed ();
100
108
for (unsigned i = 0 , n = suppressedEntries.size (); i != n; ++i) {
101
109
auto &suppressed = suppressedEntries[i];
@@ -108,21 +116,63 @@ static void checkSuppressedEntries(
108
116
if (!suppressedTy || suppressedTy->hasError ())
109
117
continue ;
110
118
111
- // Skip over suppressible protocols.
119
+ // only structs, enums, and some classes can have suppressed entries
120
+ if (!(isa<StructDecl>(typeDecl) || isa<EnumDecl>(typeDecl)
121
+ || (isa<ClassDecl>(typeDecl) && haveMoveOnlyClasses))) {
122
+ diags.diagnose (suppressed.getLoc (),
123
+ diag::suppress_on_wrong_decl,
124
+ typeDecl->getDescriptiveKind ());
125
+ // FIXME: a great fix-it would be to remove the entire entry,
126
+ // including any trailing comma. See checkInheritedEntry
127
+ // for an example of the logic to do that. You'll need to update it
128
+ // using MergedArrayRef so it understands source locations for both
129
+ // suppressed and inherited entries.
130
+ continue ;
131
+ }
132
+
133
+ // Ensure it is a suppressible protocol.
112
134
if (auto protocolTy = dyn_cast<ProtocolType>(suppressedTy))
113
135
if (auto protocolDecl = protocolTy->getDecl ())
114
136
if (auto knownProtocol = protocolDecl->getKnownProtocolKind ())
115
- if (isSuppressibleProtocol (knownProtocol.getValue ()))
116
- continue ;
137
+ if (isSuppressibleProtocol (*knownProtocol)) {
138
+ // remember that we've seen this suppression for the type
139
+ EntryTracker::iterator iter;
140
+ bool uniqueEntry;
141
+ std::tie (iter, uniqueEntry) =
142
+ seenEntries.insert ({*knownProtocol, &suppressed});
143
+
144
+ // check if already encountered an entry suppressing this protocol
145
+ if (!uniqueEntry) {
146
+ assert (suppressedTy->getCanonicalType ()
147
+ == iter->second ->getType ()->getCanonicalType ());
148
+
149
+ // Emit a diagnostic about the duplicate suppression.
150
+ diags.diagnose (suppressed.getLoc (),
151
+ diag::suppress_duplicate,
152
+ suppressedTy);
153
+ // FIXME: a great fix-it would be to remove the entire entry.
154
+
155
+ diags.diagnose (iter->second ->getLoc (),
156
+ diag::suppress_previously_here,
157
+ suppressedTy);
158
+ }
117
159
118
- diags.diagnose (suppressed.getLoc (), diag::suppress_cannot_suppress, suppressedTy);
119
- // TODO: fixit to remove both suppressed TypeLoc up to the next item in
120
- // the inheritance clause list, including a trailing comma, etc.
160
+ continue ;
161
+ }
121
162
122
- // TODO: find duplicate suppressions .
163
+ // At this point, the suppressed type is wrong. Tailor the error messages .
123
164
124
- // TODO: update checkInheritanceClause using MergedArrayRef so it can
125
- // properly locate and understand all of the clauses in its fix-its.
165
+ if (suppressedTy->isConstraintType ()) {
166
+ diags.diagnose (suppressed.getLoc (),
167
+ diag::suppress_cannot_suppress,
168
+ suppressedTy);
169
+ // FIXME: a great fix-it would be to remove the entire entry.
170
+ } else {
171
+ diags.diagnose (suppressed.getLoc (),
172
+ diag::suppress_not_protocol,
173
+ suppressedTy);
174
+ // FIXME: a great fix-it would be to remove the entire entry.
175
+ }
126
176
}
127
177
}
128
178
0 commit comments