From f74ba9daef50a0b267056c8753819d59621fc000 Mon Sep 17 00:00:00 2001
From: Roberto Raggi <roberto.raggi@nokia.com>
Date: Wed, 11 Aug 2010 13:46:32 +0200
Subject: [PATCH] Introduced CPlusPlus::Template and process the template
 declarations.

---
 src/libs/cplusplus/FindUsages.cpp             |  8 +--
 src/shared/cplusplus/AST.h                    |  4 ++
 .../cplusplus/CPlusPlusForwardDeclarations.h  |  1 +
 src/shared/cplusplus/CheckDeclaration.cpp     | 22 ++++---
 src/shared/cplusplus/Control.cpp              | 46 +++++++--------
 src/shared/cplusplus/Control.h                |  3 +
 src/shared/cplusplus/Scope.cpp                |  2 +-
 src/shared/cplusplus/Symbol.cpp               |  3 +
 src/shared/cplusplus/Symbol.h                 |  5 ++
 src/shared/cplusplus/SymbolVisitor.h          |  1 +
 src/shared/cplusplus/Symbols.cpp              | 57 +++++++++++++++++++
 src/shared/cplusplus/Symbols.h                | 35 ++++++++++++
 src/shared/cplusplus/Type.cpp                 |  3 +
 src/shared/cplusplus/Type.h                   |  3 +
 src/shared/cplusplus/TypeMatcher.cpp          |  8 +++
 src/shared/cplusplus/TypeMatcher.h            |  1 +
 src/shared/cplusplus/TypeVisitor.h            |  1 +
 tests/manual/plain-cplusplus/main.cpp         |  2 +-
 18 files changed, 166 insertions(+), 39 deletions(-)

diff --git a/src/libs/cplusplus/FindUsages.cpp b/src/libs/cplusplus/FindUsages.cpp
index a381bb91b21..ace7692097e 100644
--- a/src/libs/cplusplus/FindUsages.cpp
+++ b/src/libs/cplusplus/FindUsages.cpp
@@ -234,9 +234,7 @@ void FindUsages::checkExpression(unsigned startToken, unsigned endToken, Scope *
     if (! scope)
         scope = _currentScope;
 
-    const QList<LookupItem> results = typeofExpression(expression, scope,
-                                                       TypeOfExpression::Preprocess);
-
+    const QList<LookupItem> results = typeofExpression(expression, scope, TypeOfExpression::Preprocess);
     reportResult(endToken, results);
 }
 
@@ -245,7 +243,9 @@ Scope *FindUsages::switchScope(Scope *scope)
     if (! scope)
         return _currentScope;
 
-    return switchScope(scope);
+    Scope *previousScope = _currentScope;
+    _currentScope = scope;
+    return previousScope;
 }
 
 void FindUsages::statement(StatementAST *ast)
diff --git a/src/shared/cplusplus/AST.h b/src/shared/cplusplus/AST.h
index b1c93cf4331..37dd5bb6909 100644
--- a/src/shared/cplusplus/AST.h
+++ b/src/shared/cplusplus/AST.h
@@ -3084,6 +3084,9 @@ public:
     unsigned greater_token;
     DeclarationAST *declaration;
 
+public: // annotations
+    Template *symbol;
+
 public:
     TemplateDeclarationAST()
         : export_token(0)
@@ -3092,6 +3095,7 @@ public:
         , template_parameter_list(0)
         , greater_token(0)
         , declaration(0)
+        , symbol(0)
     {}
 
     virtual TemplateDeclarationAST *asTemplateDeclaration() { return this; }
diff --git a/src/shared/cplusplus/CPlusPlusForwardDeclarations.h b/src/shared/cplusplus/CPlusPlusForwardDeclarations.h
index 1eeeba68b46..2226d695b7b 100644
--- a/src/shared/cplusplus/CPlusPlusForwardDeclarations.h
+++ b/src/shared/cplusplus/CPlusPlusForwardDeclarations.h
@@ -119,6 +119,7 @@ class TypenameArgument;
 class Function;
 class Namespace;
 class NamespaceAlias;
+class Template;
 class BaseClass;
 class Block;
 class Class;
diff --git a/src/shared/cplusplus/CheckDeclaration.cpp b/src/shared/cplusplus/CheckDeclaration.cpp
index 595d549a48c..607fd75ef33 100644
--- a/src/shared/cplusplus/CheckDeclaration.cpp
+++ b/src/shared/cplusplus/CheckDeclaration.cpp
@@ -447,19 +447,23 @@ bool CheckDeclaration::visit(ParameterDeclarationAST *ast)
 
 bool CheckDeclaration::visit(TemplateDeclarationAST *ast)
 {
-#warning robe process template arguments
-#if 0
-    Scope *scope = new Scope(_scope->owner());
+    Template *templ = control()->newTemplate(ast->firstToken());
+    ast->symbol = templ;
 
     for (DeclarationListAST *param = ast->template_parameter_list; param; param = param->next) {
-       semantic()->check(param->value, scope);
+       semantic()->check(param->value, templ);
     }
 
-    semantic()->check(ast->declaration, _scope,
-                      new TemplateParameters(_templateParameters, scope));
-#else
-    semantic()->check(ast->declaration, _scope);
-#endif
+    semantic()->check(ast->declaration, templ);
+
+    if (Symbol *decl = templ->declaration()) {
+        // propagate the name
+        if (decl->sourceLocation())
+            templ->setSourceLocation(decl->sourceLocation(), translationUnit());
+        templ->setName(decl->name());
+    }
+
+    _scope->addMember(templ);
 
     return false;
 }
diff --git a/src/shared/cplusplus/Control.cpp b/src/shared/cplusplus/Control.cpp
index c2752220dfe..5bdadabba13 100644
--- a/src/shared/cplusplus/Control.cpp
+++ b/src/shared/cplusplus/Control.cpp
@@ -333,40 +333,35 @@ public:
 
     Declaration *newDeclaration(unsigned sourceLocation, const Name *name)
     {
-        Declaration *declaration = new Declaration(translationUnit,
-                                                   sourceLocation, name);
+        Declaration *declaration = new Declaration(translationUnit, sourceLocation, name);
         symbols.push_back(declaration);
         return declaration;
     }
 
     Argument *newArgument(unsigned sourceLocation, const Name *name)
     {
-        Argument *argument = new Argument(translationUnit,
-                                          sourceLocation, name);
+        Argument *argument = new Argument(translationUnit, sourceLocation, name);
         symbols.push_back(argument);
         return argument;
     }
 
     TypenameArgument *newTypenameArgument(unsigned sourceLocation, const Name *name)
     {
-        TypenameArgument *argument = new TypenameArgument(translationUnit,
-                                                          sourceLocation, name);
+        TypenameArgument *argument = new TypenameArgument(translationUnit, sourceLocation, name);
         symbols.push_back(argument);
         return argument;
     }
 
     Function *newFunction(unsigned sourceLocation, const Name *name)
     {
-        Function *function = new Function(translationUnit,
-                                          sourceLocation, name);
+        Function *function = new Function(translationUnit, sourceLocation, name);
         symbols.push_back(function);
         return function;
     }
 
     BaseClass *newBaseClass(unsigned sourceLocation, const Name *name)
     {
-        BaseClass *baseClass = new BaseClass(translationUnit,
-                                             sourceLocation, name);
+        BaseClass *baseClass = new BaseClass(translationUnit, sourceLocation, name);
         symbols.push_back(baseClass);
         return baseClass;
     }
@@ -380,40 +375,42 @@ public:
 
     Class *newClass(unsigned sourceLocation, const Name *name)
     {
-        Class *klass = new Class(translationUnit,
-                                 sourceLocation, name);
+        Class *klass = new Class(translationUnit, sourceLocation, name);
         symbols.push_back(klass);
         return klass;
     }
 
     Namespace *newNamespace(unsigned sourceLocation, const Name *name)
     {
-        Namespace *ns = new Namespace(translationUnit,
-                                      sourceLocation, name);
+        Namespace *ns = new Namespace(translationUnit, sourceLocation, name);
+        symbols.push_back(ns);
+        return ns;
+    }
+
+    Template *newTemplate(unsigned sourceLocation, const Name *name)
+    {
+        Template *ns = new Template(translationUnit, sourceLocation, name);
         symbols.push_back(ns);
         return ns;
     }
 
     NamespaceAlias *newNamespaceAlias(unsigned sourceLocation, const Name *name)
     {
-        NamespaceAlias *ns = new NamespaceAlias(translationUnit,
-                                                sourceLocation, name);
+        NamespaceAlias *ns = new NamespaceAlias(translationUnit, sourceLocation, name);
         symbols.push_back(ns);
         return ns;
     }
 
     UsingNamespaceDirective *newUsingNamespaceDirective(unsigned sourceLocation, const Name *name)
     {
-        UsingNamespaceDirective *u = new UsingNamespaceDirective(translationUnit,
-                                                                 sourceLocation, name);
+        UsingNamespaceDirective *u = new UsingNamespaceDirective(translationUnit, sourceLocation, name);
         symbols.push_back(u);
         return u;
     }
 
     ForwardClassDeclaration *newForwardClassDeclaration(unsigned sourceLocation, const Name *name)
     {
-        ForwardClassDeclaration *c = new ForwardClassDeclaration(translationUnit,
-                                                                 sourceLocation, name);
+        ForwardClassDeclaration *c = new ForwardClassDeclaration(translationUnit, sourceLocation, name);
         symbols.push_back(c);
         return c;
     }
@@ -476,16 +473,14 @@ public:
 
     Enum *newEnum(unsigned sourceLocation, const Name *name)
     {
-        Enum *e = new Enum(translationUnit,
-                           sourceLocation, name);
+        Enum *e = new Enum(translationUnit, sourceLocation, name);
         symbols.push_back(e);
         return e;
     }
 
     UsingDeclaration *newUsingDeclaration(unsigned sourceLocation, const Name *name)
     {
-        UsingDeclaration *u = new UsingDeclaration(translationUnit,
-                                                   sourceLocation, name);
+        UsingDeclaration *u = new UsingDeclaration(translationUnit, sourceLocation, name);
         symbols.push_back(u);
         return u;
     }
@@ -689,6 +684,9 @@ Function *Control::newFunction(unsigned sourceLocation, const Name *name)
 Namespace *Control::newNamespace(unsigned sourceLocation, const Name *name)
 { return d->newNamespace(sourceLocation, name); }
 
+Template *Control::newTemplate(unsigned sourceLocation, const Name *name)
+{ return d->newTemplate(sourceLocation, name); }
+
 NamespaceAlias *Control::newNamespaceAlias(unsigned sourceLocation, const Name *name)
 { return d->newNamespaceAlias(sourceLocation, name); }
 
diff --git a/src/shared/cplusplus/Control.h b/src/shared/cplusplus/Control.h
index bc793da03cf..c5c871a7936 100644
--- a/src/shared/cplusplus/Control.h
+++ b/src/shared/cplusplus/Control.h
@@ -129,6 +129,9 @@ public:
     /// Creates a new Namespace symbol.
     Namespace *newNamespace(unsigned sourceLocation, const Name *name = 0);
 
+    /// Creates a new Template symbol.
+    Template *newTemplate(unsigned sourceLocation, const Name *name = 0);
+
     /// Creates a new Namespace symbol.
     NamespaceAlias *newNamespaceAlias(unsigned sourceLocation, const Name *name = 0);
 
diff --git a/src/shared/cplusplus/Scope.cpp b/src/shared/cplusplus/Scope.cpp
index 0d8f75eeb2f..8d70b7854ae 100644
--- a/src/shared/cplusplus/Scope.cpp
+++ b/src/shared/cplusplus/Scope.cpp
@@ -143,7 +143,7 @@ void SymbolTable::enterSymbol(Symbol *symbol)
         _symbols = reinterpret_cast<Symbol **>(realloc(_symbols, sizeof(Symbol *) * _allocatedSymbols));
     }
 
-    assert(! symbol->_scope || symbol->scope() == this);
+    assert(! symbol->_scope || symbol->scope() == _owner);
     symbol->_index = _symbolCount;
     symbol->_scope = _owner;
     _symbols[_symbolCount] = symbol;
diff --git a/src/shared/cplusplus/Symbol.cpp b/src/shared/cplusplus/Symbol.cpp
index bb63cd96dab..2360e003639 100644
--- a/src/shared/cplusplus/Symbol.cpp
+++ b/src/shared/cplusplus/Symbol.cpp
@@ -347,6 +347,9 @@ bool Symbol::isFunction() const
 bool Symbol::isNamespace() const
 { return asNamespace() != 0; }
 
+bool Symbol::isTemplate() const
+{ return asNamespace() != 0; }
+
 bool Symbol::isClass() const
 { return asClass() != 0; }
 
diff --git a/src/shared/cplusplus/Symbol.h b/src/shared/cplusplus/Symbol.h
index bcd0e7e6953..7b80e5093cf 100644
--- a/src/shared/cplusplus/Symbol.h
+++ b/src/shared/cplusplus/Symbol.h
@@ -168,6 +168,9 @@ public:
     /// Returns true if this Symbol is a Namespace.
     bool isNamespace() const;
 
+    /// Returns true if this Symbol is a Namespace.
+    bool isTemplate() const;
+
     /// Returns true if this Symbol is a Class.
     bool isClass() const;
 
@@ -220,6 +223,7 @@ public:
     virtual const Enum *asEnum() const { return 0; }
     virtual const Function *asFunction() const { return 0; }
     virtual const Namespace *asNamespace() const { return 0; }
+    virtual const Template *asTemplate() const { return 0; }
     virtual const NamespaceAlias *asNamespaceAlias() const { return 0; }
     virtual const Class *asClass() const { return 0; }
     virtual const Block *asBlock() const { return 0; }
@@ -243,6 +247,7 @@ public:
     virtual Enum *asEnum() { return 0; }
     virtual Function *asFunction() { return 0; }
     virtual Namespace *asNamespace() { return 0; }
+    virtual Template *asTemplate() { return 0; }
     virtual NamespaceAlias *asNamespaceAlias() { return 0; }
     virtual Class *asClass() { return 0; }
     virtual Block *asBlock() { return 0; }
diff --git a/src/shared/cplusplus/SymbolVisitor.h b/src/shared/cplusplus/SymbolVisitor.h
index 9e66b459705..a20dd2c8d31 100644
--- a/src/shared/cplusplus/SymbolVisitor.h
+++ b/src/shared/cplusplus/SymbolVisitor.h
@@ -78,6 +78,7 @@ public:
     virtual bool visit(Enum *) { return true; }
     virtual bool visit(Function *) { return true; }
     virtual bool visit(Namespace *) { return true; }
+    virtual bool visit(Template *) { return true; }
     virtual bool visit(Class *) { return true; }
     virtual bool visit(Block *) { return true; }
     virtual bool visit(ForwardClassDeclaration *) { return true; }
diff --git a/src/shared/cplusplus/Symbols.cpp b/src/shared/cplusplus/Symbols.cpp
index f7477a4b140..23f17de6df4 100644
--- a/src/shared/cplusplus/Symbols.cpp
+++ b/src/shared/cplusplus/Symbols.cpp
@@ -430,6 +430,63 @@ void Enum::visitSymbol0(SymbolVisitor *visitor)
     }
 }
 
+Template::Template(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
+    : Scope(translationUnit, sourceLocation, name)
+{ }
+
+Template::~Template()
+{ }
+
+unsigned Template::templateParameterCount() const
+{
+    if (declaration() != 0)
+        return memberCount() - 1;
+
+    return 0;
+}
+
+Symbol *Template::templateParameterAt(unsigned index) const
+{ return memberAt(index); }
+
+Symbol *Template::declaration() const
+{
+    if (isEmpty())
+        return 0;
+
+    if (Symbol *s = memberAt(memberCount() - 1)) {
+        if (s->isClass() || s->isForwardClassDeclaration() ||
+            s->isTemplate() || s->isFunction() || s->isDeclaration())
+            return s;
+    }
+
+    return 0;
+}
+
+FullySpecifiedType Template::type() const
+{ return FullySpecifiedType(const_cast<Template *>(this)); }
+
+bool Template::isEqualTo(const Type *other) const
+{ return other == this; }
+
+void Template::visitSymbol0(SymbolVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+        for (unsigned i = 0; i < memberCount(); ++i) {
+            visitSymbol(memberAt(i), visitor);
+        }
+    }
+}
+
+void Template::accept0(TypeVisitor *visitor)
+{ visitor->visit(this); }
+
+bool Template::matchType0(const Type *otherType, TypeMatcher *matcher) const
+{
+    if (const Template *otherTy = otherType->asTemplateType())
+        return matcher->match(this, otherTy);
+    return false;
+}
+
 Namespace::Namespace(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
     : Scope(translationUnit, sourceLocation, name)
 { }
diff --git a/src/shared/cplusplus/Symbols.h b/src/shared/cplusplus/Symbols.h
index bc2b6b8330c..b3f388f9774 100644
--- a/src/shared/cplusplus/Symbols.h
+++ b/src/shared/cplusplus/Symbols.h
@@ -376,6 +376,41 @@ private:
     };
 };
 
+class CPLUSPLUS_EXPORT Template: public Scope, public Type
+{
+public:
+    Template(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name);
+    virtual ~Template();
+
+    unsigned templateParameterCount() const;
+    Symbol *templateParameterAt(unsigned index) const;
+    Symbol *declaration() const;
+
+    // Symbol's interface
+    virtual FullySpecifiedType type() const;
+
+    // Type's interface
+    virtual bool isEqualTo(const Type *other) const;
+
+    virtual const Template *asTemplate() const
+    { return this; }
+
+    virtual Template *asTemplate()
+    { return this; }
+
+    virtual const Template *asTemplateType() const
+    { return this; }
+
+    virtual Template *asTemplateType()
+    { return this; }
+
+protected:
+    virtual void visitSymbol0(SymbolVisitor *visitor);
+    virtual void accept0(TypeVisitor *visitor);
+    virtual bool matchType0(const Type *otherType, TypeMatcher *matcher) const;
+};
+
+
 class CPLUSPLUS_EXPORT Namespace: public Scope, public Type
 {
 public:
diff --git a/src/shared/cplusplus/Type.cpp b/src/shared/cplusplus/Type.cpp
index 778815d5301..430776c13a9 100644
--- a/src/shared/cplusplus/Type.cpp
+++ b/src/shared/cplusplus/Type.cpp
@@ -92,6 +92,9 @@ bool Type::isFunctionType() const
 bool Type::isNamespaceType() const
 { return asNamespaceType() != 0; }
 
+bool Type::isTemplateType() const
+{ return asTemplateType() != 0; }
+
 bool Type::isClassType() const
 { return asClassType() != 0; }
 
diff --git a/src/shared/cplusplus/Type.h b/src/shared/cplusplus/Type.h
index 8ff7fbd30a6..4c4dcef2426 100644
--- a/src/shared/cplusplus/Type.h
+++ b/src/shared/cplusplus/Type.h
@@ -70,6 +70,7 @@ public:
     bool isNamedType() const;
     bool isFunctionType() const;
     bool isNamespaceType() const;
+    bool isTemplateType() const;
     bool isClassType() const;
     bool isEnumType() const;
     bool isForwardClassDeclarationType() const;
@@ -90,6 +91,7 @@ public:
     virtual const NamedType *asNamedType() const { return 0; }
     virtual const Function *asFunctionType() const { return 0; }
     virtual const Namespace *asNamespaceType() const { return 0; }
+    virtual const Template *asTemplateType() const { return 0; }
     virtual const Class *asClassType() const { return 0; }
     virtual const Enum *asEnumType() const { return 0; }
     virtual const ForwardClassDeclaration *asForwardClassDeclarationType() const { return 0; }
@@ -110,6 +112,7 @@ public:
     virtual NamedType *asNamedType() { return 0; }
     virtual Function *asFunctionType() { return 0; }
     virtual Namespace *asNamespaceType() { return 0; }
+    virtual Template *asTemplateType() { return 0; }
     virtual Class *asClassType() { return 0; }
     virtual Enum *asEnumType() { return 0; }
     virtual ForwardClassDeclaration *asForwardClassDeclarationType() { return 0; }
diff --git a/src/shared/cplusplus/TypeMatcher.cpp b/src/shared/cplusplus/TypeMatcher.cpp
index 4cc1ebd3722..383a265431c 100644
--- a/src/shared/cplusplus/TypeMatcher.cpp
+++ b/src/shared/cplusplus/TypeMatcher.cpp
@@ -174,6 +174,14 @@ bool TypeMatcher::match(const Namespace *type, const Namespace *otherType)
     return true;
 }
 
+bool TypeMatcher::match(const Template *type, const Template *otherType)
+{
+    if (type != otherType)
+        return false;
+
+    return true;
+}
+
 bool TypeMatcher::match(const ForwardClassDeclaration *type, const ForwardClassDeclaration *otherType)
 {
     if (type != otherType)
diff --git a/src/shared/cplusplus/TypeMatcher.h b/src/shared/cplusplus/TypeMatcher.h
index 101269a58b1..513aa7a45e0 100644
--- a/src/shared/cplusplus/TypeMatcher.h
+++ b/src/shared/cplusplus/TypeMatcher.h
@@ -56,6 +56,7 @@ public:
     virtual bool match(const Function *type, const Function *otherType);
     virtual bool match(const Enum *type, const Enum *otherType);
     virtual bool match(const Namespace *type, const Namespace *otherType);
+    virtual bool match(const Template *type, const Template *otherType);
     virtual bool match(const ForwardClassDeclaration *type, const ForwardClassDeclaration *otherType);
     virtual bool match(const Class *type, const Class *otherType);
     virtual bool match(const ObjCClass *type, const ObjCClass *otherType);
diff --git a/src/shared/cplusplus/TypeVisitor.h b/src/shared/cplusplus/TypeVisitor.h
index a4cb7ebf22a..6e43cce0759 100644
--- a/src/shared/cplusplus/TypeVisitor.h
+++ b/src/shared/cplusplus/TypeVisitor.h
@@ -78,6 +78,7 @@ public:
     virtual void visit(NamedType *) {}
     virtual void visit(Function *) {}
     virtual void visit(Namespace *) {}
+    virtual void visit(Template *) {}
     virtual void visit(Class *) {}
     virtual void visit(Enum *) {}
     virtual void visit(ForwardClassDeclaration *) {}
diff --git a/tests/manual/plain-cplusplus/main.cpp b/tests/manual/plain-cplusplus/main.cpp
index 38a9dc28a7e..8a2fedf58e0 100644
--- a/tests/manual/plain-cplusplus/main.cpp
+++ b/tests/manual/plain-cplusplus/main.cpp
@@ -130,7 +130,7 @@ void parse(const char *fileName, const char *source, unsigned size)
         Semantic sem(&unit);
         Namespace *globalNamespace = control.newNamespace(0);
         for (List<DeclarationAST *> *it = ast->declaration_list; it; it = it->next) {
-            sem.check(it->value, globalNamespace->members());
+            sem.check(it->value, globalNamespace);
         }
     }
 }
-- 
GitLab