Not yet, but I will try to reduce one down. The best I have right now is to 
debug clang, set a breakpoint at "Sema::SelectBestMethod" and then run "p Sel" 
when you hit the breakpoint. This is of course only by running with a file:

lldb -- "/tmp/local/clang/install/bin/clang-3.8" -cc1 -triple 
arm64-apple-ios5.0.0 -Wdeprecated-objc-isa-usage 
-Werror=deprecated-objc-isa-usage -Werror=implicit-function-declaration 
-fsyntax-only -disable-free -main-file-name ios10.mi -mrelocation-model pic 
-pic-level 2 -mthread-model posix -mdisable-fp-elim -masm-verbose -target-cpu 
cyclone -target-feature +neon -target-feature +crc -target-feature +crypto 
-target-feature +zcm -target-feature +zcz -target-abi darwinpcs 
-target-linker-version 262.4 -v -dwarf-column-info -resource-dir 
/tmp/local/clang/install/bin/../lib/clang/3.8.0 -fdebug-compilation-dir /tmp 
-ferror-limit 19 -fmessage-length 80 -stack-protector 1 
-fallow-half-arguments-and-returns -fblocks -fobjc-runtime=ios-5.0.0 
-fencode-extended-block-signature -fobjc-exceptions -fexceptions 
-fmax-type-align=16 -fdiagnostics-show-option -fcolor-diagnostics -x 
objective-c-cpp-output ios10.mi

So not a very reduced test case. I will work on getting one in ASAP but I would 
like it to be more self contained and controlled. The expression also takes way 
too long (30-90 seconds) because of the changes that were previously added 
(revision 247746) that parse everything in a decl context. If that proves to be 
what is slowing down expressions, I will need to do something about it as it is 
affecting our expression performance.

So stay tuned, I'll follow up with a test soon.


> On Feb 9, 2016, at 2:48 PM, Zachary Turner <ztur...@google.com> wrote:
> 
> Any tests for this?
> 
> On Tue, Feb 9, 2016 at 2:40 PM Greg Clayton via lldb-commits 
> <lldb-commits@lists.llvm.org> wrote:
> Author: gclayton
> Date: Tue Feb  9 16:36:24 2016
> New Revision: 260308
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=260308&view=rev
> Log:
> Fixed many issues that were causing differing type definition issues to show 
> up when parsing expressions.
> 
> 1) Turns out we weren't correctly uniquing types for C++. We would search our 
> repository for "lldb_private::Process", but yet store just "Process" in the 
> unique type map. Now we store things correctly and correctly unique types.
> 2) SymbolFileDWARF::CompleteType() can be called at any time in order to 
> complete a C++ or Objective C class. All public inquiries into the SymbolFile 
> go through SymbolVendor, and SymbolVendor correctly takes the module lock 
> before it call the SymbolFile API call, but when we let CompilerType objects 
> out in the wild, they can complete themselves at any time from the expression 
> parser, so the ValueObjects or (SBValue objects in the public API), and many 
> more places. So we now take the module lock when completing a type to avoid 
> two threads being in the SymbolFileDWARF at the same time.
> 3) If a class has a template member function like:
> 
>     class A
>     {
>         <template T>
>         void Foo(T t);
>     };
> 
>     The DWARF will _only_ contain a DW_TAG_subprogram for "Foo" if anyone 
> specialized it. This would cause a class definition for A inside a.cpp that 
> used a "int" and "float" overload to look like:
>     class A
>     {
>         void Foo(int t);
>         void Foo(double t);
>     };
> 
>     And a version from b.cpp that used a "float" overload to look like:
>     class A
>     {
>         void Foo(float t);
>     };
> 
>     And a version from c.cpp that use no overloads to look like:
> 
>     class A
>     {
>     };
> 
>     Then in an expression if you have two variables, one name "a" from a.cpp 
> in liba.dylib, and one named "b" from b.cpp in libb.dylib, you will get 
> conflicting definitions for "A" and your expression will fail. This all stems 
> from the fact that DWARF _only_ emits template specializations, not generic 
> definitions, and they are only emitted if they are used. There are two 
> solutions to this:
>     a) When ever you run into ANY class, you must say "just because this 
> class doesn't have templatized member functions, it doesn't mean that any 
> other instances might not have any, so when ever I run into ANY class, I must 
> parse all compile units and parse all instances of class "A" just in case it 
> has member functions that are templatized.". That is really bad because it 
> means you always pull in ALL DWARF that contains most likely exact duplicate 
> definitions of the class "A" and you bloat the memory that the 
> SymbolFileDWARF plug-in uses in LLDB (since you pull in all DIEs from all 
> compile units that contain a "A" definition) uses for little value most of 
> the time.
>     b) Modify DWARF to emit generic template member function definitions so 
> that you know from looking at any instance of class "A" wether it has 
> template member functions or not. In order to do this, we would have to have 
> the ability to correctly parse a member function template, but there is a 
> compiler bug:
>     <rdar://problem/24515533> [PR 26553] C++ Debug info should reference 
> DW_TAG_template_type_parameter
>     This bugs means that not all of the info needed to correctly make a 
> template member function is in the DWARF. The main source of the problem is 
> if we have DWARF for a template instantiation for "int" like: "void 
> A::Foo<int>(T)" the DWARF comes out as "void A::Foo<int>(int)" (it doesn't 
> mention type "T", it resolves the type to the specialized type to "int"). But 
> if you actually have your function defined as "<template T> void Foo(int t)" 
> and you only use T for local variables inside the function call, we can't 
> correctly make the function prototype up in the clang::ASTContext.
> 
>     So the best we can do for now we just omit all member functions that are 
> templatized from the class definition so that "A" never has any template 
> member functions. This means all defintions of "A" look like:
> 
>     class A
>     {
>     };
> 
>     And our expressions will work. You won't be able to call template member 
> fucntions in expressions (not a regression, we weren't able to do this 
> before) and if you are stopped in a templatized member function, we won't 
> know that are are in a method of class "A". All things we should fix, but we 
> need <rdar://problem/24515533> fixed first, followed by:
> 
>     <rdar://problem/24515624> Classes should always include a template 
> subprogram definition, even when no template member functions are used
> 
>     before we can do anything about it in LLDB.
> 
> This bug mainly fixed the following Apple radar:
> 
> <rdar://problem/24483905>
> 
> 
> Modified:
>     lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
>     lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
>     lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
> 
> Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
> URL: 
> http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp?rev=260308&r1=260307&r2=260308&view=diff
> ==============================================================================
> --- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp 
> (original)
> +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp Tue 
> Feb  9 16:36:24 2016
> @@ -555,43 +555,32 @@ DWARFASTParserClang::ParseTypeFromDWARF
>                      // and clang isn't good and sharing the stack space for 
> variables in different blocks.
>                      std::unique_ptr<UniqueDWARFASTType> 
> unique_ast_entry_ap(new UniqueDWARFASTType());
> 
> +                    ConstString unique_typename(type_name_const_str);
> +                    Declaration unique_decl(decl);
> +
>                      if (type_name_const_str)
>                      {
>                          LanguageType die_language = die.GetLanguage();
> -                        bool handled = false;
>                          if (Language::LanguageIsCPlusPlus(die_language))
>                          {
> +                            // For C++, we rely solely upon the one 
> definition rule that says only
> +                            // one thing can exist at a given decl context. 
> We ignore the file and
> +                            // line that things are declared on.
>                              std::string qualified_name;
>                              if (die.GetQualifiedName(qualified_name))
> -                            {
> -                                handled = true;
> -                                ConstString 
> const_qualified_name(qualified_name);
> -                                if 
> (dwarf->GetUniqueDWARFASTTypeMap().Find(const_qualified_name, die, 
> Declaration(),
> -                                                                           
> byte_size_valid ? byte_size : -1,
> -                                                                           
> *unique_ast_entry_ap))
> -                                {
> -                                    type_sp = unique_ast_entry_ap->m_type_sp;
> -                                    if (type_sp)
> -                                    {
> -                                        dwarf->GetDIEToType()[die.GetDIE()] 
> = type_sp.get();
> -                                        return type_sp;
> -                                    }
> -                                }
> -                            }
> +                                unique_typename = 
> ConstString(qualified_name);
> +                            unique_decl.Clear();
>                          }
> 
> -                        if (!handled)
> +                        if 
> (dwarf->GetUniqueDWARFASTTypeMap().Find(unique_typename, die, unique_decl,
> +                                                                   
> byte_size_valid ? byte_size : -1,
> +                                                                   
> *unique_ast_entry_ap))
>                          {
> -                            if 
> (dwarf->GetUniqueDWARFASTTypeMap().Find(type_name_const_str, die, decl,
> -                                                                       
> byte_size_valid ? byte_size : -1,
> -                                                                       
> *unique_ast_entry_ap))
> +                            type_sp = unique_ast_entry_ap->m_type_sp;
> +                            if (type_sp)
>                              {
> -                                type_sp = unique_ast_entry_ap->m_type_sp;
> -                                if (type_sp)
> -                                {
> -                                    dwarf->GetDIEToType()[die.GetDIE()] = 
> type_sp.get();
> -                                    return type_sp;
> -                                }
> +                                dwarf->GetDIEToType()[die.GetDIE()] = 
> type_sp.get();
> +                                return type_sp;
>                              }
>                          }
>                      }
> @@ -822,9 +811,9 @@ DWARFASTParserClang::ParseTypeFromDWARF
>                      // and over in the ASTContext for our module
>                      unique_ast_entry_ap->m_type_sp = type_sp;
>                      unique_ast_entry_ap->m_die = die;
> -                    unique_ast_entry_ap->m_declaration = decl;
> +                    unique_ast_entry_ap->m_declaration = unique_decl;
>                      unique_ast_entry_ap->m_byte_size = byte_size;
> -                    dwarf->GetUniqueDWARFASTTypeMap().Insert 
> (type_name_const_str,
> +                    dwarf->GetUniqueDWARFASTTypeMap().Insert 
> (unique_typename,
>                                                                
> *unique_ast_entry_ap);
> 
>                      if (is_forward_declaration && die.HasChildren())
> @@ -1069,6 +1058,7 @@ DWARFASTParserClang::ParseTypeFromDWARF
>                      bool is_virtual = false;
>                      bool is_explicit = false;
>                      bool is_artificial = false;
> +                    bool has_template_params = false;
>                      DWARFFormValue specification_die_form;
>                      DWARFFormValue abstract_origin_die_form;
>                      dw_offset_t object_pointer_die_offset = 
> DW_INVALID_OFFSET;
> @@ -1193,11 +1183,13 @@ DWARFASTParserClang::ParseTypeFromDWARF
>                      clang::DeclContext *containing_decl_ctx = 
> GetClangDeclContextContainingDIE (die, &decl_ctx_die);
>                      const clang::Decl::Kind containing_decl_kind = 
> containing_decl_ctx->getDeclKind();
> 
> -                    const bool is_cxx_method = DeclKindIsCXXClass 
> (containing_decl_kind);
> +                    bool is_cxx_method = DeclKindIsCXXClass 
> (containing_decl_kind);
>                      // Start off static. This will be set to false in 
> ParseChildParameters(...)
>                      // if we find a "this" parameters as the first parameter
>                      if (is_cxx_method)
> +                    {
>                          is_static = true;
> +                    }
> 
>                      if (die.HasChildren())
>                      {
> @@ -1208,11 +1200,26 @@ DWARFASTParserClang::ParseTypeFromDWARF
>                                                skip_artificial,
>                                                is_static,
>                                                is_variadic,
> +                                              has_template_params,
>                                                function_param_types,
>                                                function_param_decls,
>                                                type_quals);
>                      }
> 
> +                    bool ignore_containing_context = false;
> +                    // Check for templatized class member functions. If we 
> had any DW_TAG_template_type_parameter
> +                    // or DW_TAG_template_value_parameter the 
> DW_TAG_subprogram DIE, then we can't let this become
> +                    // a method in a class. Why? Because templatized 
> functions are only emitted if one of the
> +                    // templatized methods is used in the current compile 
> unit and we will end up with classes
> +                    // that may or may not include these member functions 
> and this means one class won't match another
> +                    // class definition and it affects our ability to use a 
> class in the clang expression parser. So
> +                    // for the greater good, we currently must not allow any 
> template member functions in a class definition.
> +//                    if (is_cxx_method && has_template_params)
> +//                    {
> +//                        ignore_containing_context = true;
> +//                        is_cxx_method = false;
> +//                    }
> +
>                      // clang_type will get the function prototype clang type 
> after this call
>                      clang_type = m_ast.CreateFunctionType (return_clang_type,
>                                                             
> function_param_types.data(),
> @@ -1220,7 +1227,6 @@ DWARFASTParserClang::ParseTypeFromDWARF
>                                                             is_variadic,
>                                                             type_quals);
> 
> -                    bool ignore_containing_context = false;
> 
>                      if (type_name_cstr)
>                      {
> @@ -1980,6 +1986,10 @@ DWARFASTParserClang::CompleteTypeFromDWA
>                                              lldb_private::Type *type,
>                                              CompilerType &clang_type)
>  {
> +    SymbolFileDWARF *dwarf = die.GetDWARF();
> +
> +    lldb_private::Mutex::Locker 
> locker(dwarf->GetObjectFile()->GetModule()->GetMutex());
> +
>      // Disable external storage for this type so we don't get anymore
>      // clang::ExternalASTSource queries for this type.
>      m_ast.SetHasExternalStorage (clang_type.GetOpaqueQualType(), false);
> @@ -1989,8 +1999,6 @@ DWARFASTParserClang::CompleteTypeFromDWA
> 
>      const dw_tag_t tag = die.Tag();
> 
> -    SymbolFileDWARF *dwarf = die.GetDWARF();
> -
>      Log *log = nullptr; // 
> (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO|DWARF_LOG_TYPE_COMPLETION));
>      if (log)
>          dwarf->GetObjectFile()->GetModule()->LogMessageVerboseBacktrace (log,
> @@ -2507,6 +2515,7 @@ DWARFASTParserClang::ParseFunctionFromDW
>                  // never mangled.
>                  bool is_static = false;
>                  bool is_variadic = false;
> +                bool has_template_params = false;
>                  unsigned type_quals = 0;
>                  std::vector<CompilerType> param_types;
>                  std::vector<clang::ParmVarDecl*> param_decls;
> @@ -2523,6 +2532,7 @@ DWARFASTParserClang::ParseFunctionFromDW
>                                       true,
>                                       is_static,
>                                       is_variadic,
> +                                     has_template_params,
>                                       param_types,
>                                       param_decls,
>                                       type_quals);
> @@ -3189,6 +3199,7 @@ DWARFASTParserClang::ParseChildParameter
>                                             bool skip_artificial,
>                                             bool &is_static,
>                                             bool &is_variadic,
> +                                           bool &has_template_params,
>                                             std::vector<CompilerType>& 
> function_param_types,
>                                             std::vector<clang::ParmVarDecl*>& 
> function_param_decls,
>                                             unsigned &type_quals)
> @@ -3347,6 +3358,7 @@ DWARFASTParserClang::ParseChildParameter
>                  // in SymbolFileDWARF::ParseType() so this was removed. If 
> we ever need
>                  // the template params back, we can add them back.
>                  // ParseTemplateDIE (dwarf_cu, die, template_param_infos);
> +                has_template_params = true;
>                  break;
> 
>              default:
> 
> Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
> URL: 
> http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h?rev=260308&r1=260307&r2=260308&view=diff
> ==============================================================================
> --- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h 
> (original)
> +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h Tue Feb  
> 9 16:36:24 2016
> @@ -133,6 +133,7 @@ protected:
>                            bool skip_artificial,
>                            bool &is_static,
>                            bool &is_variadic,
> +                          bool &has_template_params,
>                            std::vector<lldb_private::CompilerType>& 
> function_args,
>                            std::vector<clang::ParmVarDecl*>& 
> function_param_decls,
>                            unsigned &type_quals);
> 
> Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
> URL: 
> http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp?rev=260308&r1=260307&r2=260308&view=diff
> ==============================================================================
> --- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (original)
> +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Tue Feb  9 
> 16:36:24 2016
> @@ -1623,6 +1623,8 @@ SymbolFileDWARF::HasForwardDeclForClangT
>  bool
>  SymbolFileDWARF::CompleteType (CompilerType &compiler_type)
>  {
> +    lldb_private::Mutex::Locker 
> locker(GetObjectFile()->GetModule()->GetMutex());
> +
>      TypeSystem *type_system = compiler_type.GetTypeSystem();
>      if (type_system)
>      {
> 
> 
> _______________________________________________
> lldb-commits mailing list
> lldb-commits@lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to