OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/report.h" | 5 #include "vm/report.h" |
6 | 6 |
7 #include "vm/code_patcher.h" | 7 #include "vm/code_patcher.h" |
8 #include "vm/exceptions.h" | 8 #include "vm/exceptions.h" |
9 #include "vm/flags.h" | 9 #include "vm/flags.h" |
10 #include "vm/longjump.h" | 10 #include "vm/longjump.h" |
11 #include "vm/object.h" | 11 #include "vm/object.h" |
12 #include "vm/stack_frame.h" | 12 #include "vm/stack_frame.h" |
13 #include "vm/symbols.h" | 13 #include "vm/symbols.h" |
14 | 14 |
15 namespace dart { | 15 namespace dart { |
16 | 16 |
17 DEFINE_FLAG(bool, silent_warnings, false, "Silence warnings."); | 17 DEFINE_FLAG(bool, silent_warnings, false, "Silence warnings."); |
18 DEFINE_FLAG(bool, warning_as_error, false, "Treat warnings as errors."); | 18 DEFINE_FLAG(bool, warning_as_error, false, "Treat warnings as errors."); |
19 | 19 |
20 RawString* Report::PrependSnippet(Kind kind, | 20 RawString* Report::PrependSnippet(Kind kind, |
21 const Script& script, | 21 const Script& script, |
22 TokenPosition token_pos, | 22 TokenPosition token_pos, |
23 bool report_after_token, | 23 bool report_after_token, |
24 const String& message) { | 24 const String& message) { |
25 const char* message_header; | 25 const char* message_header; |
26 switch (kind) { | 26 switch (kind) { |
27 case kWarning: message_header = "warning"; break; | 27 case kWarning: |
28 case kError: message_header = "error"; break; | 28 message_header = "warning"; |
29 case kMalformedType: message_header = "malformed type"; break; | 29 break; |
30 case kMalboundedType: message_header = "malbounded type"; break; | 30 case kError: |
31 case kBailout: message_header = "bailout"; break; | 31 message_header = "error"; |
32 default: message_header = ""; UNREACHABLE(); | 32 break; |
| 33 case kMalformedType: |
| 34 message_header = "malformed type"; |
| 35 break; |
| 36 case kMalboundedType: |
| 37 message_header = "malbounded type"; |
| 38 break; |
| 39 case kBailout: |
| 40 message_header = "bailout"; |
| 41 break; |
| 42 default: |
| 43 message_header = ""; |
| 44 UNREACHABLE(); |
33 } | 45 } |
34 String& result = String::Handle(); | 46 String& result = String::Handle(); |
35 if (!script.IsNull()) { | 47 if (!script.IsNull()) { |
36 const String& script_url = String::Handle(script.url()); | 48 const String& script_url = String::Handle(script.url()); |
37 if (token_pos.IsReal()) { | 49 if (token_pos.IsReal()) { |
38 intptr_t line, column, token_len; | 50 intptr_t line, column, token_len; |
39 script.GetTokenLocation(token_pos, &line, &column, &token_len); | 51 script.GetTokenLocation(token_pos, &line, &column, &token_len); |
40 if (report_after_token) { | 52 if (report_after_token) { |
41 column += token_len; | 53 column += token_len; |
42 } | 54 } |
43 // Only report the line position if we have the original source. We still | 55 // Only report the line position if we have the original source. We still |
44 // need to get a valid column so that we can report the ^ mark below the | 56 // need to get a valid column so that we can report the ^ mark below the |
45 // snippet. | 57 // snippet. |
46 // Allocate formatted strings in old space as they may be created during | 58 // Allocate formatted strings in old space as they may be created during |
47 // optimizing compilation. Those strings are created rarely and should not | 59 // optimizing compilation. Those strings are created rarely and should not |
48 // polute old space. | 60 // polute old space. |
49 if (script.HasSource()) { | 61 if (script.HasSource()) { |
50 result = String::NewFormatted(Heap::kOld, | 62 result = String::NewFormatted( |
51 "'%s': %s: line %" Pd " pos %" Pd ": ", | 63 Heap::kOld, "'%s': %s: line %" Pd " pos %" Pd ": ", |
52 script_url.ToCString(), | 64 script_url.ToCString(), message_header, line, column); |
53 message_header, | |
54 line, | |
55 column); | |
56 } else { | 65 } else { |
57 result = String::NewFormatted(Heap::kOld, | 66 result = |
58 "'%s': %s: line %" Pd ": ", | 67 String::NewFormatted(Heap::kOld, "'%s': %s: line %" Pd ": ", |
59 script_url.ToCString(), | 68 script_url.ToCString(), message_header, line); |
60 message_header, | |
61 line); | |
62 } | 69 } |
63 // Append the formatted error or warning message. | 70 // Append the formatted error or warning message. |
64 const Array& strs = Array::Handle( | 71 const Array& strs = Array::Handle(Array::New(6, Heap::kOld)); |
65 Array::New(6, Heap::kOld)); | |
66 strs.SetAt(0, result); | 72 strs.SetAt(0, result); |
67 strs.SetAt(1, message); | 73 strs.SetAt(1, message); |
68 // Append the source line. | 74 // Append the source line. |
69 const String& script_line = String::Handle( | 75 const String& script_line = |
70 script.GetLine(line, Heap::kOld)); | 76 String::Handle(script.GetLine(line, Heap::kOld)); |
71 ASSERT(!script_line.IsNull()); | 77 ASSERT(!script_line.IsNull()); |
72 strs.SetAt(2, Symbols::NewLine()); | 78 strs.SetAt(2, Symbols::NewLine()); |
73 strs.SetAt(3, script_line); | 79 strs.SetAt(3, script_line); |
74 strs.SetAt(4, Symbols::NewLine()); | 80 strs.SetAt(4, Symbols::NewLine()); |
75 // Append the column marker. | 81 // Append the column marker. |
76 const String& column_line = String::Handle( | 82 const String& column_line = String::Handle(String::NewFormatted( |
77 String::NewFormatted(Heap::kOld, | 83 Heap::kOld, "%*s\n", static_cast<int>(column), "^")); |
78 "%*s\n", static_cast<int>(column), "^")); | |
79 strs.SetAt(5, column_line); | 84 strs.SetAt(5, column_line); |
80 result = String::ConcatAll(strs, Heap::kOld); | 85 result = String::ConcatAll(strs, Heap::kOld); |
81 } else { | 86 } else { |
82 // Token position is unknown. | 87 // Token position is unknown. |
83 result = String::NewFormatted(Heap::kOld, "'%s': %s: ", | 88 result = String::NewFormatted(Heap::kOld, "'%s': %s: ", |
84 script_url.ToCString(), | 89 script_url.ToCString(), message_header); |
85 message_header); | |
86 result = String::Concat(result, message, Heap::kOld); | 90 result = String::Concat(result, message, Heap::kOld); |
87 } | 91 } |
88 } else { | 92 } else { |
89 // Script is unknown. | 93 // Script is unknown. |
90 // Append the formatted error or warning message. | 94 // Append the formatted error or warning message. |
91 result = String::NewFormatted(Heap::kOld, "%s: ", message_header); | 95 result = String::NewFormatted(Heap::kOld, "%s: ", message_header); |
92 result = String::Concat(result, message, Heap::kOld); | 96 result = String::Concat(result, message, Heap::kOld); |
93 } | 97 } |
94 return result.raw(); | 98 return result.raw(); |
95 } | 99 } |
96 | 100 |
97 | 101 |
98 void Report::LongJump(const Error& error) { | 102 void Report::LongJump(const Error& error) { |
99 Thread::Current()->long_jump_base()->Jump(1, error); | 103 Thread::Current()->long_jump_base()->Jump(1, error); |
100 UNREACHABLE(); | 104 UNREACHABLE(); |
101 } | 105 } |
102 | 106 |
103 | 107 |
104 void Report::LongJumpF(const Error& prev_error, | 108 void Report::LongJumpF(const Error& prev_error, |
105 const Script& script, TokenPosition token_pos, | 109 const Script& script, |
106 const char* format, ...) { | 110 TokenPosition token_pos, |
| 111 const char* format, |
| 112 ...) { |
107 va_list args; | 113 va_list args; |
108 va_start(args, format); | 114 va_start(args, format); |
109 LongJumpV(prev_error, script, token_pos, format, args); | 115 LongJumpV(prev_error, script, token_pos, format, args); |
110 va_end(args); | 116 va_end(args); |
111 UNREACHABLE(); | 117 UNREACHABLE(); |
112 } | 118 } |
113 | 119 |
114 | 120 |
115 void Report::LongJumpV(const Error& prev_error, | 121 void Report::LongJumpV(const Error& prev_error, |
116 const Script& script, TokenPosition token_pos, | 122 const Script& script, |
117 const char* format, va_list args) { | 123 TokenPosition token_pos, |
| 124 const char* format, |
| 125 va_list args) { |
118 const Error& error = Error::Handle(LanguageError::NewFormattedV( | 126 const Error& error = Error::Handle(LanguageError::NewFormattedV( |
119 prev_error, script, token_pos, Report::AtLocation, | 127 prev_error, script, token_pos, Report::AtLocation, kError, Heap::kOld, |
120 kError, Heap::kOld, | |
121 format, args)); | 128 format, args)); |
122 LongJump(error); | 129 LongJump(error); |
123 UNREACHABLE(); | 130 UNREACHABLE(); |
124 } | 131 } |
125 | 132 |
126 | 133 |
127 void Report::MessageF(Kind kind, | 134 void Report::MessageF(Kind kind, |
128 const Script& script, | 135 const Script& script, |
129 TokenPosition token_pos, | 136 TokenPosition token_pos, |
130 bool report_after_token, | 137 bool report_after_token, |
131 const char* format, ...) { | 138 const char* format, |
| 139 ...) { |
132 va_list args; | 140 va_list args; |
133 va_start(args, format); | 141 va_start(args, format); |
134 MessageV(kind, script, token_pos, report_after_token, format, args); | 142 MessageV(kind, script, token_pos, report_after_token, format, args); |
135 va_end(args); | 143 va_end(args); |
136 } | 144 } |
137 | 145 |
138 | 146 |
139 void Report::MessageV(Kind kind, | 147 void Report::MessageV(Kind kind, |
140 const Script& script, | 148 const Script& script, |
141 TokenPosition token_pos, | 149 TokenPosition token_pos, |
142 bool report_after_token, | 150 bool report_after_token, |
143 const char* format, va_list args) { | 151 const char* format, |
| 152 va_list args) { |
144 if (kind < kError) { | 153 if (kind < kError) { |
145 // Reporting a warning. | 154 // Reporting a warning. |
146 if (FLAG_silent_warnings) { | 155 if (FLAG_silent_warnings) { |
147 return; | 156 return; |
148 } | 157 } |
149 if (!FLAG_warning_as_error) { | 158 if (!FLAG_warning_as_error) { |
150 const String& msg = String::Handle(String::NewFormattedV(format, args)); | 159 const String& msg = String::Handle(String::NewFormattedV(format, args)); |
151 const String& snippet_msg = String::Handle( | 160 const String& snippet_msg = String::Handle( |
152 PrependSnippet(kind, script, token_pos, report_after_token, msg)); | 161 PrependSnippet(kind, script, token_pos, report_after_token, msg)); |
153 OS::Print("%s", snippet_msg.ToCString()); | 162 OS::Print("%s", snippet_msg.ToCString()); |
154 return; | 163 return; |
155 } | 164 } |
156 } | 165 } |
157 // Reporting an error (or a warning as error). | 166 // Reporting an error (or a warning as error). |
158 const Error& error = Error::Handle( | 167 const Error& error = Error::Handle(LanguageError::NewFormattedV( |
159 LanguageError::NewFormattedV(Error::Handle(), // No previous error. | 168 Error::Handle(), // No previous error. |
160 script, token_pos, report_after_token, | 169 script, token_pos, report_after_token, kind, Heap::kOld, format, args)); |
161 kind, Heap::kOld, | |
162 format, args)); | |
163 LongJump(error); | 170 LongJump(error); |
164 UNREACHABLE(); | 171 UNREACHABLE(); |
165 } | 172 } |
166 | 173 |
167 } // namespace dart | 174 } // namespace dart |
168 | |
OLD | NEW |