Skip to content

Commit 7237653

Browse files
authored
---
yaml --- r: 348783 b: refs/heads/master c: 9b7ab6b h: refs/heads/master i: 348781: 67b37df 348779: 12d6a7e 348775: b4a8335 348767: c10adcc
1 parent 70e193f commit 7237653

File tree

160 files changed

+5768
-5238
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

160 files changed

+5768
-5238
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: 6f3d6105c25d94c660093a5e07a6a762db699e98
2+
refs/heads/master: 9b7ab6bfe7d9eb6c129e5de45911e0941d9326d9
33
refs/heads/master-next: 203b3026584ecad859eb328b2e12490099409cd5
44
refs/tags/osx-passed: b6b74147ef8a386f532cf9357a1bde006e552c54
55
refs/tags/swift-2.2-SNAPSHOT-2015-12-01-a: 6bb18e013c2284f2b45f5f84f2df2887dc0f7dea

trunk/include/swift/AST/DiagnosticConsumer.h

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,17 @@ enum class DiagnosticKind : uint8_t {
3838
Note
3939
};
4040

41-
/// Extra information carried along with a diagnostic, which may or
42-
/// may not be of interest to a given diagnostic consumer.
41+
/// Information about a diagnostic passed to DiagnosticConsumers.
4342
struct DiagnosticInfo {
4443
DiagID ID = DiagID(0);
44+
SourceLoc Loc;
45+
DiagnosticKind Kind;
46+
StringRef FormatString;
47+
ArrayRef<DiagnosticArgument> FormatArgs;
48+
SourceLoc BufferIndirectlyCausingDiagnostic;
49+
50+
/// DiagnosticInfo of notes which are children of this diagnostic, if any
51+
ArrayRef<DiagnosticInfo *> ChildDiagnosticInfo;
4552

4653
/// Represents a fix-it, a replacement of one range of text with another.
4754
class FixIt {
@@ -60,6 +67,24 @@ struct DiagnosticInfo {
6067

6168
/// Extra source ranges that are attached to the diagnostic.
6269
ArrayRef<FixIt> FixIts;
70+
71+
/// This is a note which has a parent error or warning
72+
bool IsChildNote = false;
73+
74+
DiagnosticInfo() {}
75+
76+
DiagnosticInfo(DiagID ID, SourceLoc Loc, DiagnosticKind Kind,
77+
StringRef FormatString,
78+
ArrayRef<DiagnosticArgument> FormatArgs,
79+
SourceLoc BufferIndirectlyCausingDiagnostic,
80+
ArrayRef<DiagnosticInfo *> ChildDiagnosticInfo,
81+
ArrayRef<CharSourceRange> Ranges, ArrayRef<FixIt> FixIts,
82+
bool IsChildNote)
83+
: ID(ID), Loc(Loc), Kind(Kind), FormatString(FormatString),
84+
FormatArgs(FormatArgs),
85+
BufferIndirectlyCausingDiagnostic(BufferIndirectlyCausingDiagnostic),
86+
ChildDiagnosticInfo(ChildDiagnosticInfo), Ranges(Ranges),
87+
FixIts(FixIts), IsChildNote(IsChildNote) {}
6388
};
6489

6590
/// Abstract interface for classes that present diagnostics to the user.

trunk/include/swift/AST/DiagnosticEngine.h

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,9 @@ namespace swift {
337337
SmallVector<DiagnosticArgument, 3> Args;
338338
SmallVector<CharSourceRange, 2> Ranges;
339339
SmallVector<FixIt, 2> FixIts;
340+
std::vector<Diagnostic> ChildNotes;
340341
SourceLoc Loc;
342+
bool IsChildNote = false;
341343
const Decl *Decl = nullptr;
342344

343345
friend DiagnosticEngine;
@@ -362,10 +364,13 @@ namespace swift {
362364
ArrayRef<DiagnosticArgument> getArgs() const { return Args; }
363365
ArrayRef<CharSourceRange> getRanges() const { return Ranges; }
364366
ArrayRef<FixIt> getFixIts() const { return FixIts; }
367+
ArrayRef<Diagnostic> getChildNotes() const { return ChildNotes; }
368+
bool isChildNote() const { return IsChildNote; }
365369
SourceLoc getLoc() const { return Loc; }
366370
const class Decl *getDecl() const { return Decl; }
367371

368372
void setLoc(SourceLoc loc) { Loc = loc; }
373+
void setIsChildNote(bool isChildNote) { IsChildNote = isChildNote; }
369374
void setDecl(const class Decl *decl) { Decl = decl; }
370375

371376
/// Returns true if this object represents a particular diagnostic.
@@ -386,6 +391,8 @@ namespace swift {
386391
void addFixIt(FixIt &&F) {
387392
FixIts.push_back(std::move(F));
388393
}
394+
395+
void addChildNote(Diagnostic &&D);
389396
};
390397

391398
/// Describes an in-flight diagnostic, which is currently active
@@ -665,7 +672,8 @@ namespace swift {
665672

666673
friend class InFlightDiagnostic;
667674
friend class DiagnosticTransaction;
668-
675+
friend class CompoundDiagnosticTransaction;
676+
669677
public:
670678
explicit DiagnosticEngine(SourceManager &SourceMgr)
671679
: SourceMgr(SourceMgr), ActiveDiagnostic(),
@@ -878,6 +886,15 @@ namespace swift {
878886
return diagnose(decl, Diagnostic(id, std::move(args)...));
879887
}
880888

889+
/// Emit a parent diagnostic and attached notes.
890+
///
891+
/// \param parentDiag An InFlightDiagnostic representing the parent diag.
892+
///
893+
/// \param builder A closure which builds and emits notes to be attached to
894+
/// the parent diag.
895+
void diagnoseWithNotes(InFlightDiagnostic parentDiag,
896+
llvm::function_ref<void(void)> builder);
897+
881898
/// \returns true if diagnostic is marked with PointsToFirstBadToken
882899
/// option.
883900
bool isDiagnosticPointsToFirstBadToken(DiagID id) const;
@@ -905,6 +922,10 @@ namespace swift {
905922
/// Retrieve the active diagnostic.
906923
Diagnostic &getActiveDiagnostic() { return *ActiveDiagnostic; }
907924

925+
/// Generate DiagnosticInfo for a Diagnostic to be passed to consumers.
926+
Optional<DiagnosticInfo>
927+
diagnosticInfoForDiagnostic(const Diagnostic &diagnostic);
928+
908929
/// Send \c diag to all diagnostic consumers.
909930
void emitDiagnostic(const Diagnostic &diag);
910931

@@ -945,6 +966,7 @@ namespace swift {
945966
/// in LIFO order. An open transaction is implicitly committed upon
946967
/// destruction.
947968
class DiagnosticTransaction {
969+
protected:
948970
DiagnosticEngine &Engine;
949971

950972
/// How many tentative diagnostics there were when the transaction
@@ -968,7 +990,6 @@ namespace swift {
968990
Depth(Engine.TransactionCount),
969991
IsOpen(true)
970992
{
971-
assert(!Engine.ActiveDiagnostic);
972993
Engine.TransactionCount++;
973994
}
974995

@@ -1011,6 +1032,61 @@ namespace swift {
10111032
"transactions must be closed LIFO");
10121033
}
10131034
};
1035+
1036+
/// Represents a diagnostic transaction which constructs a compound diagnostic
1037+
/// from any diagnostics emitted inside. A compound diagnostic consists of a
1038+
/// parent error, warning, or remark followed by a variable number of child
1039+
/// notes. The semantics are otherwise the same as a regular
1040+
/// DiagnosticTransaction.
1041+
class CompoundDiagnosticTransaction : public DiagnosticTransaction {
1042+
public:
1043+
explicit CompoundDiagnosticTransaction(DiagnosticEngine &engine)
1044+
: DiagnosticTransaction(engine) {}
1045+
1046+
~CompoundDiagnosticTransaction() {
1047+
if (IsOpen) {
1048+
commit();
1049+
}
1050+
1051+
if (Depth == 0) {
1052+
Engine.TransactionStrings.clear();
1053+
Engine.TransactionAllocator.Reset();
1054+
}
1055+
}
1056+
1057+
void commit() {
1058+
assert(PrevDiagnostics < Engine.TentativeDiagnostics.size() &&
1059+
"CompoundDiagnosticTransaction must contain at least one diag");
1060+
1061+
// The first diagnostic is assumed to be the parent. If this is not an
1062+
// error or warning, we'll assert later when trying to add children.
1063+
Diagnostic &parent = Engine.TentativeDiagnostics[PrevDiagnostics];
1064+
1065+
// Associate the children with the parent.
1066+
for (auto diag =
1067+
Engine.TentativeDiagnostics.begin() + PrevDiagnostics + 1;
1068+
diag != Engine.TentativeDiagnostics.end(); ++diag) {
1069+
diag->setIsChildNote(true);
1070+
parent.addChildNote(std::move(*diag));
1071+
}
1072+
1073+
// Erase the children, they'll be emitted alongside their parent.
1074+
Engine.TentativeDiagnostics.erase(Engine.TentativeDiagnostics.begin() +
1075+
PrevDiagnostics + 1,
1076+
Engine.TentativeDiagnostics.end());
1077+
1078+
DiagnosticTransaction::commit();
1079+
}
1080+
};
1081+
1082+
inline void
1083+
DiagnosticEngine::diagnoseWithNotes(InFlightDiagnostic parentDiag,
1084+
llvm::function_ref<void(void)> builder) {
1085+
CompoundDiagnosticTransaction transaction(*this);
1086+
parentDiag.flush();
1087+
builder();
1088+
}
1089+
10141090
} // end namespace swift
10151091

10161092
#endif

trunk/include/swift/Basic/STLExtras.h

Lines changed: 16 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ inline Iterator prev_or_begin(Iterator it, Iterator begin) {
253253

254254
/// A range of iterators.
255255
/// TODO: Add `llvm::iterator_range::empty()`, then remove this helper, along
256-
/// with the superfluous FilterIterator and TransformIterator.
256+
/// with the superfluous TransformIterator.
257257
template<typename Iterator>
258258
class IteratorRange {
259259
Iterator First, Last;
@@ -279,136 +279,6 @@ makeIteratorRange(Iterator first, Iterator last) {
279279
return IteratorRange<Iterator>(first, last);
280280
}
281281

282-
/// An iterator that filters the results of an underlying forward
283-
/// iterator, only passing through those values that satisfy a predicate.
284-
///
285-
/// \tparam Iterator the underlying iterator.
286-
///
287-
/// \tparam Predicate A predicate that determines whether a value of the
288-
/// underlying iterator is available in the resulting sequence.
289-
template<typename Iterator, typename Predicate>
290-
class FilterIterator {
291-
Iterator Current, End;
292-
293-
/// FIXME: Could optimize away this storage with EBCO tricks.
294-
Predicate Pred;
295-
296-
/// Skip any non-matching elements.
297-
void skipNonMatching() {
298-
while (Current != End && !Pred(*Current))
299-
++Current;
300-
}
301-
302-
public:
303-
/// Used to indicate when the current iterator has already been
304-
/// "primed", meaning that it's at the end or points to a value that
305-
/// satisfies the predicate.
306-
enum PrimedT { Primed };
307-
308-
using iterator_category = std::forward_iterator_tag;
309-
using value_type = typename std::iterator_traits<Iterator>::value_type;
310-
using reference = typename std::iterator_traits<Iterator>::reference;
311-
using pointer = typename std::iterator_traits<Iterator>::pointer;
312-
using difference_type =
313-
typename std::iterator_traits<Iterator>::difference_type;
314-
315-
/// Construct a new filtering iterator for the given iterator range
316-
/// and predicate.
317-
FilterIterator(Iterator current, Iterator end, Predicate pred)
318-
: Current(current), End(end), Pred(pred)
319-
{
320-
// Prime the iterator.
321-
skipNonMatching();
322-
}
323-
324-
/// Construct a new filtering iterator for the given iterator range
325-
/// and predicate, where the iterator range has already been
326-
/// "primed" by ensuring that it is empty or the current iterator
327-
/// points to something that matches the predicate.
328-
FilterIterator(Iterator current, Iterator end, Predicate pred, PrimedT)
329-
: Current(current), End(end), Pred(pred)
330-
{
331-
// Assert that the iterators have already been primed.
332-
assert(Current == End || Pred(*Current) && "Not primed!");
333-
}
334-
335-
reference operator*() const {
336-
return *Current;
337-
}
338-
339-
pointer operator->() const {
340-
return Current.operator->();
341-
}
342-
343-
FilterIterator &operator++() {
344-
++Current;
345-
skipNonMatching();
346-
return *this;
347-
}
348-
349-
FilterIterator operator++(int) {
350-
FilterIterator old = *this;
351-
++*this;
352-
return old;
353-
}
354-
355-
friend bool operator==(FilterIterator lhs, FilterIterator rhs) {
356-
return lhs.Current == rhs.Current;
357-
}
358-
friend bool operator!=(FilterIterator lhs, FilterIterator rhs) {
359-
return !(lhs == rhs);
360-
}
361-
};
362-
363-
/// Create a new filter iterator.
364-
template<typename Iterator, typename Predicate>
365-
inline FilterIterator<Iterator, Predicate>
366-
makeFilterIterator(Iterator current, Iterator end, Predicate pred) {
367-
return FilterIterator<Iterator, Predicate>(current, end, pred);
368-
}
369-
370-
/// A range filtered by a specific predicate.
371-
template<typename Range, typename Predicate>
372-
class FilterRange {
373-
using Iterator = typename Range::iterator;
374-
375-
Iterator First, Last;
376-
Predicate Pred;
377-
378-
public:
379-
using iterator = FilterIterator<Iterator, Predicate>;
380-
381-
FilterRange(Range range, Predicate pred)
382-
: First(range.begin()), Last(range.end()), Pred(pred)
383-
{
384-
// Prime the sequence.
385-
while (First != Last && !Pred(*First))
386-
++First;
387-
}
388-
389-
iterator begin() const {
390-
return iterator(First, Last, Pred, iterator::Primed);
391-
}
392-
393-
iterator end() const {
394-
return iterator(Last, Last, Pred, iterator::Primed);
395-
}
396-
397-
bool empty() const { return First == Last; }
398-
399-
typename std::iterator_traits<iterator>::value_type front() const {
400-
assert(!empty() && "Front of empty range");
401-
return *begin();
402-
}
403-
};
404-
405-
/// Create a new filter range.
406-
template<typename Range, typename Predicate>
407-
inline FilterRange<Range, Predicate>
408-
makeFilterRange(Range range, Predicate pred) {
409-
return FilterRange<Range, Predicate>(range, pred);
410-
}
411-
412282
/// An iterator that transforms the result of an underlying bidirectional
413283
/// iterator with a given operation.
414284
///
@@ -488,7 +358,7 @@ class TransformRange {
488358
Operation Op;
489359

490360
public:
491-
using iterator = TransformIterator<typename Range::iterator, Operation>;
361+
using iterator = TransformIterator<decltype(Rng.begin()), Operation>;
492362

493363
TransformRange(Range range, Operation op)
494364
: Rng(range), Op(op) { }
@@ -497,6 +367,20 @@ class TransformRange {
497367
iterator end() const { return iterator(Rng.end(), Op); }
498368
bool empty() const { return begin() == end(); }
499369

370+
// The dummy template parameter keeps 'size()' from being eagerly
371+
// instantiated.
372+
template <typename Dummy = Range>
373+
typename function_traits<decltype(&Dummy::size)>::result_type
374+
size() const {
375+
return Rng.size();
376+
}
377+
378+
template <typename Index>
379+
typename function_traits<Operation>::result_type
380+
operator[](Index index) const {
381+
return Op(Rng[index]);
382+
}
383+
500384
typename std::iterator_traits<iterator>::value_type front() const {
501385
assert(!empty() && "Front of empty range");
502386
return *begin();

0 commit comments

Comments
 (0)