1 //===-- FormatNavigator.h ----------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #ifndef lldb_FormatNavigator_h_
11 #define lldb_FormatNavigator_h_
16 // Other libraries and framework includes
17 #include "clang/AST/DeclCXX.h"
18 #include "clang/AST/Type.h"
19 #include "clang/AST/DeclObjC.h"
22 #include "lldb/lldb-public.h"
24 #include "lldb/Core/Log.h"
25 #include "lldb/Core/RegularExpression.h"
26 #include "lldb/Core/ValueObject.h"
28 #include "lldb/DataFormatters/FormatClasses.h"
30 #include "lldb/Symbol/ClangASTContext.h"
31 #include "lldb/Symbol/ClangASTType.h"
33 #include "lldb/Target/ObjCLanguageRuntime.h"
34 #include "lldb/Target/Process.h"
35 #include "lldb/Target/StackFrame.h"
36 #include "lldb/Target/TargetList.h"
38 namespace lldb_private {
40 // this file (and its. cpp) contain the low-level implementation of LLDB Data Visualization
41 // class DataVisualization is the high-level front-end of this feature
42 // clients should refer to that class as the entry-point into the data formatters
43 // unless they have a good reason to bypass it and prefer to use this file's objects directly
44 class IFormatChangeListener
51 ~IFormatChangeListener () {}
54 GetCurrentRevision () = 0;
61 return ( (c == ' ') || (c == '\t') || (c == '\v') || (c == '\f') );
65 HasPrefix (const char* str1, const char* str2)
67 return ( ::strstr(str1, str2) == str1 );
70 // if the user tries to add formatters for, say, "struct Foo"
71 // those will not match any type because of the way we strip qualifiers from typenames
72 // this method looks for the case where the user is adding a "class","struct","enum" or "union" Foo
73 // and strips the unnecessary qualifier
74 static inline ConstString
75 GetValidTypeName_Impl (const ConstString& type)
82 const char* type_cstr = type.AsCString();
84 if ( HasPrefix(type_cstr, "class ") )
86 else if ( HasPrefix(type_cstr, "enum ") )
88 else if ( HasPrefix(type_cstr, "struct ") )
90 else if ( HasPrefix(type_cstr, "union ") )
96 type_cstr += strip_len;
97 while (IsWhitespace(*type_cstr) && ++type_cstr)
100 return ConstString(type_cstr);
103 template<typename KeyType, typename ValueType>
104 class FormatNavigator;
106 template<typename KeyType, typename ValueType>
111 typedef typename ValueType::SharedPointer ValueSP;
112 typedef std::map<KeyType, ValueSP> MapType;
113 typedef typename MapType::iterator MapIterator;
114 typedef bool(*CallbackType)(void*, KeyType, const ValueSP&);
116 FormatMap(IFormatChangeListener* lst) :
118 m_map_mutex(Mutex::eMutexTypeRecursive),
125 const ValueSP& entry)
128 entry->GetRevision() = listener->GetCurrentRevision();
130 entry->GetRevision() = 0;
132 Mutex::Locker locker(m_map_mutex);
139 Delete (KeyType name)
141 Mutex::Locker locker(m_map_mutex);
142 MapIterator iter = m_map.find(name);
143 if (iter == m_map.end())
154 Mutex::Locker locker(m_map_mutex);
164 Mutex::Locker locker(m_map_mutex);
165 MapIterator iter = m_map.find(name);
166 if (iter == m_map.end())
168 entry = iter->second;
173 LoopThrough (CallbackType callback, void* param)
177 Mutex::Locker locker(m_map_mutex);
178 MapIterator pos, end = m_map.end();
179 for (pos = m_map.begin(); pos != end; pos++)
181 KeyType type = pos->first;
182 if (!callback(param, type, pos->second))
195 GetValueAtIndex (size_t index)
197 Mutex::Locker locker(m_map_mutex);
198 MapIterator iter = m_map.begin();
199 MapIterator end = m_map.end();
211 GetKeyAtIndex (size_t index)
213 Mutex::Locker locker(m_map_mutex);
214 MapIterator iter = m_map.begin();
215 MapIterator end = m_map.end();
229 IFormatChangeListener* listener;
243 friend class FormatNavigator<KeyType, ValueType>;
244 friend class FormatManager;
248 template<typename KeyType, typename ValueType>
249 class FormatNavigator
252 typedef FormatMap<KeyType,ValueType> BackEndType;
255 typedef typename BackEndType::MapType MapType;
256 typedef typename MapType::iterator MapIterator;
257 typedef typename MapType::key_type MapKeyType;
258 typedef typename MapType::mapped_type MapValueType;
259 typedef typename BackEndType::CallbackType CallbackType;
260 typedef typename std::shared_ptr<FormatNavigator<KeyType, ValueType> > SharedPointer;
262 friend class TypeCategoryImpl;
264 FormatNavigator(std::string name,
265 IFormatChangeListener* lst) :
268 m_id_cs(ConstString("id"))
273 Add (const MapKeyType &type, const MapValueType& entry)
275 Add_Impl(type, entry, (KeyType*)NULL);
279 Delete (ConstString type)
281 return Delete_Impl(type, (KeyType*)NULL);
285 Get(ValueObject& valobj,
287 lldb::DynamicValueType use_dynamic,
288 uint32_t* why = NULL)
290 uint32_t value = lldb_private::eFormatterChoiceCriterionDirectChoice;
291 ClangASTType ast_type(valobj.GetClangType());
292 bool ret = Get(valobj, ast_type, entry, use_dynamic, value);
294 entry = MapValueType(entry);
296 entry = MapValueType();
303 Get (ConstString type, MapValueType& entry)
305 return Get_Impl(type, entry, (KeyType*)NULL);
309 GetExact (ConstString type, MapValueType& entry)
311 return GetExact_Impl(type, entry, (KeyType*)NULL);
315 GetAtIndex (size_t index)
317 return m_format_map.GetValueAtIndex(index);
320 lldb::TypeNameSpecifierImplSP
321 GetTypeNameSpecifierAtIndex (size_t index)
323 return GetTypeNameSpecifierAtIndex_Impl(index, (KeyType*)NULL);
329 m_format_map.Clear();
333 LoopThrough (CallbackType callback, void* param)
335 m_format_map.LoopThrough(callback,param);
341 return m_format_map.GetCount();
346 BackEndType m_format_map;
350 DISALLOW_COPY_AND_ASSIGN(FormatNavigator);
355 Add_Impl (const MapKeyType &type, const MapValueType& entry, lldb::RegularExpressionSP *dummy)
357 m_format_map.Add(type,entry);
360 void Add_Impl (const ConstString &type, const MapValueType& entry, ConstString *dummy)
362 m_format_map.Add(GetValidTypeName_Impl(type), entry);
366 Delete_Impl (ConstString type, ConstString *dummy)
368 return m_format_map.Delete(type);
372 Delete_Impl (ConstString type, lldb::RegularExpressionSP *dummy)
374 Mutex& x_mutex = m_format_map.mutex();
375 lldb_private::Mutex::Locker locker(x_mutex);
376 MapIterator pos, end = m_format_map.map().end();
377 for (pos = m_format_map.map().begin(); pos != end; pos++)
379 lldb::RegularExpressionSP regex = pos->first;
380 if ( ::strcmp(type.AsCString(),regex->GetText()) == 0)
382 m_format_map.map().erase(pos);
383 if (m_format_map.listener)
384 m_format_map.listener->Changed();
392 Get_Impl (ConstString type, MapValueType& entry, ConstString *dummy)
394 return m_format_map.Get(type, entry);
398 GetExact_Impl (ConstString type, MapValueType& entry, ConstString *dummy)
400 return Get_Impl(type,entry, (KeyType*)0);
403 lldb::TypeNameSpecifierImplSP
404 GetTypeNameSpecifierAtIndex_Impl (size_t index, ConstString *dummy)
406 ConstString key = m_format_map.GetKeyAtIndex(index);
408 return lldb::TypeNameSpecifierImplSP(new TypeNameSpecifierImpl(key.AsCString(),
411 return lldb::TypeNameSpecifierImplSP();
414 lldb::TypeNameSpecifierImplSP
415 GetTypeNameSpecifierAtIndex_Impl (size_t index, lldb::RegularExpressionSP *dummy)
417 lldb::RegularExpressionSP regex = m_format_map.GetKeyAtIndex(index);
418 if (regex.get() == NULL)
419 return lldb::TypeNameSpecifierImplSP();
420 return lldb::TypeNameSpecifierImplSP(new TypeNameSpecifierImpl(regex->GetText(),
425 Get_Impl (ConstString key, MapValueType& value, lldb::RegularExpressionSP *dummy)
427 const char* key_cstr = key.AsCString();
430 Mutex& x_mutex = m_format_map.mutex();
431 lldb_private::Mutex::Locker locker(x_mutex);
432 MapIterator pos, end = m_format_map.map().end();
433 for (pos = m_format_map.map().begin(); pos != end; pos++)
435 lldb::RegularExpressionSP regex = pos->first;
436 if (regex->Execute(key_cstr))
446 GetExact_Impl (ConstString key, MapValueType& value, lldb::RegularExpressionSP *dummy)
448 Mutex& x_mutex = m_format_map.mutex();
449 lldb_private::Mutex::Locker locker(x_mutex);
450 MapIterator pos, end = m_format_map.map().end();
451 for (pos = m_format_map.map().begin(); pos != end; pos++)
453 lldb::RegularExpressionSP regex = pos->first;
454 if (strcmp(regex->GetText(),key.AsCString()) == 0)
464 Get_BitfieldMatch (ValueObject& valobj,
465 ConstString typeName,
469 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
470 // for bitfields, append size to the typename so one can custom format them
471 StreamString sstring;
472 sstring.Printf("%s:%d",typeName.AsCString(),valobj.GetBitfieldBitSize());
473 ConstString bitfieldname = ConstString(sstring.GetData());
475 log->Printf("[Get_BitfieldMatch] appended bitfield info, final result is %s", bitfieldname.GetCString());
476 if (Get(bitfieldname, entry))
479 log->Printf("[Get_BitfieldMatch] bitfield direct match found, returning");
484 reason |= lldb_private::eFormatterChoiceCriterionStrippedBitField;
486 log->Printf("[Get_BitfieldMatch] no bitfield direct match");
491 bool Get_ObjC (ValueObject& valobj,
494 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
495 lldb::ProcessSP process_sp = valobj.GetProcessSP();
496 ObjCLanguageRuntime* runtime = process_sp->GetObjCLanguageRuntime();
500 log->Printf("[Get_ObjC] no valid ObjC runtime, skipping dynamic");
503 ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp (runtime->GetClassDescriptor(valobj));
507 log->Printf("[Get_ObjC] invalid ISA, skipping dynamic");
510 ConstString name (objc_class_sp->GetClassName());
512 log->Printf("[Get_ObjC] dynamic type inferred is %s - looking for direct dynamic match", name.GetCString());
513 if (Get(name, entry))
516 log->Printf("[Get_ObjC] direct dynamic match found, returning");
520 log->Printf("[Get_ObjC] no dynamic match");
525 Get_Impl (ValueObject& valobj,
526 ClangASTType clang_type,
528 lldb::DynamicValueType use_dynamic,
531 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
533 if (!clang_type.IsValid())
536 log->Printf("[Get_Impl] type is invalid, returning");
540 clang_type = clang_type.RemoveFastQualifiers();
542 ConstString typeName(clang_type.GetConstTypeName());
544 if (valobj.GetBitfieldBitSize() > 0)
546 if (Get_BitfieldMatch(valobj, typeName, entry, reason))
551 log->Printf("[Get_Impl] trying to get %s for VO name %s of type %s",
553 valobj.GetName().AsCString(),
554 typeName.AsCString());
556 if (Get(typeName, entry))
559 log->Printf("[Get] direct match found, returning");
563 log->Printf("[Get_Impl] no direct match");
565 // strip pointers and references and see if that helps
566 if (clang_type.IsReferenceType())
569 log->Printf("[Get_Impl] stripping reference");
570 if (Get_Impl(valobj, clang_type.GetNonReferenceType(), entry, use_dynamic, reason) && !entry->SkipsReferences())
572 reason |= lldb_private::eFormatterChoiceCriterionStrippedPointerReference;
576 else if (clang_type.IsPointerType())
579 log->Printf("[Get_Impl] stripping pointer");
580 if (Get_Impl(valobj, clang_type.GetPointeeType(), entry, use_dynamic, reason) && !entry->SkipsPointers())
582 reason |= lldb_private::eFormatterChoiceCriterionStrippedPointerReference;
587 bool canBeObjCDynamic = valobj.GetClangType().IsPossibleDynamicType (NULL,
591 if (canBeObjCDynamic)
593 if (use_dynamic != lldb::eNoDynamicValues)
596 log->Printf("[Get_Impl] allowed to figure out dynamic ObjC type");
597 if (Get_ObjC(valobj,entry))
599 reason |= lldb_private::eFormatterChoiceCriterionDynamicObjCDiscovery;
604 log->Printf("[Get_Impl] dynamic disabled or failed - stripping ObjC pointer");
605 if (Get_Impl(valobj, clang_type.GetPointeeType(), entry, use_dynamic, reason) && !entry->SkipsPointers())
607 reason |= lldb_private::eFormatterChoiceCriterionStrippedPointerReference;
612 // try to strip typedef chains
613 if (clang_type.IsTypedefType())
616 log->Printf("[Get_Impl] stripping typedef");
617 if ((Get_Impl(valobj, clang_type.GetTypedefedType(), entry, use_dynamic, reason)) && entry->Cascades())
619 reason |= lldb_private::eFormatterChoiceCriterionNavigatedTypedefs;
628 // we are separately passing in valobj and type because the valobj is fixed (and is used for ObjC discovery and bitfield size)
629 // but the type can change (e.g. stripping pointers, ...)
630 bool Get (ValueObject& valobj,
631 ClangASTType clang_type,
633 lldb::DynamicValueType use_dynamic,
636 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
638 if (Get_Impl (valobj, clang_type, entry, use_dynamic, reason))
641 // try going to the unqualified type
644 log->Printf("[Get] trying the unqualified type");
645 if (!clang_type.IsValid())
648 ClangASTType unqual_clang_ast_type = clang_type.GetFullyUnqualifiedType();
649 if (!unqual_clang_ast_type.IsValid())
652 log->Printf("[Get] could not get the unqual_clang_ast_type");
655 if (unqual_clang_ast_type.GetOpaqueQualType() != clang_type.GetOpaqueQualType())
658 log->Printf("[Get] unqualified type is there and is not the same, let's try");
659 if (Get_Impl (valobj, unqual_clang_ast_type,entry, use_dynamic, reason))
663 log->Printf("[Get] unqualified type same as original type");
666 // if all else fails, go to static type
667 if (valobj.IsDynamic())
670 log->Printf("[Get] going to static value");
671 lldb::ValueObjectSP static_value_sp(valobj.GetStaticValue());
675 log->Printf("[Get] has a static value - actually use it");
676 if (Get(*static_value_sp.get(), static_value_sp->GetClangType(), entry, use_dynamic, reason))
678 reason |= lldb_private::eFormatterChoiceCriterionWentToStaticValue;
688 } // namespace lldb_private
690 #endif // lldb_FormatNavigator_h_