@@ -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,26 @@ 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
+ // We've already checked that the character is ASCII
222
+ // Once `char::is_ascii_punctuation` and `char::is_ascii_alphanumeric`
223
+ // have been stable for long enough, use those instead for clarity
224
+ c. is_alphanumeric ( ) || is_ascii_punctuation ( c)
225
+ } )
226
+ }
227
+
228
+ // Copied from the documentation of `char::is_ascii_punctuation`
229
+ fn is_ascii_punctuation ( c : char ) -> bool {
230
+ match c {
231
+ '\u{0021}' ... '\u{002F}' |
232
+ '\u{003A}' ... '\u{0040}' |
233
+ '\u{005B}' ... '\u{0060}' |
234
+ '\u{007B}' ... '\u{007E}' => true ,
235
+ _ => false ,
236
+ }
237
+ }
238
+
205
239
impl < ' a > fmt:: Display for Demangle < ' a > {
206
240
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
207
241
// Alright, let's do this.
@@ -288,6 +322,8 @@ impl<'a> fmt::Display for Demangle<'a> {
288
322
}
289
323
}
290
324
325
+ try!( f. write_str ( self . suffix ) ) ;
326
+
291
327
Ok ( ( ) )
292
328
}
293
329
}
@@ -398,6 +434,17 @@ mod tests {
398
434
t_nohash ! ( "_ZN9backtrace3foo17hbb467fcdaea5d79bE.llvm.A5310EB9" , "backtrace::foo" ) ;
399
435
}
400
436
437
+ #[ test]
438
+ fn demangle_llvm_ir_branch_labels ( ) {
439
+ 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" ) ;
440
+ 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" ) ;
441
+ }
442
+
443
+ #[ test]
444
+ fn demangle_ignores_suffix_that_doesnt_look_like_a_symbol ( ) {
445
+ t ! ( "_ZN3fooE.llvm moocow" , "_ZN3fooE.llvm moocow" ) ;
446
+ }
447
+
401
448
#[ test]
402
449
fn dont_panic ( ) {
403
450
super :: demangle ( "_ZN2222222222222222222222EE" ) . to_string ( ) ;
0 commit comments