@@ -36,6 +36,7 @@ use core::fmt;
36
36
pub struct Demangle < ' a > {
37
37
original : & ' a str ,
38
38
inner : & ' a str ,
39
+ suffix : & ' a str ,
39
40
valid : bool ,
40
41
/// The number of ::-separated elements in the original name.
41
42
elements : usize ,
@@ -98,6 +99,18 @@ pub fn demangle(mut s: &str) -> Demangle {
98
99
}
99
100
}
100
101
102
+ // Output like LLVM IR adds extra period-delimited words. See if
103
+ // we are in that case and save the trailing words if so.
104
+ let mut suffix = "" ;
105
+ if let Some ( i) = s. rfind ( "E." ) {
106
+ let ( head, tail) = s. split_at ( i + 1 ) ; // After the E, before the period
107
+
108
+ if is_symbol_like ( tail) {
109
+ s = head;
110
+ suffix = tail;
111
+ }
112
+ }
113
+
101
114
// First validate the symbol. If it doesn't look like anything we're
102
115
// expecting, we just print it literally. Note that we must handle non-Rust
103
116
// symbols because we could have any function in the backtrace.
@@ -155,6 +168,7 @@ pub fn demangle(mut s: &str) -> Demangle {
155
168
156
169
Demangle {
157
170
inner : inner,
171
+ suffix : suffix,
158
172
valid : valid,
159
173
elements : elements,
160
174
original : s,
@@ -202,6 +216,35 @@ fn is_rust_hash(s: &str) -> bool {
202
216
s. starts_with ( 'h' ) && s[ 1 ..] . chars ( ) . all ( |c| c. is_digit ( 16 ) )
203
217
}
204
218
219
+ fn is_symbol_like ( s : & str ) -> bool {
220
+ s. chars ( ) . all ( |c| {
221
+ // Once `char::is_ascii_punctuation` and `char::is_ascii_alphanumeric`
222
+ // have been stable for long enough, use those instead for clarity
223
+ is_ascii_alphanumeric ( c) || is_ascii_punctuation ( c)
224
+ } )
225
+ }
226
+
227
+ // Copied from the documentation of `char::is_ascii_alphanumeric`
228
+ fn is_ascii_alphanumeric ( c : char ) -> bool {
229
+ match c {
230
+ '\u{0041}' ... '\u{005A}' |
231
+ '\u{0061}' ... '\u{007A}' |
232
+ '\u{0030}' ... '\u{0039}' => true ,
233
+ _ => false ,
234
+ }
235
+ }
236
+
237
+ // Copied from the documentation of `char::is_ascii_punctuation`
238
+ fn is_ascii_punctuation ( c : char ) -> bool {
239
+ match c {
240
+ '\u{0021}' ... '\u{002F}' |
241
+ '\u{003A}' ... '\u{0040}' |
242
+ '\u{005B}' ... '\u{0060}' |
243
+ '\u{007B}' ... '\u{007E}' => true ,
244
+ _ => false ,
245
+ }
246
+ }
247
+
205
248
impl < ' a > fmt:: Display for Demangle < ' a > {
206
249
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
207
250
// Alright, let's do this.
@@ -288,6 +331,8 @@ impl<'a> fmt::Display for Demangle<'a> {
288
331
}
289
332
}
290
333
334
+ try!( f. write_str ( self . suffix ) ) ;
335
+
291
336
Ok ( ( ) )
292
337
}
293
338
}
@@ -398,6 +443,17 @@ mod tests {
398
443
t_nohash ! ( "_ZN9backtrace3foo17hbb467fcdaea5d79bE.llvm.A5310EB9" , "backtrace::foo" ) ;
399
444
}
400
445
446
+ #[ test]
447
+ fn demangle_llvm_ir_branch_labels ( ) {
448
+ t ! ( "_ZN4core5slice77_$LT$impl$u20$core..ops..index..IndexMut$LT$I$GT$$u20$for$u20$$u5b$T$u5d$$GT$9index_mut17haf9727c2edfbc47bE.exit.i.i" , "core::slice::<impl core::ops::index::IndexMut<I> for [T]>::index_mut::haf9727c2edfbc47b.exit.i.i" ) ;
449
+ t_nohash ! ( "_ZN4core5slice77_$LT$impl$u20$core..ops..index..IndexMut$LT$I$GT$$u20$for$u20$$u5b$T$u5d$$GT$9index_mut17haf9727c2edfbc47bE.exit.i.i" , "core::slice::<impl core::ops::index::IndexMut<I> for [T]>::index_mut.exit.i.i" ) ;
450
+ }
451
+
452
+ #[ test]
453
+ fn demangle_ignores_suffix_that_doesnt_look_like_a_symbol ( ) {
454
+ t ! ( "_ZN3fooE.llvm moocow" , "_ZN3fooE.llvm moocow" ) ;
455
+ }
456
+
401
457
#[ test]
402
458
fn dont_panic ( ) {
403
459
super :: demangle ( "_ZN2222222222222222222222EE" ) . to_string ( ) ;
0 commit comments