Skip to content

Commit eafa51d

Browse files
committed
[AST] DiagnosticEngine: retain strings used in tentative diagnostic arguments
If diagnostics are produced as part of a transaction, let's copy strings associated with arguments into a separate long(er) term storage which is going to be cleaned up when diagnostic is actually emit to the consumers.
1 parent c28174a commit eafa51d

File tree

2 files changed

+39
-2
lines changed

2 files changed

+39
-2
lines changed

include/swift/AST/DiagnosticEngine.h

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include "swift/AST/TypeLoc.h"
2323
#include "swift/AST/DeclNameLoc.h"
2424
#include "swift/AST/DiagnosticConsumer.h"
25+
#include "llvm/ADT/StringMap.h"
26+
#include "llvm/Support/Allocator.h"
2527

2628
namespace swift {
2729
class Decl;
@@ -323,6 +325,8 @@ namespace swift {
323325
SourceLoc Loc;
324326
const Decl *Decl = nullptr;
325327

328+
friend DiagnosticEngine;
329+
326330
public:
327331
// All constructors are intentionally implicit.
328332
template<typename ...ArgTypes>
@@ -564,6 +568,12 @@ namespace swift {
564568
/// results that we can point to on the command line.
565569
llvm::DenseMap<const Decl *, SourceLoc> PrettyPrintedDeclarations;
566570

571+
llvm::BumpPtrAllocator TransactionAllocator;
572+
/// A set of all strings involved in current transactional chain.
573+
/// This is required because diagnostics are not directly emitted
574+
/// but rather stored until all transactions complete.
575+
llvm::StringMap<char, llvm::BumpPtrAllocator &> TransactionStrings;
576+
567577
/// The number of open diagnostic transactions. Diagnostics are only
568578
/// emitted once all transactions have closed.
569579
unsigned TransactionCount = 0;
@@ -579,8 +589,8 @@ namespace swift {
579589

580590
public:
581591
explicit DiagnosticEngine(SourceManager &SourceMgr)
582-
: SourceMgr(SourceMgr), ActiveDiagnostic() {
583-
}
592+
: SourceMgr(SourceMgr), ActiveDiagnostic(),
593+
TransactionStrings(TransactionAllocator) {}
584594

585595
/// hadAnyError - return true if any *error* diagnostics have been emitted.
586596
bool hadAnyError() const { return state.hadAnyError(); }
@@ -797,6 +807,11 @@ namespace swift {
797807
DiagnosticFormatOptions FormatOpts = DiagnosticFormatOptions());
798808

799809
private:
810+
/// Called when tentative diagnostic is about to be flushed,
811+
/// to apply any required transformations e.g. copy string arguments
812+
/// to extend their lifetime.
813+
void onTentativeDiagnosticFlush(Diagnostic &diagnostic);
814+
800815
/// Flush the active diagnostic.
801816
void flushActiveDiagnostic();
802817

@@ -870,6 +885,11 @@ namespace swift {
870885
if (IsOpen) {
871886
commit();
872887
}
888+
889+
if (Depth == 0) {
890+
Engine.TransactionStrings.clear();
891+
Engine.TransactionAllocator.Reset();
892+
}
873893
}
874894

875895
/// Abort and close this transaction and erase all diagnostics

lib/AST/DiagnosticEngine.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -754,6 +754,7 @@ void DiagnosticEngine::flushActiveDiagnostic() {
754754
if (TransactionCount == 0) {
755755
emitDiagnostic(*ActiveDiagnostic);
756756
} else {
757+
onTentativeDiagnosticFlush(*ActiveDiagnostic);
757758
TentativeDiagnostics.emplace_back(std::move(*ActiveDiagnostic));
758759
}
759760
ActiveDiagnostic.reset();
@@ -940,3 +941,19 @@ BufferIndirectlyCausingDiagnosticRAII::BufferIndirectlyCausingDiagnosticRAII(
940941
if (loc.isValid())
941942
Diags.setBufferIndirectlyCausingDiagnosticToInput(loc);
942943
}
944+
945+
void DiagnosticEngine::onTentativeDiagnosticFlush(Diagnostic &diagnostic) {
946+
for (auto curr = diagnostic.Args.begin(), last = diagnostic.Args.end();
947+
curr != last; ++curr) {
948+
auto &arg = *curr;
949+
if (arg.getKind() != DiagnosticArgumentKind::String)
950+
continue;
951+
952+
auto str = arg.getAsString();
953+
if (str.empty())
954+
continue;
955+
956+
auto I = TransactionStrings.insert(std::make_pair(str, char())).first;
957+
*curr = DiagnosticArgument(StringRef(I->getKeyData()));
958+
}
959+
}

0 commit comments

Comments
 (0)