blob: 0c013fee37eafe5fb29d4e0b9d044ab2ec40bcf5 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- Mangled.cpp ---------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include <cxxabi.h>
11
Greg Claytone41e5892010-09-03 23:26:12 +000012#include "llvm/ADT/DenseMap.h"
13
Chris Lattner30fdc8d2010-06-08 16:52:24 +000014#include "lldb/Core/ConstString.h"
15#include "lldb/Core/Mangled.h"
Greg Clayton83c5cd92010-11-14 22:13:40 +000016#include "lldb/Core/RegularExpression.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000017#include "lldb/Core/Stream.h"
18#include "lldb/Core/Timer.h"
Eli Friedman88966972010-06-09 08:50:27 +000019#include <ctype.h>
20#include <string.h>
Chris Lattner30fdc8d2010-06-08 16:52:24 +000021
22using namespace lldb_private;
23
24#pragma mark Mangled
25//----------------------------------------------------------------------
26// Default constructor
27//----------------------------------------------------------------------
28Mangled::Mangled () :
29 m_mangled(),
30 m_demangled()
31{
32}
33
34//----------------------------------------------------------------------
35// Constructor with an optional string and a boolean indicating if it is
36// the mangled version.
37//----------------------------------------------------------------------
38Mangled::Mangled (const char *s, bool mangled) :
39 m_mangled(),
40 m_demangled()
41{
42 if (s && s[0])
43 {
44 SetValue(s, mangled);
45 }
46}
47
48//----------------------------------------------------------------------
49// Destructor
50//----------------------------------------------------------------------
51Mangled::~Mangled ()
52{
53}
54
55//----------------------------------------------------------------------
56// Convert to pointer operator. This allows code to check any Mangled
57// objects to see if they contain anything valid using code such as:
58//
59// Mangled mangled(...);
60// if (mangled)
61// { ...
62//----------------------------------------------------------------------
63Mangled::operator void* () const
64{
65 return (m_mangled) ? const_cast<Mangled*>(this) : NULL;
66}
67
68//----------------------------------------------------------------------
69// Logical NOT operator. This allows code to check any Mangled
70// objects to see if they are invalid using code such as:
71//
72// Mangled mangled(...);
73// if (!file_spec)
74// { ...
75//----------------------------------------------------------------------
76bool
77Mangled::operator! () const
78{
79 return !m_mangled;
80}
81
82//----------------------------------------------------------------------
83// Clear the mangled and demangled values.
84//----------------------------------------------------------------------
85void
86Mangled::Clear ()
87{
88 m_mangled.Clear();
89 m_demangled.Clear();
90}
91
92
93//----------------------------------------------------------------------
94// Compare the the string values.
95//----------------------------------------------------------------------
96int
97Mangled::Compare (const Mangled& a, const Mangled& b)
98{
Jim Ingham89bf5e92010-09-15 00:13:44 +000099 return ConstString::Compare(a.GetName(ePreferMangled), a.GetName(ePreferMangled));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000100}
101
102
103
104//----------------------------------------------------------------------
105// Set the string value in this objects. If "mangled" is true, then
106// the mangled named is set with the new value in "s", else the
107// demangled name is set.
108//----------------------------------------------------------------------
109void
110Mangled::SetValue (const char *s, bool mangled)
111{
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000112 if (s)
113 {
114 if (mangled)
Greg Clayton385aa282011-04-22 03:55:06 +0000115 {
116 m_demangled.Clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000117 m_mangled.SetCString (s);
Greg Clayton385aa282011-04-22 03:55:06 +0000118 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000119 else
Greg Clayton385aa282011-04-22 03:55:06 +0000120 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000121 m_demangled.SetCString(s);
Greg Clayton385aa282011-04-22 03:55:06 +0000122 m_mangled.Clear();
123 }
124 }
125 else
126 {
127 m_demangled.Clear();
128 m_mangled.Clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000129 }
130}
131
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000132//----------------------------------------------------------------------
133// Generate the demangled name on demand using this accessor. Code in
134// this class will need to use this accessor if it wishes to decode
135// the demangled name. The result is cached and will be kept until a
136// new string value is supplied to this object, or until the end of the
137// object's lifetime.
138//----------------------------------------------------------------------
139const ConstString&
140Mangled::GetDemangledName () const
141{
142 // Check to make sure we have a valid mangled name and that we
143 // haven't already decoded our mangled name.
144 if (m_mangled && !m_demangled)
145 {
146 // We need to generate and cache the demangled name.
147 Timer scoped_timer (__PRETTY_FUNCTION__,
148 "Mangled::GetDemangledName (m_mangled = %s)",
149 m_mangled.GetCString());
150
151 // We already know mangled is valid from the above check,
152 // lets just make sure it isn't empty...
153 const char * mangled = m_mangled.AsCString();
Jason Molendab690fbb2010-12-15 04:20:25 +0000154 // Don't bother running anything that doesn't start with _Z through the demangler
Greg Claytonc3ae1ce2011-06-09 22:34:34 +0000155 if (mangled[0] == '_' && mangled[1] == 'Z')
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000156 {
Greg Claytonc3ae1ce2011-06-09 22:34:34 +0000157 if (!m_mangled.GetMangledCounterpart(m_demangled))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000158 {
Greg Claytone41e5892010-09-03 23:26:12 +0000159 // We didn't already mangle this name, demangle it and if all goes well
160 // add it to our map.
161 char *demangled_name = abi::__cxa_demangle (mangled, NULL, NULL, NULL);
162
163 if (demangled_name)
164 {
Greg Claytonc3ae1ce2011-06-09 22:34:34 +0000165 m_demangled.SetCStringWithMangledCounterpart(demangled_name, m_mangled);
Greg Claytone41e5892010-09-03 23:26:12 +0000166 free (demangled_name);
167 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000168 }
169 }
Jason Molenda3f8688b2010-12-15 04:27:04 +0000170 if (!m_demangled)
171 {
172 // Set the demangled string to the empty string to indicate we
173 // tried to parse it once and failed.
174 m_demangled.SetCString("");
175 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000176 }
177
178 return m_demangled;
179}
180
Greg Clayton83c5cd92010-11-14 22:13:40 +0000181
182bool
183Mangled::NameMatches (const RegularExpression& regex) const
184{
185 if (m_mangled && regex.Execute (m_mangled.AsCString()))
186 return true;
187
188 if (GetDemangledName() && regex.Execute (m_demangled.AsCString()))
189 return true;
190 return false;
191}
192
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000193//----------------------------------------------------------------------
194// Get the demangled name if there is one, else return the mangled name.
195//----------------------------------------------------------------------
196const ConstString&
Jim Ingham08b87e02010-09-14 22:03:00 +0000197Mangled::GetName (Mangled::NamePreference preference) const
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000198{
Greg Clayton87425432010-09-14 23:44:49 +0000199 if (preference == ePreferDemangled)
Jim Ingham08b87e02010-09-14 22:03:00 +0000200 {
Greg Claytond0b89f82010-09-14 23:48:44 +0000201 // Call the accessor to make sure we get a demangled name in case
202 // it hasn't been demangled yet...
203 if (GetDemangledName())
204 return m_demangled;
Greg Clayton87425432010-09-14 23:44:49 +0000205 return m_mangled;
206 }
207 else
208 {
Greg Claytond0b89f82010-09-14 23:48:44 +0000209 if (m_mangled)
210 return m_mangled;
211 return GetDemangledName();
Jim Ingham08b87e02010-09-14 22:03:00 +0000212 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000213}
214
215//----------------------------------------------------------------------
216// Generate the tokens from the demangled name.
217//
218// Returns the number of tokens that were parsed.
219//----------------------------------------------------------------------
220size_t
221Mangled::GetTokens (Mangled::TokenList &tokens) const
222{
223 tokens.Clear();
224 const ConstString& demangled = GetDemangledName();
225 if (demangled && !demangled.IsEmpty())
226 tokens.Parse(demangled.AsCString());
227
228 return tokens.Size();
229}
230
231//----------------------------------------------------------------------
232// Dump a Mangled object to stream "s". We don't force our
233// demangled name to be computed currently (we don't use the accessor).
234//----------------------------------------------------------------------
235void
236Mangled::Dump (Stream *s) const
237{
238 if (m_mangled)
239 {
240 *s << ", mangled = " << m_mangled;
241 }
242 if (m_demangled)
243 {
244 const char * demangled = m_demangled.AsCString();
245 s->Printf(", demangled = %s", demangled[0] ? demangled : "<error>");
246 }
247}
248
249//----------------------------------------------------------------------
250// Dumps a debug version of this string with extra object and state
251// information to stream "s".
252//----------------------------------------------------------------------
253void
254Mangled::DumpDebug (Stream *s) const
255{
256 s->Printf("%*p: Mangled mangled = ", (int)sizeof(void*) * 2, this);
257 m_mangled.DumpDebug(s);
258 s->Printf(", demangled = ");
259 m_demangled.DumpDebug(s);
260}
261
262//----------------------------------------------------------------------
263// Return the size in byte that this object takes in memory. The size
264// includes the size of the objects it owns, and not the strings that
265// it references because they are shared strings.
266//----------------------------------------------------------------------
267size_t
268Mangled::MemorySize () const
269{
270 return m_mangled.MemorySize() + m_demangled.MemorySize();
271}
272
273//----------------------------------------------------------------------
274// Dump OBJ to the supplied stream S.
275//----------------------------------------------------------------------
276Stream&
277operator << (Stream& s, const Mangled& obj)
278{
279 if (obj.GetMangledName())
280 s << "mangled = '" << obj.GetMangledName() << "'";
281
282 const ConstString& demangled = obj.GetDemangledName();
283 if (demangled)
284 s << ", demangled = '" << demangled << '\'';
285 else
286 s << ", demangled = <error>";
287 return s;
288}
289
290
291
292
293#pragma mark Mangled::Token
294
295//--------------------------------------------------------------
296// Default constructor
297//--------------------------------------------------------------
298Mangled::Token::Token () :
299 type(eInvalid),
300 value()
301{
302}
303
304//--------------------------------------------------------------
305// Equal to operator
306//--------------------------------------------------------------
307bool
308Mangled::Token::operator== (const Token& rhs) const
309{
310 return type == rhs.type && value == rhs.value;
311}
312
313//--------------------------------------------------------------
314// Dump the token to a stream "s"
315//--------------------------------------------------------------
316void
317Mangled::Token::Dump (Stream *s) const
318{
319 switch (type)
320 {
321 case eInvalid: s->PutCString("invalid "); break;
322 case eNameSpace: s->PutCString("namespace "); break;
323 case eMethodName: s->PutCString("method "); break;
324 case eType: s->PutCString("type "); break;
325 case eTemplate: s->PutCString("template "); break;
326 case eTemplateBeg: s->PutCString("template < "); break;
327 case eTemplateEnd: s->PutCString("template > "); break;
328 case eParamsBeg: s->PutCString("params ( "); break;
329 case eParamsEnd: s->PutCString("params ) "); break;
330 case eQualifier: s->PutCString("qualifier "); break;
331 case eError: s->PutCString("ERROR "); break;
332 default:
333 s->Printf("type = %i", type);
334 break;
335 }
336 value.DumpDebug(s);
337}
338
339//--------------------------------------------------------------
340// Returns true if this token is a wildcard
341//--------------------------------------------------------------
342bool
343Mangled::Token::IsWildcard () const
344{
345 static ConstString g_wildcard_str("*");
346 return value == g_wildcard_str;
347}
348
349
350//----------------------------------------------------------------------
351// Dump "obj" to the supplied stream "s"
352//----------------------------------------------------------------------
353Stream&
354lldb_private::operator << (Stream& s, const Mangled::Token& obj)
355{
356 obj.Dump(&s);
357 return s;
358}
359
360
361#pragma mark Mangled::TokenList
362//----------------------------------------------------------------------
363// Mangled::TokenList
364//----------------------------------------------------------------------
365
366//--------------------------------------------------------------
367// Default constructor. If demangled is non-NULL and not-empty
368// the token list will parse up the demangled string it is
369// given, else the object will initialize an empty token list.
370//--------------------------------------------------------------
371Mangled::TokenList::TokenList (const char *demangled) :
372 m_tokens()
373{
374 if (demangled && demangled[0])
375 {
376 Parse(demangled);
377 }
378}
379
380//----------------------------------------------------------------------
381// Destructor
382//----------------------------------------------------------------------
383Mangled::TokenList::~TokenList ()
384{
385}
386
387//----------------------------------------------------------------------
388// Parses "demangled" into tokens. This allows complex
389// comparisons to be done. Comparisons can include wildcards at
390// the namespace, method name, template, and template and
391// parameter type levels.
392//
393// Example queries include:
394// "std::basic_string<*>" // Find all std::basic_string variants
395// "std::basic_string<*>::erase(*)" // Find all std::basic_string::erase variants with any number of parameters
396// "*::clear()" // Find all functions with a method name of
397// // "clear" that are in any namespace that
398// // have no parameters
399// "::printf" // Find the printf function in the global namespace
400// "printf" // Ditto
401// "foo::*(int)" // Find all functions in the class or namespace "foo" that take a single integer argument
402//
403// Returns the number of tokens that were decoded, or zero when
404// we fail.
405//----------------------------------------------------------------------
406size_t
407Mangled::TokenList::Parse (const char *s)
408{
409 m_tokens.clear();
410
411 Token token;
412 token.type = eNameSpace;
413
414 TokenType max_type = eInvalid;
415 const char *p = s;
416 size_t span = 0;
417 size_t sep_size = 0;
418
419 while (*p != '\0')
420 {
421 p = p + span + sep_size;
422 while (isspace(*p))
423 ++p;
424
425 if (*p == '\0')
426 break;
427
428 span = strcspn(p, ":<>(),");
429 sep_size = 1;
430 token.type = eInvalid;
431 switch (p[span])
432 {
433 case '\0':
434 break;
435
436 case ':':
437 if (p[span+1] == ':')
438 {
439 sep_size = 2;
440 if (span > 0)
441 {
442 token.type = eNameSpace;
443 token.value.SetCStringWithLength (p, span);
444 m_tokens.push_back(token);
445 }
446 else
447 continue;
448 }
449 break;
450
451 case '(':
452 if (span > 0)
453 {
454 token.type = eMethodName;
455 token.value.SetCStringWithLength (p, span);
456 m_tokens.push_back(token);
457 }
458
459 token.type = eParamsBeg;
460 token.value.Clear();
461 m_tokens.push_back(token);
462 break;
463
464 case ',':
465 if (span > 0)
466 {
467 token.type = eType;
468 token.value.SetCStringWithLength (p, span);
469 m_tokens.push_back(token);
470 }
471 else
472 {
473 continue;
474 }
475 break;
476
477 case ')':
478 if (span > 0)
479 {
480 token.type = eType;
481 token.value.SetCStringWithLength (p, span);
482 m_tokens.push_back(token);
483 }
484
485 token.type = eParamsEnd;
486 token.value.Clear();
487 m_tokens.push_back(token);
488 break;
489
490 case '<':
491 if (span > 0)
492 {
493 token.type = eTemplate;
494 token.value.SetCStringWithLength (p, span);
495 m_tokens.push_back(token);
496 }
497
498 token.type = eTemplateBeg;
499 token.value.Clear();
500 m_tokens.push_back(token);
501 break;
502
503 case '>':
504 if (span > 0)
505 {
506 token.type = eType;
507 token.value.SetCStringWithLength (p, span);
508 m_tokens.push_back(token);
509 }
510
511 token.type = eTemplateEnd;
512 token.value.Clear();
513 m_tokens.push_back(token);
514 break;
515 }
516
517 if (max_type < token.type)
518 max_type = token.type;
519
520 if (token.type == eInvalid)
521 {
522 if (max_type >= eParamsEnd)
523 {
524 token.type = eQualifier;
525 token.value.SetCString(p);
526 m_tokens.push_back(token);
527 }
528 else if (max_type >= eParamsBeg)
529 {
530 token.type = eType;
531 token.value.SetCString(p);
532 m_tokens.push_back(token);
533 }
534 else
535 {
536 token.type = eMethodName;
537 token.value.SetCString(p);
538 m_tokens.push_back(token);
539 }
540 break;
541 }
542 }
543 return m_tokens.size();
544}
545
546
547//----------------------------------------------------------------------
548// Clear the token list.
549//----------------------------------------------------------------------
550void
551Mangled::TokenList::Clear ()
552{
553 m_tokens.clear();
554}
555
556//----------------------------------------------------------------------
557// Dump the token list to the stream "s"
558//----------------------------------------------------------------------
559void
560Mangled::TokenList::Dump (Stream *s) const
561{
562 collection::const_iterator pos;
563 collection::const_iterator beg = m_tokens.begin();
564 collection::const_iterator end = m_tokens.end();
565 for (pos = beg; pos != end; ++pos)
566 {
567 s->Indent("token[");
568 *s << (uint32_t)std::distance(beg, pos) << "] = " << *pos << "\n";
569 }
570}
571
572//----------------------------------------------------------------------
573// Find the first token in the list that has "token_type" as its
574// type
575//----------------------------------------------------------------------
576const Mangled::Token *
577Mangled::TokenList::Find (TokenType token_type) const
578{
579 collection::const_iterator pos;
580 collection::const_iterator beg = m_tokens.begin();
581 collection::const_iterator end = m_tokens.end();
582 for (pos = beg; pos != end; ++pos)
583 {
584 if (pos->type == token_type)
585 return &(*pos);
586 }
587 return NULL;
588}
589
590//----------------------------------------------------------------------
591// Return the token at index "idx", or NULL if the index is
592// out of range.
593//----------------------------------------------------------------------
594const Mangled::Token *
595Mangled::TokenList::GetTokenAtIndex (uint32_t idx) const
596{
597 if (idx < m_tokens.size())
598 return &m_tokens[idx];
599 return NULL;
600}
601
602
603//----------------------------------------------------------------------
604// Given a token list, see if it matches this object's tokens.
605// "token_list" can contain wild card values to enable powerful
606// matching. Matching the std::string::erase(*) example that was
607// tokenized above we could use a token list such as:
608//
609// token name
610// ----------- ----------------------------------------
611// eNameSpace "std"
612// eTemplate "basic_string"
613// eTemplateBeg
614// eInvalid "*"
615// eTemplateEnd
616// eMethodName "erase"
617// eParamsBeg
618// eInvalid "*"
619// eParamsEnd
620//
621// Returns true if it "token_list" matches this object's tokens,
622// false otherwise.
623//----------------------------------------------------------------------
624bool
625Mangled::TokenList::MatchesQuery (const Mangled::TokenList &match) const
626{
627 size_t match_count = 0;
628 collection::const_iterator pos;
629 collection::const_iterator pos_end = m_tokens.end();
630
631 collection::const_iterator match_pos;
632 collection::const_iterator match_pos_end = match.m_tokens.end();
633 collection::const_iterator match_wildcard_pos = match_pos_end;
634 collection::const_iterator match_next_pos = match_pos_end;
635
636 size_t template_scope_depth = 0;
637
638 for (pos = m_tokens.begin(), match_pos = match.m_tokens.begin();
639 pos != pos_end && match_pos != match_pos_end;
640 ++match_pos)
641 {
642 match_next_pos = match_pos + 1;
643 // Is this a wildcard?
644 if (match_pos->IsWildcard())
645 {
646 if (match_wildcard_pos != match_pos_end)
647 return false; // Can't have two wildcards in effect at once.
648
649 match_wildcard_pos = match_pos;
650 // Are we at the end of the MATCH token list?
651 if (match_next_pos == match_pos_end)
652 {
653 // There is nothing more to match, return if we have any matches so far...
654 return match_count > 0;
655 }
656 }
657
658 if (match_pos->type == eInvalid || match_pos->type == eError)
659 {
660 return false;
661 }
662 else
663 {
664 if (match_pos->type == eTemplateBeg)
665 {
666 ++template_scope_depth;
667 }
668 else if (match_pos->type == eTemplateEnd)
669 {
670 assert(template_scope_depth > 0);
671 --template_scope_depth;
672 }
673
674 // Do we have a wildcard going right now?
675 if (match_wildcard_pos == match_pos_end)
676 {
677 // No wildcard matching right now, just check and see if things match
678 if (*pos == *match_pos)
679 ++match_count;
680 else
681 return false;
682 }
683 else
684 {
685 // We have a wildcard match going
686
687 // For template types we need to make sure to match the template depths...
688 const size_t start_wildcard_template_scope_depth = template_scope_depth;
689 size_t curr_wildcard_template_scope_depth = template_scope_depth;
690 while (pos != pos_end)
691 {
692 if (match_wildcard_pos->type == eNameSpace && pos->type == eParamsBeg)
693 return false;
694
695 if (start_wildcard_template_scope_depth == curr_wildcard_template_scope_depth)
696 {
697 if (*pos == *match_next_pos)
698 {
699 ++match_count;
700 match_pos = match_next_pos;
701 match_wildcard_pos = match_pos_end;
702 break;
703 }
704 }
705 if (pos->type == eTemplateBeg)
706 ++curr_wildcard_template_scope_depth;
707 else if (pos->type == eTemplateEnd)
708 --curr_wildcard_template_scope_depth;
709
710
711 ++pos;
712 }
713 }
714 }
715
716 if (pos != pos_end)
717 ++pos;
718 }
719 if (match_pos != match_pos_end)
720 return false;
721
722 return match_count > 0;
723}
724
725
726//----------------------------------------------------------------------
727// Return the number of tokens in the token collection
728//----------------------------------------------------------------------
729size_t
730Mangled::TokenList::Size () const
731{
732 return m_tokens.size();
733}
734
735
736//----------------------------------------------------------------------
737// Stream out the tokens
738//----------------------------------------------------------------------
739Stream&
740lldb_private::operator << (Stream& s, const Mangled::TokenList& obj)
741{
742 obj.Dump(&s);
743 return s;
744}