From 600f4438bb8e729535c335b0083ba67bb788f3a2 Mon Sep 17 00:00:00 2001
From: Przemyslaw Gorszkowski <pgorszkowski@gmail.com>
Date: Wed, 27 Feb 2013 07:40:55 +0100
Subject: [PATCH] C++: performance improvement for template instantiation

Add cache for instantiated instantiations in base template class.

Change-Id: I5c457ea4dfeab72cc3910f0092ca1bc14b8aa1ac
Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com>
---
 src/libs/cplusplus/LookupContext.cpp | 11 +++++++++--
 src/libs/cplusplus/LookupContext.h   |  1 +
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp
index ef259bb2545..4562d41346f 100644
--- a/src/libs/cplusplus/LookupContext.cpp
+++ b/src/libs/cplusplus/LookupContext.cpp
@@ -749,6 +749,7 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespac
         return 0;
 
     ClassOrNamespace *reference = it->second;
+    ClassOrNamespace *baseTemplateClassReference = reference;
 
     const TemplateNameId *templId = name->asTemplateNameId();
     if (templId) {
@@ -764,7 +765,8 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespac
         if (templId->isSpecialization()) {
             // if it is a specialization we try to find or create new one and
             // add to base class(reference)
-            TemplateNameIdTable::const_iterator cit = reference->_specializations.find(templId);
+            TemplateNameIdTable::const_iterator cit
+                    = reference->_specializations.find(templId);
             if (cit != reference->_specializations.end()) {
                 return cit->second;
             } else {
@@ -776,6 +778,10 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespac
                 return newSpecialization;
             }
         } else {
+            QMap<const TemplateNameId *, ClassOrNamespace *>::const_iterator citInstantiation
+                    = reference->_instantiations.find(templId);
+            if (citInstantiation != reference->_instantiations.end())
+                return citInstantiation.value();
             TemplateNameId *nonConstTemplId = const_cast<TemplateNameId *>(templId);
             // make this instantiation looks like specialization which help to find
             // full specialization for this instantiation
@@ -833,7 +839,7 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespac
     // construct all instantiation data.
     if (templId) {
         _alreadyConsideredTemplates.insert(templId);
-        ClassOrNamespace *instantiation = _factory->allocClassOrNamespace(reference);
+        ClassOrNamespace *instantiation = _factory->allocClassOrNamespace(baseTemplateClassReference);
 #ifdef DEBUG_LOOKUP
         instantiation->_name = templId;
 #endif // DEBUG_LOOKUP
@@ -960,6 +966,7 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespac
         }
 
         _alreadyConsideredTemplates.clear(templId);
+        baseTemplateClassReference->_instantiations[templId] = instantiation;
         return instantiation;
     }
 
diff --git a/src/libs/cplusplus/LookupContext.h b/src/libs/cplusplus/LookupContext.h
index 87efcefbb70..88506c1e8f9 100644
--- a/src/libs/cplusplus/LookupContext.h
+++ b/src/libs/cplusplus/LookupContext.h
@@ -113,6 +113,7 @@ private:
     QList<Symbol *> _todo;
     QSharedPointer<Control> _control;
     TemplateNameIdTable _specializations;
+    QMap<const TemplateNameId *, ClassOrNamespace *> _instantiations;
 
     // it's an instantiation.
     const TemplateNameId *_templateId;
-- 
GitLab