mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 10:49:00 +00:00
0633041729
Closes https://github.com/dart-lang/sdk/pull/50786 TEST=ci GitOrigin-RevId: 781a38e2925ba505f0223ecd578faa9be8e1485c Change-Id: Ia3c615012d1bac3f0cf64dc01c2ceb40d50d1193 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/276684 Reviewed-by: Alexander Markov <alexmarkov@google.com> Commit-Queue: Martin Kustermann <kustermann@google.com>
162 lines
5.5 KiB
C++
162 lines
5.5 KiB
C++
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
#include "vm/report.h"
|
|
|
|
#include "vm/code_patcher.h"
|
|
#include "vm/exceptions.h"
|
|
#include "vm/flags.h"
|
|
#include "vm/longjump.h"
|
|
#include "vm/object.h"
|
|
#include "vm/stack_frame.h"
|
|
#include "vm/symbols.h"
|
|
|
|
namespace dart {
|
|
|
|
DEFINE_FLAG(bool, silent_warnings, false, "Silence warnings.");
|
|
DEFINE_FLAG(bool, warning_as_error, false, "Treat warnings as errors.");
|
|
|
|
StringPtr Report::PrependSnippet(Kind kind,
|
|
const Script& script,
|
|
TokenPosition token_pos,
|
|
bool report_after_token,
|
|
const String& message) {
|
|
const char* message_header;
|
|
switch (kind) {
|
|
case kWarning:
|
|
message_header = "warning";
|
|
break;
|
|
case kError:
|
|
message_header = "error";
|
|
break;
|
|
case kBailout:
|
|
message_header = "bailout";
|
|
break;
|
|
default:
|
|
message_header = "";
|
|
UNREACHABLE();
|
|
}
|
|
String& result = String::Handle();
|
|
if (!script.IsNull() && script.HasSource()) {
|
|
const String& script_url = String::Handle(script.url());
|
|
intptr_t line, column;
|
|
if (script.GetTokenLocation(token_pos, &line, &column)) {
|
|
const intptr_t token_len = script.GetTokenLength(token_pos);
|
|
if (report_after_token) {
|
|
column += token_len < 0 ? 1 : token_len;
|
|
}
|
|
// Allocate formatted strings in old space as they may be created during
|
|
// optimizing compilation. Those strings are created rarely and should not
|
|
// pollute old space.
|
|
result = String::NewFormatted(
|
|
Heap::kOld, "'%s': %s: line %" Pd " pos %" Pd ": ",
|
|
script_url.ToCString(), message_header, line, column);
|
|
// Append the formatted error or warning message.
|
|
const Array& strs = Array::Handle(Array::New(6, Heap::kOld));
|
|
strs.SetAt(0, result);
|
|
strs.SetAt(1, message);
|
|
// Append the source line.
|
|
const String& script_line =
|
|
String::Handle(script.GetLine(line, Heap::kOld));
|
|
ASSERT(!script_line.IsNull());
|
|
strs.SetAt(2, Symbols::NewLine());
|
|
strs.SetAt(3, script_line);
|
|
strs.SetAt(4, Symbols::NewLine());
|
|
// Append the column marker.
|
|
const String& column_line = String::Handle(String::NewFormatted(
|
|
Heap::kOld, "%*s\n", static_cast<int>(column), "^"));
|
|
strs.SetAt(5, column_line);
|
|
result = String::ConcatAll(strs, Heap::kOld);
|
|
} else {
|
|
// Token position is unknown.
|
|
result = String::NewFormatted(
|
|
Heap::kOld, "'%s': %s: ", script_url.ToCString(), message_header);
|
|
result = String::Concat(result, message, Heap::kOld);
|
|
}
|
|
} else {
|
|
// Script is unknown.
|
|
// Append the formatted error or warning message.
|
|
result = String::NewFormatted(Heap::kOld, "%s: ", message_header);
|
|
result = String::Concat(result, message, Heap::kOld);
|
|
}
|
|
return result.ptr();
|
|
}
|
|
|
|
void Report::LongJump(const Error& error) {
|
|
Thread::Current()->long_jump_base()->Jump(1, error);
|
|
UNREACHABLE();
|
|
}
|
|
|
|
void Report::LongJumpF(const Error& prev_error,
|
|
const Script& script,
|
|
TokenPosition token_pos,
|
|
const char* format,
|
|
...) {
|
|
va_list args;
|
|
va_start(args, format);
|
|
LongJumpV(prev_error, script, token_pos, format, args);
|
|
va_end(args);
|
|
UNREACHABLE();
|
|
}
|
|
|
|
void Report::LongJumpV(const Error& prev_error,
|
|
const Script& script,
|
|
TokenPosition token_pos,
|
|
const char* format,
|
|
va_list args) {
|
|
// If an isolate is being killed a [UnwindError] will be propagated up the
|
|
// stack. In such a case we cannot wrap the unwind error in a new
|
|
// [LanguageError]. Instead we simply continue propagating the [UnwindError]
|
|
// upwards.
|
|
if (prev_error.IsUnwindError()) {
|
|
LongJump(prev_error);
|
|
UNREACHABLE();
|
|
}
|
|
const Error& error = Error::Handle(LanguageError::NewFormattedV(
|
|
prev_error, script, token_pos, Report::AtLocation, kError, Heap::kOld,
|
|
format, args));
|
|
LongJump(error);
|
|
UNREACHABLE();
|
|
}
|
|
|
|
void Report::MessageF(Kind kind,
|
|
const Script& script,
|
|
TokenPosition token_pos,
|
|
bool report_after_token,
|
|
const char* format,
|
|
...) {
|
|
va_list args;
|
|
va_start(args, format);
|
|
MessageV(kind, script, token_pos, report_after_token, format, args);
|
|
va_end(args);
|
|
}
|
|
|
|
void Report::MessageV(Kind kind,
|
|
const Script& script,
|
|
TokenPosition token_pos,
|
|
bool report_after_token,
|
|
const char* format,
|
|
va_list args) {
|
|
if (kind < kError) {
|
|
// Reporting a warning.
|
|
if (FLAG_silent_warnings) {
|
|
return;
|
|
}
|
|
if (!FLAG_warning_as_error) {
|
|
const String& msg = String::Handle(String::NewFormattedV(format, args));
|
|
const String& snippet_msg = String::Handle(
|
|
PrependSnippet(kind, script, token_pos, report_after_token, msg));
|
|
OS::PrintErr("%s", snippet_msg.ToCString());
|
|
return;
|
|
}
|
|
}
|
|
// Reporting an error (or a warning as error).
|
|
const Error& error = Error::Handle(LanguageError::NewFormattedV(
|
|
Error::Handle(), // No previous error.
|
|
script, token_pos, report_after_token, kind, Heap::kOld, format, args));
|
|
LongJump(error);
|
|
UNREACHABLE();
|
|
}
|
|
|
|
} // namespace dart
|