Skip to content

Commit

Permalink
[Basic] Add a DiagnosticError llvm::ErrorInfo subclass
Browse files Browse the repository at this point in the history
Clang's DiagnosticError is an llvm::Error payload that stores a partial
diagnostic and its location. I'll be using it in the refactoring engine.

Differential Revision: https://reviews.llvm.org/D36969


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@311778 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
hyp committed Aug 25, 2017
1 parent 59be67f commit 494ef6f
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 1 deletion.
61 changes: 61 additions & 0 deletions include/clang/Basic/DiagnosticError.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//===--- DiagnosticError.h - Diagnostic payload for llvm::Error -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_BASIC_DIAGNOSTIC_ERROR_H
#define LLVM_CLANG_BASIC_DIAGNOSTIC_ERROR_H

#include "clang/Basic/PartialDiagnostic.h"
#include "llvm/Support/Error.h"

namespace clang {

/// \brief Carries a Clang diagnostic in an llvm::Error.
///
/// Users should emit the stored diagnostic using the DiagnosticsEngine.
class DiagnosticError : public llvm::ErrorInfo<DiagnosticError> {
public:
DiagnosticError(PartialDiagnosticAt Diag) : Diag(std::move(Diag)) {}

void log(raw_ostream &OS) const override { OS << "clang diagnostic"; }

PartialDiagnosticAt &getDiagnostic() { return Diag; }
const PartialDiagnosticAt &getDiagnostic() const { return Diag; }

/// Creates a new \c DiagnosticError that contains the given diagnostic at
/// the given location.
static llvm::Error create(SourceLocation Loc, PartialDiagnostic Diag) {
return llvm::make_error<DiagnosticError>(
PartialDiagnosticAt(Loc, std::move(Diag)));
}

/// Extracts and returns the diagnostic payload from the given \c Error if
/// the error is a \c DiagnosticError. Returns none if the given error is not
/// a \c DiagnosticError.
static Optional<PartialDiagnosticAt> take(llvm::Error &Err) {
Optional<PartialDiagnosticAt> Result;
Err = llvm::handleErrors(std::move(Err), [&](DiagnosticError &E) {
Result = std::move(E.getDiagnostic());
});
return Result;
}

static char ID;

private:
// Users are not expected to use error_code.
std::error_code convertToErrorCode() const override {
return llvm::inconvertibleErrorCode();
}

PartialDiagnosticAt Diag;
};

} // end namespace clang

#endif // LLVM_CLANG_BASIC_DIAGNOSTIC_ERROR_H
5 changes: 4 additions & 1 deletion lib/Basic/Diagnostic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
//
//===----------------------------------------------------------------------===//

#include "clang/Basic/CharInfo.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/DiagnosticError.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/PartialDiagnostic.h"
Expand Down Expand Up @@ -1050,3 +1051,5 @@ PartialDiagnostic::StorageAllocator::~StorageAllocator() {
llvm::CrashRecoveryContext::isRecoveringFromCrash()) &&
"A partial is on the lam");
}

char DiagnosticError::ID;
22 changes: 22 additions & 0 deletions unittests/Basic/DiagnosticTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//

#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticError.h"
#include "clang/Basic/DiagnosticIDs.h"
#include "gtest/gtest.h"

Expand Down Expand Up @@ -72,4 +73,25 @@ TEST(DiagnosticTest, suppressAfterFatalError) {
}
}

TEST(DiagnosticTest, diagnosticError) {
DiagnosticsEngine Diags(new DiagnosticIDs(), new DiagnosticOptions,
new IgnoringDiagConsumer());
PartialDiagnostic::StorageAllocator Alloc;
llvm::Expected<std::pair<int, int>> Value = DiagnosticError::create(
SourceLocation(), PartialDiagnostic(diag::err_cannot_open_file, Alloc)
<< "file"
<< "error");
ASSERT_TRUE(!Value);
llvm::Error Err = Value.takeError();
Optional<PartialDiagnosticAt> ErrDiag = DiagnosticError::take(Err);
llvm::cantFail(std::move(Err));
ASSERT_FALSE(!ErrDiag);
EXPECT_EQ(ErrDiag->first, SourceLocation());
EXPECT_EQ(ErrDiag->second.getDiagID(), diag::err_cannot_open_file);

Value = std::make_pair(20, 1);
ASSERT_FALSE(!Value);
EXPECT_EQ(*Value, std::make_pair(20, 1));
EXPECT_EQ(Value->first, 20);
}
}

0 comments on commit 494ef6f

Please sign in to comment.