Modified the expression parser's class wrapper to
support reporting "this" as a templated class.  The
expression parser wraps expressions in C++ methods
as methods with the signature

$__lldb_class::$__lldb_expr(...)

and previously responded to clang's queries about
$__lldb_class with the type of *this.  This didn't
work if *this was a ClassTemplateSpecializationDecl
because ClassTemplateSpecializationDecls can't be
the result of simple name queries.

Instead what we do now is respond that $__lldb_class
is a typedef and that the target of the typedef is
the (potentially templated) type of *this.  That is
much more robust.

Thanks to John McCall for key insights.

<rdar://problem/10987183>

llvm-svn: 174153
diff --git a/lldb/source/Expression/ClangExpressionDeclMap.cpp b/lldb/source/Expression/ClangExpressionDeclMap.cpp
index ce6404d..21fc0fd 100644
--- a/lldb/source/Expression/ClangExpressionDeclMap.cpp
+++ b/lldb/source/Expression/ClangExpressionDeclMap.cpp
@@ -2650,7 +2650,6 @@
             
             if (method_decl)
             {
-            
                 clang::CXXRecordDecl *class_decl = method_decl->getParent();
                 
                 QualType class_qual_type(class_decl->getTypeForDecl(), 0);
@@ -2664,7 +2663,28 @@
                     log->Printf("  CEDM::FEVD[%u] Adding type for $__lldb_class: %s", current_id, ast_dumper.GetCString());
                 }
                 
-                AddOneType(context, class_user_type, current_id, true);
+                TypeFromParser class_type = CopyClassType(class_user_type, current_id);
+                
+                if (!class_type.IsValid())
+                    return;
+                
+                TypeSourceInfo *type_source_info = m_ast_context->CreateTypeSourceInfo(QualType::getFromOpaquePtr(class_type.GetOpaqueQualType()));
+                
+                if (!type_source_info)
+                    return;
+                
+                TypedefDecl *typedef_decl = TypedefDecl::Create(*m_ast_context,
+                                                                m_ast_context->getTranslationUnitDecl(),
+                                                                SourceLocation(),
+                                                                SourceLocation(),
+                                                                context.m_decl_name.getAsIdentifierInfo(),
+                                                                type_source_info);
+                
+                
+                if (!typedef_decl)
+                    return;
+                
+                context.AddNamedDecl(typedef_decl);
                 
                 if (method_decl->isInstance())
                 {
@@ -2715,7 +2735,7 @@
                         
                         TypeFromUser class_user_type (class_type.getAsOpaquePtr(),
                                                         this_type->GetClangAST());
-                        AddOneType(context, class_user_type, current_id, false);
+                        AddOneType(context, class_user_type, current_id);
                                     
                                     
                         TypeFromUser this_user_type(this_type->GetClangFullType(),
@@ -2774,7 +2794,7 @@
                     log->Printf("  FEVD[%u] Adding type for $__lldb_objc_class: %s", current_id, ast_dumper.GetCString());
                 }
                     
-                AddOneType(context, class_user_type, current_id, false);
+                AddOneType(context, class_user_type, current_id);
                                 
                 if (method_decl->isInstanceMethod())
                 {
@@ -2841,7 +2861,7 @@
                         TypeFromUser class_user_type (class_type.getAsOpaquePtr(),
                                                       self_type->GetClangAST());
                         
-                        AddOneType(context, class_user_type, current_id, false);
+                        AddOneType(context, class_user_type, current_id);
                                     
                         TypeFromUser self_user_type(self_type->GetClangFullType(),
                                                     self_type->GetClangAST());
@@ -3605,28 +3625,26 @@
     }
 }
 
-void 
-ClangExpressionDeclMap::AddOneType(NameSearchContext &context, 
-                                   TypeFromUser &ut,
-                                   unsigned int current_id,
-                                   bool add_method)
+TypeFromParser
+ClangExpressionDeclMap::CopyClassType(TypeFromUser &ut,
+                                      unsigned int current_id)
 {
     ASTContext *parser_ast_context = m_ast_context;
     ASTContext *user_ast_context = ut.GetASTContext();
-    
+
     void *copied_type = GuardedCopyType(parser_ast_context, user_ast_context, ut.GetOpaqueQualType());
     
     if (!copied_type)
     {
         lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
-        if (log)
-            log->Printf("ClangExpressionDeclMap::AddOneType - Couldn't import the type");
         
-        return;
+        if (log)
+            log->Printf("ClangExpressionDeclMap::CopyClassType - Couldn't import the type");
+        
+        return TypeFromParser();
     }
-     
-    if (add_method && ClangASTContext::IsAggregateType(copied_type) && ClangASTContext::GetCompleteType (parser_ast_context, copied_type))
+
+    if (ClangASTContext::IsAggregateType(copied_type) && ClangASTContext::GetCompleteType (parser_ast_context, copied_type))
     {
         void *args[1];
         
@@ -3659,5 +3677,28 @@
                                                    is_artificial);
     }
     
+    return TypeFromParser(copied_type, parser_ast_context);
+}
+
+void 
+ClangExpressionDeclMap::AddOneType(NameSearchContext &context, 
+                                   TypeFromUser &ut,
+                                   unsigned int current_id)
+{
+    ASTContext *parser_ast_context = m_ast_context;
+    ASTContext *user_ast_context = ut.GetASTContext();
+    
+    void *copied_type = GuardedCopyType(parser_ast_context, user_ast_context, ut.GetOpaqueQualType());
+    
+    if (!copied_type)
+    {
+        lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+        if (log)
+            log->Printf("ClangExpressionDeclMap::AddOneType - Couldn't import the type");
+        
+        return;
+    }
+    
     context.AddTypeDecl(copied_type);
 }
diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp
index 169a32f..a5c6b1a 100644
--- a/lldb/source/Symbol/ClangASTContext.cpp
+++ b/lldb/source/Symbol/ClangASTContext.cpp
@@ -1309,8 +1309,8 @@
 
     // With templated classes, we say that a class is templated with
     // specializations, but that the bare class has no functions.
-    template_cxx_decl->startDefinition();
-    template_cxx_decl->completeDefinition();
+    //template_cxx_decl->startDefinition();
+    //template_cxx_decl->completeDefinition();
     
     class_template_decl = ClassTemplateDecl::Create (*ast,
                                                      decl_ctx,  // What decl context do we use here? TU? The actual decl context?
@@ -1356,6 +1356,8 @@
                                                                                                                    template_param_infos.args.size(),
                                                                                                                    NULL);
     
+    class_template_specialization_decl->setSpecializationKind(TSK_ExplicitSpecialization);
+    
     return class_template_specialization_decl;
 }