Skip to content

Commit e422947

Browse files
committed
Handle access note I/O and parse errors
1 parent d347ffa commit e422947

File tree

5 files changed

+58
-14
lines changed

5 files changed

+58
-14
lines changed

include/swift/AST/DiagnosticsFrontend.def

+5
Original file line numberDiff line numberDiff line change
@@ -405,5 +405,10 @@ WARNING(module_incompatible_with_skip_function_bodies,none,
405405
"-experimental-skip-*-function-bodies* flags; they have "
406406
"been automatically disabled", (StringRef))
407407

408+
WARNING(invalid_access_notes_file,none,
409+
"access notes at '%0' will be ignored due to an error while loading "
410+
"them: %1",
411+
(StringRef, StringRef))
412+
408413
#define UNDEFINE_DIAGNOSTIC_MACROS
409414
#include "DefineDiagnosticMacros.h"

lib/AST/AccessNotes.cpp

+17-2
Original file line numberDiff line numberDiff line change
@@ -215,15 +215,30 @@ template <> struct llvm::yaml::MappingTraits<swift::AccessNote> {
215215
};
216216

217217
namespace swift {
218+
219+
static void
220+
convertToErrorAndJoin(const llvm::SMDiagnostic &diag, void *Context) {
221+
auto newError = llvm::createStringError(std::errc::invalid_argument,
222+
"%s at line %d, column %d",
223+
diag.getMessage().bytes_begin(),
224+
diag.getLineNo(), diag.getColumnNo());
225+
226+
auto &errors = *(llvm::Error*)Context;
227+
errors = llvm::joinErrors(std::move(errors), std::move(newError));
228+
}
229+
218230
llvm::Expected<AccessNotes>
219231
AccessNotes::load(ASTContext &ctx, llvm::MemoryBuffer *buffer) {
220-
llvm::yaml::Input yamlIn(buffer->getBuffer(), (void *)&ctx);
232+
llvm::Error errors = llvm::Error::success();
233+
234+
llvm::yaml::Input yamlIn(buffer->getBuffer(), (void *)&ctx,
235+
convertToErrorAndJoin, &errors);
221236

222237
AccessNotes notes;
223238
yamlIn >> notes;
224239

225240
if (yamlIn.error())
226-
return llvm::errorCodeToError(yamlIn.error());
241+
return llvm::Expected<AccessNotes>(std::move(errors));
227242

228243
return notes;
229244
}

lib/Frontend/Frontend.cpp

+30-12
Original file line numberDiff line numberDiff line change
@@ -902,6 +902,16 @@ bool CompilerInstance::createFilesForMainModule(
902902
return false;
903903
}
904904

905+
template<typename ExpectedOut, typename ExpectedIn>
906+
static llvm::Expected<ExpectedOut>
907+
flatMap(llvm::Expected<ExpectedIn> &&in,
908+
llvm::function_ref<llvm::Expected<ExpectedOut>(ExpectedIn &&)> transform) {
909+
if (!in)
910+
return llvm::Expected<ExpectedOut>(in.takeError());
911+
912+
return transform(std::move(in.get()));
913+
}
914+
905915
ModuleDecl *CompilerInstance::getMainModule() const {
906916
if (!MainModule) {
907917
Identifier ID = Context->getIdentifier(Invocation.getModuleName());
@@ -935,18 +945,26 @@ ModuleDecl *CompilerInstance::getMainModule() const {
935945
}
936946

937947
if (!Invocation.getFrontendOptions().AccessNotesPath.empty()) {
938-
auto bufferOrError =
939-
swift::vfs::getFileOrSTDIN(getFileSystem(),
940-
Invocation.getFrontendOptions().AccessNotesPath);
941-
// FIXME: Diagnose properly
942-
auto buffer = cantFail(llvm::errorOrToExpected(std::move(bufferOrError)),
943-
"can't open access notes file");
944-
945-
auto expectedAccessNotes = AccessNotes::load(*Context, buffer.get());
946-
// FIXME: Diagnose properly
947-
MainModule->getAccessNotes() = cantFail(std::move(expectedAccessNotes),
948-
"invalid access notes:");
949-
948+
auto accessNotesPath = Invocation.getFrontendOptions().AccessNotesPath;
949+
950+
auto expectedBuffer = llvm::errorOrToExpected(
951+
swift::vfs::getFileOrSTDIN(getFileSystem(), accessNotesPath));
952+
953+
auto expectedAccessNotes =
954+
flatMap<AccessNotes, std::unique_ptr<llvm::MemoryBuffer>>(
955+
std::move(expectedBuffer),
956+
[&](auto &&buffer) -> auto {
957+
return AccessNotes::load(*Context, buffer.get());
958+
});
959+
960+
if (expectedAccessNotes)
961+
MainModule->getAccessNotes() = std::move(expectedAccessNotes).get();
962+
else
963+
llvm::handleAllErrors(expectedAccessNotes.takeError(),
964+
[&](const llvm::ErrorInfoBase &error) {
965+
Context->Diags.diagnose(SourceLoc(), diag::invalid_access_notes_file,
966+
accessNotesPath, error.message());
967+
});
950968
}
951969
}
952970
return MainModule;

test/Sema/Inputs/bad.accessnotes

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Colourless green ideas sleep furiously.

test/Sema/access-notes-invalid.swift

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// RUN: %target-swift-frontend -typecheck -primary-file %s -access-notes-path %S/Inputs/missing.accessnotes 2>&1 | %FileCheck --check-prefix=CHECK-MISSING %s
2+
// CHECK-MISSING: <unknown>:0: warning: access notes at 'SOURCE_DIR/test/Sema/Inputs/missing.accessnotes' will be ignored due to an error while loading them: No such file or directory{{$}}
3+
4+
// RUN: %target-swift-frontend -typecheck -primary-file %s -access-notes-path %S/Inputs/bad.accessnotes 2>&1 | %FileCheck --check-prefix=CHECK-BAD %s
5+
// CHECK-BAD: <unknown>:0: warning: access notes at 'SOURCE_DIR/test/Sema/Inputs/bad.accessnotes' will be ignored due to an error while loading them: not a mapping at line 1, column 0{{$}}

0 commit comments

Comments
 (0)