From d01795d9334a96f0ae3f2b19b689fe9abd7fdf34 Mon Sep 17 00:00:00 2001
From: Roberto Raggi <qtc-committer@nokia.com>
Date: Mon, 9 Feb 2009 17:44:06 +0100
Subject: [PATCH] Reimplemented Type::as*Type() using virtual methods.

---
 src/libs/cplusplus/Icons.cpp                  |   6 +-
 src/libs/cplusplus/OverviewModel.cpp          |   2 +-
 src/libs/cplusplus/ResolveExpression.cpp      |  14 +--
 src/plugins/cppeditor/cppeditor.cpp           |   6 +-
 src/plugins/cppeditor/cpphoverhandler.cpp     |   8 +-
 src/plugins/cpptools/cppcodecompletion.cpp    |  40 +++----
 src/plugins/designer/workbenchintegration.cpp |   6 +-
 src/shared/cplusplus/CheckDeclaration.cpp     |  13 +-
 src/shared/cplusplus/CheckDeclarator.cpp      |   7 +-
 src/shared/cplusplus/CheckExpression.cpp      |   2 +-
 src/shared/cplusplus/CoreTypes.h              |  48 ++++++++
 src/shared/cplusplus/Symbols.cpp              |   8 +-
 src/shared/cplusplus/Symbols.h                |  24 ++++
 src/shared/cplusplus/Type.cpp                 | 113 +++---------------
 src/shared/cplusplus/Type.h                   |  59 +++++----
 15 files changed, 175 insertions(+), 181 deletions(-)

diff --git a/src/libs/cplusplus/Icons.cpp b/src/libs/cplusplus/Icons.cpp
index e0b50903c39..8626088052f 100644
--- a/src/libs/cplusplus/Icons.cpp
+++ b/src/libs/cplusplus/Icons.cpp
@@ -63,11 +63,13 @@ Icons::Icons()
 
 QIcon Icons::iconForSymbol(const Symbol *symbol) const
 {
-    if (symbol->isFunction() || (symbol->isDeclaration() && symbol->type()->isFunction()))
+    FullySpecifiedType symbolType = symbol->type();
+    if (symbol->isFunction() || (symbol->isDeclaration() && symbolType &&
+                                 symbolType->isFunctionType()))
     {
         const Function *function = symbol->asFunction();
         if (!function)
-            function = symbol->type()->asFunction();
+            function = symbol->type()->asFunctionType();
 
         if (function->isSlot()) {
             if (function->isPublic()) {
diff --git a/src/libs/cplusplus/OverviewModel.cpp b/src/libs/cplusplus/OverviewModel.cpp
index fe78cb34332..1bef20f36d3 100644
--- a/src/libs/cplusplus/OverviewModel.cpp
+++ b/src/libs/cplusplus/OverviewModel.cpp
@@ -171,7 +171,7 @@ QVariant OverviewModel::data(const QModelIndex &index, int role) const
         if (! symbol->isScopedSymbol() || symbol->isFunction()) {
             QString type = _overview.prettyType(symbol->type());
             if (! type.isEmpty()) {
-                if (! symbol->type()->isFunction())
+                if (! symbol->type()->isFunctionType())
                     name += QLatin1String(": ");
                 name += type;
             }
diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp
index e6d4d81adce..4f39b8cad22 100644
--- a/src/libs/cplusplus/ResolveExpression.cpp
+++ b/src/libs/cplusplus/ResolveExpression.cpp
@@ -512,7 +512,7 @@ bool ResolveExpression::visit(CallAST *ast)
     _results.clear();
 
     foreach (Result p, baseResults) {
-        if (Function *funTy = p.first->asFunction()) {
+        if (Function *funTy = p.first->asFunctionType()) {
             unsigned minNumberArguments = 0;
             for (; minNumberArguments < funTy->argumentCount(); ++minNumberArguments) {
                 Argument *arg = funTy->argumentAt(minNumberArguments)->asArgument();
@@ -528,7 +528,7 @@ bool ResolveExpression::visit(CallAST *ast)
                 p.first = funTy->returnType();
                 addResult(p);
             }
-        } else if (Class *classTy = p.first->asClass()) {
+        } else if (Class *classTy = p.first->asClassType()) {
             // Constructor call
             p.first = control()->namedType(classTy->name());
             addResult(p);
@@ -566,7 +566,7 @@ bool ResolveExpression::visit(ArrayAccessAST *ast)
                         resolveArrayOperator(p, namedTy, classObject->asClass());
                 foreach (Result r, overloads) {
                     FullySpecifiedType ty = r.first;
-                    Function *funTy = ty->asFunction();
+                    Function *funTy = ty->asFunctionType();
                     if (! funTy)
                         continue;
 
@@ -621,7 +621,7 @@ ResolveExpression::resolveMemberExpression(const QList<Result> &baseResults,
                                                                          classObject->asClass());
                     foreach (Result r, overloads) {
                         FullySpecifiedType ty = r.first;
-                        Function *funTy = ty->asFunction();
+                        Function *funTy = ty->asFunctionType();
                         if (! funTy)
                             continue;
 
@@ -651,7 +651,7 @@ ResolveExpression::resolveMemberExpression(const QList<Result> &baseResults,
 
             if (NamedType *namedTy = ty->asNamedType())
                 results += resolveMember(p, memberName, namedTy);
-            else if (Function *fun = ty->asFunction()) {
+            else if (Function *fun = ty->asFunctionType()) {
                 if (fun->scope()->isBlockScope() || fun->scope()->isNamespaceScope()) {
                     ty = fun->returnType();
 
@@ -849,7 +849,7 @@ QList<Symbol *> ResolveClass::resolveClass(NamedType *namedTy,
             resolvedSymbols.append(klass);
         } else if (candidate->isTypedef()) {
             if (Declaration *decl = candidate->asDeclaration()) {
-                if (Class *asClass = decl->type()->asClass()) {
+                if (Class *asClass = decl->type()->asClassType()) {
                     // typedef struct { } Point;
                     // Point pt;
                     // pt.
@@ -863,7 +863,7 @@ QList<Symbol *> ResolveClass::resolveClass(NamedType *namedTy,
                 }
             }
         } else if (Declaration *decl = candidate->asDeclaration()) {
-            if (Function *funTy = decl->type()->asFunction()) {
+            if (Function *funTy = decl->type()->asFunctionType()) {
                 // QString foo("ciao");
                 // foo.
                 if (funTy->scope()->isBlockScope() || funTy->scope()->isNamespaceScope()) {
diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp
index ab38af3772b..b0eb63ffe35 100644
--- a/src/plugins/cppeditor/cppeditor.cpp
+++ b/src/plugins/cppeditor/cppeditor.cpp
@@ -424,7 +424,7 @@ static bool isCompatible(Name *name, Name *otherName)
 
 static bool isCompatible(Function *definition, Symbol *declaration, QualifiedNameId *declarationName)
 {
-    Function *declTy = declaration->type()->asFunction();
+    Function *declTy = declaration->type()->asFunctionType();
     if (! declTy)
         return false;
 
@@ -507,7 +507,7 @@ void CPPEditor::switchDeclarationDefinition()
 
         if (declaration)
             openEditorAt(declaration);
-    } else if (lastSymbol->type()->isFunction()) {
+    } else if (lastSymbol->type()->isFunctionType()) {
         if (Symbol *def = findDefinition(lastSymbol))
             openEditorAt(def);
     }
@@ -594,7 +594,7 @@ Symbol *CPPEditor::findDefinition(Symbol *symbol)
     if (symbol->isFunction())
         return 0; // symbol is a function definition.
 
-    Function *funTy = symbol->type()->asFunction();
+    Function *funTy = symbol->type()->asFunctionType();
     if (! funTy)
         return 0; // symbol does not have function type.
 
diff --git a/src/plugins/cppeditor/cpphoverhandler.cpp b/src/plugins/cppeditor/cpphoverhandler.cpp
index b814ed291aa..3959d953f92 100644
--- a/src/plugins/cppeditor/cpphoverhandler.cpp
+++ b/src/plugins/cppeditor/cpphoverhandler.cpp
@@ -147,13 +147,13 @@ static QString buildHelpId(const FullySpecifiedType &type,
     Name *name = 0;
     Scope *scope = 0;
 
-    if (const Function *f = type->asFunction()) {
+    if (const Function *f = type->asFunctionType()) {
         name = f->name();
         scope = f->scope();
-    } else if (const Class *c = type->asClass()) {
+    } else if (const Class *c = type->asClassType()) {
         name = c->name();
         scope = c->scope();
-    } else if (const Enum *e = type->asEnum()) {
+    } else if (const Enum *e = type->asEnumType()) {
         name = e->name();
         scope = e->scope();
     } else if (const NamedType *t = type->asNamedType()) {
@@ -270,7 +270,7 @@ void CppHoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, in
             m_helpId = buildHelpId(docType, symbol);
             QString displayName = buildHelpId(firstType, symbol);
 
-            if (!firstType->isClass() && !firstType->isNamedType()) {
+            if (!firstType->isClassType() && !firstType->isNamedType()) {
                 Overview overview;
                 overview.setShowArgumentNames(true);
                 overview.setShowReturnTypes(true);
diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp
index 40b73996183..c1dc1e0ddb2 100644
--- a/src/plugins/cpptools/cppcodecompletion.cpp
+++ b/src/plugins/cpptools/cppcodecompletion.cpp
@@ -512,7 +512,7 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
             context = typeOfExpression.lookupContext();
         }
 
-        if (! resolvedTypes.isEmpty()) {
+        if (! resolvedTypes.isEmpty() && resolvedTypes.first().first) {
             FullySpecifiedType exprTy = resolvedTypes.first().first;
 
             if (exprTy->isReferenceType())
@@ -549,9 +549,9 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
 
             // If it's a class, add completions for the constructors
             foreach (const TypeOfExpression::Result &result, results) {
-                if (result.first->isClass()) {
+                if (result.first->isClassType()) {
                     FullySpecifiedType exprTy = result.first;
-                    if (completeConstructors(exprTy->asClass()))
+                    if (completeConstructors(exprTy->asClassType()))
                         return m_startPosition;
                     break;
                 }
@@ -567,7 +567,7 @@ bool CppCodeCompletion::completeFunction(FullySpecifiedType exprTy,
                                          const QList<TypeOfExpression::Result> &resolvedTypes,
                                          const LookupContext &)
 {
-    if (Class *klass = exprTy->asClass()) {
+    if (Class *klass = exprTy->asClassType()) {
         completeConstructors(klass);
     } else {
         ConvertToCompletionItem toCompletionItem(this);
@@ -578,7 +578,7 @@ bool CppCodeCompletion::completeFunction(FullySpecifiedType exprTy,
         QSet<QString> signatures;
         foreach (TypeOfExpression::Result p, resolvedTypes) {
             FullySpecifiedType ty = p.first;
-            if (Function *fun = ty->asFunction()) {
+            if (Function *fun = ty->asFunctionType()) {
                 if (TextEditor::CompletionItem item = toCompletionItem(fun)) {
                     QString signature;
                     signature += overview.prettyName(fun->name());
@@ -612,7 +612,7 @@ bool CppCodeCompletion::completeMember(const QList<TypeOfExpression::Result> &re
         if (ReferenceType *refTy = ty->asReferenceType())
             ty = refTy->elementType();
 
-        if (Class *classTy = ty->asClass()) {
+        if (Class *classTy = ty->asClassType()) {
             Symbol *symbol = result.second;
             if (symbol && ! symbol->isClass())
                 classObjectCandidates.append(classTy);
@@ -641,7 +641,7 @@ bool CppCodeCompletion::completeMember(const QList<TypeOfExpression::Result> &re
 
                 foreach (TypeOfExpression::Result r, overloads) {
                     FullySpecifiedType ty = r.first;
-                    Function *funTy = ty->asFunction();
+                    Function *funTy = ty->asFunctionType();
                     if (! funTy)
                         continue;
 
@@ -674,7 +674,7 @@ bool CppCodeCompletion::completeMember(const QList<TypeOfExpression::Result> &re
                     if (! classObjectCandidates.contains(c))
                         classObjectCandidates.append(c);
                 }
-            } else if (Class *classTy = ptrTy->elementType()->asClass()) {
+            } else if (Class *classTy = ptrTy->elementType()->asClassType()) {
                 // typedef struct { int x } *Ptr;
                 // Ptr p;
                 // p->
@@ -715,14 +715,14 @@ bool CppCodeCompletion::completeMember(const QList<TypeOfExpression::Result> &re
                 ++m_startPosition;
                 namedTy = ptrTy->elementType()->asNamedType();
             }
-        } else if (Class *classTy = ty->asClass()) {
+        } else if (Class *classTy = ty->asClassType()) {
             Symbol *symbol = result.second;
             if (symbol && ! symbol->isClass())
                 classObjectCandidates.append(classTy);
         } else {
             namedTy = ty->asNamedType();
             if (! namedTy) {
-                Function *fun = ty->asFunction();
+                Function *fun = ty->asFunctionType();
                 if (fun && (fun->scope()->isBlockScope() || fun->scope()->isNamespaceScope()))
                     namedTy = fun->returnType()->asNamedType();
             }
@@ -759,24 +759,24 @@ bool CppCodeCompletion::completeScope(const QList<TypeOfExpression::Result> &res
     foreach (result, results) {
         FullySpecifiedType ty = result.first;
 
-        if (ty->isClass() || ty->isNamespace())
+        if (ty->isClassType() || ty->isNamespaceType())
             break;
     }
 
     FullySpecifiedType exprTy = result.first;
     if (! exprTy) {
         return false;
-    } else if (exprTy->asNamespace()) {
+    } else if (exprTy->isNamespaceType()) {
         QList<Symbol *> candidates;
         foreach (TypeOfExpression::Result p, results) {
-            if (Namespace *ns = p.first->asNamespace())
+            if (Namespace *ns = p.first->asNamespaceType())
                 candidates.append(ns);
         }
         completeNamespace(candidates, context);
-    } else if (exprTy->isClass()) {
+    } else if (exprTy->isClassType()) {
         QList<Symbol *> candidates;
         foreach (TypeOfExpression::Result p, results) {
-            if (Class *k = p.first->asClass())
+            if (Class *k = p.first->asClassType())
                 candidates.append(k);
         }
         completeClass(candidates, context);
@@ -896,7 +896,7 @@ bool CppCodeCompletion::completeConstructors(Class *klass)
 
     for (unsigned i = 0; i < klass->memberCount(); ++i) {
         Symbol *member = klass->memberAt(i);
-        if (! member->type()->isFunction())
+        if (! member->type()->isFunctionType())
             continue;
         else if (! member->identity())
             continue;
@@ -959,7 +959,7 @@ bool CppCodeCompletion::completeQtMethod(CPlusPlus::FullySpecifiedType,
 
             for (unsigned i = 0; i < scope->symbolCount(); ++i) {
                 Symbol *member = scope->symbolAt(i);
-                Function *fun = member->type()->asFunction();
+                Function *fun = member->type()->asFunctionType();
                 if (! fun)
                     continue;
                 if (wantSignals && ! fun->isSignal())
@@ -1075,7 +1075,7 @@ void CppCodeCompletion::complete(const TextEditor::CompletionItem &item)
 
     if (m_completionOperator == T_LPAREN) {
         if (symbol) {
-            Function *function = symbol->type()->asFunction();
+            Function *function = symbol->type()->asFunctionType();
             QTC_ASSERT(function, return);
 
             m_functionArgumentWidget = new FunctionArgumentWidget();
@@ -1094,8 +1094,8 @@ void CppCodeCompletion::complete(const TextEditor::CompletionItem &item)
         //qDebug() << "current symbol:" << overview.prettyName(symbol->name())
         //<< overview.prettyType(symbol->type());
 
-        if (m_autoInsertBraces && symbol) {
-            if (Function *function = symbol->type()->asFunction()) {
+        if (m_autoInsertBraces && symbol && symbol->type()) {
+            if (Function *function = symbol->type()->asFunctionType()) {
                 // If the member is a function, automatically place the opening parenthesis,
                 // except when it might take template parameters.
                 const bool hasReturnType = function->returnType().isValid()  ||
diff --git a/src/plugins/designer/workbenchintegration.cpp b/src/plugins/designer/workbenchintegration.cpp
index bb657999ca4..20f8520e755 100644
--- a/src/plugins/designer/workbenchintegration.cpp
+++ b/src/plugins/designer/workbenchintegration.cpp
@@ -195,7 +195,7 @@ static const Function *findDeclaration(const Class *cl, const QString &functionN
     const Overview overview;
     for (unsigned j = 0; j < mCount; j++) { // go through all members
         if (const Declaration *decl = cl->memberAt(j)->asDeclaration())
-            if (const Function *fun = decl->type()->asFunction()) {
+            if (const Function *fun = decl->type()->asFunctionType()) {
                 // Format signature
                 QString memberFunction = overview.prettyName(fun->name());
                 memberFunction += QLatin1Char('(');
@@ -233,7 +233,7 @@ static bool isCompatible(const Name *name, const Name *otherName)
 // TODO: remove me, see below
 static bool isCompatible(const Function *definition, const Symbol *declaration, const QualifiedNameId *declarationName)
 {
-    Function *declTy = declaration->type()->asFunction();
+    Function *declTy = declaration->type()->asFunctionType();
     if (! declTy)
         return false;
 
@@ -385,7 +385,7 @@ static void addDeclaration(const QString &docFileName, const Class *cl, const QS
     const unsigned mCount = cl->memberCount();
     for (unsigned j = 0; j < mCount; j++) { // go through all members
         if (const Declaration *decl = cl->memberAt(j)->asDeclaration())
-            if (const Function *fun = decl->type()->asFunction())  {
+            if (const Function *fun = decl->type()->asFunctionType())  {
                 // we are only interested in declarations of methods.
                 // fun->column() returns always 0, what can cause trouble in case in one
                 // line if there is: "private slots: void foo();"
diff --git a/src/shared/cplusplus/CheckDeclaration.cpp b/src/shared/cplusplus/CheckDeclaration.cpp
index 179dd069879..ee9e80ffa66 100644
--- a/src/shared/cplusplus/CheckDeclaration.cpp
+++ b/src/shared/cplusplus/CheckDeclaration.cpp
@@ -130,8 +130,8 @@ bool CheckDeclaration::visit(SimpleDeclarationAST *ast)
     FullySpecifiedType ty = semantic()->check(ast->decl_specifier_seq, _scope);
     FullySpecifiedType qualTy = ty.qualifiedType();
 
-    if (_templateParameters) {
-        if (Class *klass = ty->asClass()) {
+    if (_templateParameters && ty) {
+        if (Class *klass = ty->asClassType()) {
             klass->setTemplateParameters(_templateParameters);
         }
     }
@@ -142,7 +142,8 @@ bool CheckDeclaration::visit(SimpleDeclarationAST *ast)
         FullySpecifiedType declTy = semantic()->check(it->declarator, qualTy,
                                                       _scope, &name);
 
-        if (Function *fun = declTy->asFunction()) {
+        Function *fun = 0;
+        if (declTy && 0 != (fun = declTy->asFunctionType())) {
             fun->setScope(_scope);
             fun->setName(name);
             fun->setMethodKey(semantic()->currentMethodKey());
@@ -162,7 +163,7 @@ bool CheckDeclaration::visit(SimpleDeclarationAST *ast)
         symbol->setType(control()->integerType(IntegerType::Int));
         symbol->setType(declTy);
 
-        if (_templateParameters && it == ast->declarators && ! ty->asClass())
+        if (_templateParameters && it == ast->declarators && ty && ! ty->isClassType())
             symbol->setTemplateParameters(_templateParameters);
 
         symbol->setVisibility(semantic()->currentVisibility());
@@ -225,13 +226,13 @@ bool CheckDeclaration::visit(FunctionDefinitionAST *ast)
     Name *name = 0;
     FullySpecifiedType funTy = semantic()->check(ast->declarator, qualTy,
                                                  _scope, &name);
-    Function *fun = funTy->asFunction();
-    if (! fun) {
+    if (! (funTy && funTy->isFunctionType())) {
         translationUnit()->error(ast->firstToken(),
                                  "expected a function prototype");
         return false;
     }
 
+    Function *fun = funTy->asFunctionType();
     fun->setName(name);
     fun->setTemplateParameters(_templateParameters);
     fun->setVisibility(semantic()->currentVisibility());
diff --git a/src/shared/cplusplus/CheckDeclarator.cpp b/src/shared/cplusplus/CheckDeclarator.cpp
index beb2ed0bca7..169a9f5d81f 100644
--- a/src/shared/cplusplus/CheckDeclarator.cpp
+++ b/src/shared/cplusplus/CheckDeclarator.cpp
@@ -135,9 +135,12 @@ bool CheckDeclarator::visit(DeclaratorAST *ast)
     // ### check the initializer
     // FullySpecifiedType exprTy = semantic()->check(ast->initializer, _scope);
 
-    if (ast->initializer && _fullySpecifiedType->isFunction()) {
-        _fullySpecifiedType->asFunction()->setPureVirtual(true);
+    if (ast->initializer && _fullySpecifiedType) {
+        if (Function *funTy = _fullySpecifiedType->asFunctionType()) {
+            funTy->setPureVirtual(true);
+        }
     }
+
     return false;
 }
 
diff --git a/src/shared/cplusplus/CheckExpression.cpp b/src/shared/cplusplus/CheckExpression.cpp
index e546a99a539..726a113a8e2 100644
--- a/src/shared/cplusplus/CheckExpression.cpp
+++ b/src/shared/cplusplus/CheckExpression.cpp
@@ -319,7 +319,7 @@ bool CheckExpression::visit(QtMethodAST *ast)
     Scope dummy;
     FullySpecifiedType methTy = semantic()->check(ast->declarator, FullySpecifiedType(),
                                                   &dummy, &name);
-    Function *fty = methTy->asFunction();
+    Function *fty = methTy->asFunctionType();
     if (! fty)
         translationUnit()->warning(ast->firstToken(), "expected a function declarator");
     else {
diff --git a/src/shared/cplusplus/CoreTypes.h b/src/shared/cplusplus/CoreTypes.h
index c3c04618385..42895f4dba3 100644
--- a/src/shared/cplusplus/CoreTypes.h
+++ b/src/shared/cplusplus/CoreTypes.h
@@ -66,6 +66,12 @@ class CPLUSPLUS_EXPORT VoidType: public Type
 public:
     virtual bool isEqualTo(const Type *other) const;
 
+    virtual const VoidType *asVoidType() const
+    { return this; }
+
+    virtual VoidType *asVoidType()
+    { return this; }
+
 protected:
     virtual void accept0(TypeVisitor *visitor);
 };
@@ -91,6 +97,12 @@ public:
 
     virtual bool isEqualTo(const Type *other) const;
 
+    virtual IntegerType *asIntegerType()
+    { return this; }
+
+    virtual const IntegerType *asIntegerType() const
+    { return this; }
+
 protected:
     virtual void accept0(TypeVisitor *visitor);
 
@@ -115,6 +127,12 @@ public:
 
     virtual bool isEqualTo(const Type *other) const;
 
+    virtual const FloatType *asFloatType() const
+    { return this; }
+
+    virtual FloatType *asFloatType()
+    { return this; }
+
 protected:
     virtual void accept0(TypeVisitor *visitor);
 
@@ -132,6 +150,12 @@ public:
 
     virtual bool isEqualTo(const Type *other) const;
 
+    virtual const PointerType *asPointerType() const
+    { return this; }
+
+    virtual PointerType *asPointerType()
+    { return this; }
+
 protected:
     virtual void accept0(TypeVisitor *visitor);
 
@@ -150,6 +174,12 @@ public:
 
     virtual bool isEqualTo(const Type *other) const;
 
+    virtual const PointerToMemberType *asPointerToMemberType() const
+    { return this; }
+
+    virtual PointerToMemberType *asPointerToMemberType()
+    { return this; }
+
 protected:
     virtual void accept0(TypeVisitor *visitor);
 
@@ -168,6 +198,12 @@ public:
 
     virtual bool isEqualTo(const Type *other) const;
 
+    virtual const ReferenceType *asReferenceType() const
+    { return this; }
+
+    virtual ReferenceType *asReferenceType()
+    { return this; }
+
 protected:
     virtual void accept0(TypeVisitor *visitor);
 
@@ -186,6 +222,12 @@ public:
 
     virtual bool isEqualTo(const Type *other) const;
 
+    virtual const ArrayType *asArrayType() const
+    { return this; }
+
+    virtual ArrayType *asArrayType()
+    { return this; }
+
 protected:
     virtual void accept0(TypeVisitor *visitor);
 
@@ -204,6 +246,12 @@ public:
 
     virtual bool isEqualTo(const Type *other) const;
 
+    virtual const NamedType *asNamedType() const
+    { return this; }
+
+    virtual NamedType *asNamedType()
+    { return this; }
+
 protected:
     virtual void accept0(TypeVisitor *visitor);
 
diff --git a/src/shared/cplusplus/Symbols.cpp b/src/shared/cplusplus/Symbols.cpp
index a7ed4682ffe..6fae11453bf 100644
--- a/src/shared/cplusplus/Symbols.cpp
+++ b/src/shared/cplusplus/Symbols.cpp
@@ -188,7 +188,7 @@ void Function::setTemplateParameters(Scope *templateParameters)
 
 bool Function::isEqualTo(const Type *other) const
 {
-    const Function *o = other->asFunction();
+    const Function *o = other->asFunctionType();
     if (! o)
         return false;
     Name *l = identity();
@@ -323,7 +323,7 @@ FullySpecifiedType Enum::type() const
 
 bool Enum::isEqualTo(const Type *other) const
 {
-    const Enum *o = other->asEnum();
+    const Enum *o = other->asEnumType();
     if (! o)
         return false;
     Name *l = identity();
@@ -356,7 +356,7 @@ Namespace::~Namespace()
 
 bool Namespace::isEqualTo(const Type *other) const
 {
-    const Namespace *o = other->asNamespace();
+    const Namespace *o = other->asNamespaceType();
     if (! o)
         return false;
     Name *l = identity();
@@ -458,7 +458,7 @@ FullySpecifiedType Class::type() const
 
 bool Class::isEqualTo(const Type *other) const
 {
-    const Class *o = other->asClass();
+    const Class *o = other->asClassType();
     if (! o)
         return false;
     Name *l = identity();
diff --git a/src/shared/cplusplus/Symbols.h b/src/shared/cplusplus/Symbols.h
index c7b3e924b4f..2153b55393e 100644
--- a/src/shared/cplusplus/Symbols.h
+++ b/src/shared/cplusplus/Symbols.h
@@ -217,6 +217,12 @@ public:
     virtual Enum *asEnum()
     { return this; }
 
+    virtual const Enum *asEnumType() const
+    { return this; }
+
+    virtual Enum *asEnumType()
+    { return this; }
+
 protected:
     virtual void visitSymbol0(SymbolVisitor *visitor);
     virtual void accept0(TypeVisitor *visitor);
@@ -278,6 +284,12 @@ public:
     virtual Function *asFunction()
     { return this; }
 
+    virtual const Function *asFunctionType() const
+    { return this; }
+
+    virtual Function *asFunctionType()
+    { return this; }
+
 protected:
     virtual void visitSymbol0(SymbolVisitor *visitor);
     virtual void accept0(TypeVisitor *visitor);
@@ -318,6 +330,12 @@ public:
     virtual Namespace *asNamespace()
     { return this; }
 
+    virtual const Namespace *asNamespaceType() const
+    { return this; }
+
+    virtual Namespace *asNamespaceType()
+    { return this; }
+
 protected:
     virtual void visitSymbol0(SymbolVisitor *visitor);
     virtual void accept0(TypeVisitor *visitor);
@@ -388,6 +406,12 @@ public:
     virtual Class *asClass()
     { return this; }
 
+    virtual const Class *asClassType() const
+    { return this; }
+
+    virtual Class *asClassType()
+    { return this; }
+
 protected:
     virtual void visitSymbol0(SymbolVisitor *visitor);
     virtual void accept0(TypeVisitor *visitor);
diff --git a/src/shared/cplusplus/Type.cpp b/src/shared/cplusplus/Type.cpp
index 98ccd3c893f..52d51b57bdb 100644
--- a/src/shared/cplusplus/Type.cpp
+++ b/src/shared/cplusplus/Type.cpp
@@ -64,121 +64,40 @@ Type::~Type()
 { }
 
 bool Type::isVoidType() const
-{ return dynamic_cast<const VoidType *>(this) != 0; }
+{ return asVoidType() != 0; }
 
 bool Type::isIntegerType() const
-{ return dynamic_cast<const IntegerType *>(this) != 0; }
+{ return asIntegerType() != 0; }
 
 bool Type::isFloatType() const
-{ return dynamic_cast<const FloatType *>(this) != 0; }
+{ return asFloatType() != 0; }
 
 bool Type::isPointerType() const
-{ return dynamic_cast<const PointerType *>(this) != 0; }
+{ return asPointerType()  != 0; }
 
 bool Type::isPointerToMemberType() const
-{ return dynamic_cast<const PointerToMemberType *>(this) != 0; }
+{ return asPointerToMemberType() != 0; }
 
 bool Type::isReferenceType() const
-{ return dynamic_cast<const ReferenceType *>(this) != 0; }
+{ return asReferenceType() != 0; }
 
 bool Type::isArrayType() const
-{ return dynamic_cast<const ArrayType *>(this) != 0; }
+{ return asArrayType() != 0; }
 
 bool Type::isNamedType() const
-{ return dynamic_cast<const NamedType *>(this) != 0; }
+{ return asNamedType() != 0; }
 
-bool Type::isFunction() const
-{ return dynamic_cast<const Function *>(this) != 0; }
+bool Type::isFunctionType() const
+{ return asFunctionType() != 0; }
 
-bool Type::isNamespace() const
-{ return dynamic_cast<const Namespace *>(this) != 0; }
+bool Type::isNamespaceType() const
+{ return asNamespaceType() != 0; }
 
-bool Type::isClass() const
-{ return dynamic_cast<const Class *>(this) != 0; }
+bool Type::isClassType() const
+{ return asClassType() != 0; }
 
-bool Type::isEnum() const
-{ return dynamic_cast<const Enum *>(this) != 0; }
-
-bool Type::isScopedSymbol() const
-{ return dynamic_cast<const ScopedSymbol *>(this) != 0; }
-
-const VoidType *Type::asVoidType() const
-{ return dynamic_cast<const VoidType *>(this); }
-
-const IntegerType *Type::asIntegerType() const
-{ return dynamic_cast<const IntegerType *>(this); }
-
-const FloatType *Type::asFloatType() const
-{ return dynamic_cast<const FloatType *>(this); }
-
-const PointerType *Type::asPointerType() const
-{ return dynamic_cast<const PointerType *>(this); }
-
-const PointerToMemberType *Type::asPointerToMemberType() const
-{ return dynamic_cast<const PointerToMemberType *>(this); }
-
-const ReferenceType *Type::asReferenceType() const
-{ return dynamic_cast<const ReferenceType *>(this); }
-
-const ArrayType *Type::asArrayType() const
-{ return dynamic_cast<const ArrayType *>(this); }
-
-const NamedType *Type::asNamedType() const
-{ return dynamic_cast<const NamedType *>(this); }
-
-const Function *Type::asFunction() const
-{ return dynamic_cast<const Function *>(this); }
-
-const Namespace *Type::asNamespace() const
-{ return dynamic_cast<const Namespace *>(this); }
-
-const Class *Type::asClass() const
-{ return dynamic_cast<const Class *>(this); }
-
-const Enum *Type::asEnum() const
-{ return dynamic_cast<const Enum *>(this); }
-
-const ScopedSymbol *Type::asScopedSymbol() const
-{ return dynamic_cast<const ScopedSymbol *>(this); }
-
-VoidType *Type::asVoidType()
-{ return dynamic_cast<VoidType *>(this); }
-
-IntegerType *Type::asIntegerType()
-{ return dynamic_cast<IntegerType *>(this); }
-
-FloatType *Type::asFloatType()
-{ return dynamic_cast<FloatType *>(this); }
-
-PointerType *Type::asPointerType()
-{ return dynamic_cast<PointerType *>(this); }
-
-PointerToMemberType *Type::asPointerToMemberType()
-{ return dynamic_cast<PointerToMemberType *>(this); }
-
-ReferenceType *Type::asReferenceType()
-{ return dynamic_cast<ReferenceType *>(this); }
-
-ArrayType *Type::asArrayType()
-{ return dynamic_cast<ArrayType *>(this); }
-
-NamedType *Type::asNamedType()
-{ return dynamic_cast<NamedType *>(this); }
-
-Function *Type::asFunction()
-{ return dynamic_cast<Function *>(this); }
-
-Namespace *Type::asNamespace()
-{ return dynamic_cast<Namespace *>(this); }
-
-Class *Type::asClass()
-{ return dynamic_cast<Class *>(this); }
-
-Enum *Type::asEnum()
-{ return dynamic_cast<Enum *>(this); }
-
-ScopedSymbol *Type::asScopedSymbol()
-{ return dynamic_cast<ScopedSymbol *>(this); }
+bool Type::isEnumType() const
+{ return asEnumType() != 0; }
 
 void Type::accept(TypeVisitor *visitor)
 {
diff --git a/src/shared/cplusplus/Type.h b/src/shared/cplusplus/Type.h
index 7cc347d5532..dd22c982c24 100644
--- a/src/shared/cplusplus/Type.h
+++ b/src/shared/cplusplus/Type.h
@@ -75,39 +75,36 @@ public:
     bool isReferenceType() const;
     bool isArrayType() const;
     bool isNamedType() const;
-    bool isFunction() const;
-    bool isNamespace() const;
-    bool isClass() const;
-    bool isEnum() const;
-    bool isScopedSymbol() const;
+    bool isFunctionType() const;
+    bool isNamespaceType() const;
+    bool isClassType() const;
+    bool isEnumType() const;
 
-    const VoidType *asVoidType() const;
-    const IntegerType *asIntegerType() const;
-    const FloatType *asFloatType() const;
-    const PointerType *asPointerType() const;
-    const PointerToMemberType *asPointerToMemberType() const;
-    const ReferenceType *asReferenceType() const;
-    const ArrayType *asArrayType() const;
-    const NamedType *asNamedType() const;
-    const Function *asFunction() const;
-    const Namespace *asNamespace() const;
-    const Class *asClass() const;
-    const Enum *asEnum() const;
-    const ScopedSymbol *asScopedSymbol() const;
+    virtual const VoidType *asVoidType() const { return 0; }
+    virtual const IntegerType *asIntegerType() const { return 0; }
+    virtual const FloatType *asFloatType() const { return 0; }
+    virtual const PointerType *asPointerType() const { return 0; }
+    virtual const PointerToMemberType *asPointerToMemberType() const { return 0; }
+    virtual const ReferenceType *asReferenceType() const { return 0; }
+    virtual const ArrayType *asArrayType() const { return 0; }
+    virtual const NamedType *asNamedType() const { return 0; }
+    virtual const Function *asFunctionType() const { return 0; }
+    virtual const Namespace *asNamespaceType() const { return 0; }
+    virtual const Class *asClassType() const { return 0; }
+    virtual const Enum *asEnumType() const { return 0; }
 
-    VoidType *asVoidType();
-    IntegerType *asIntegerType();
-    FloatType *asFloatType();
-    PointerType *asPointerType();
-    PointerToMemberType *asPointerToMemberType();
-    ReferenceType *asReferenceType();
-    ArrayType *asArrayType();
-    NamedType *asNamedType();
-    Function *asFunction();
-    Namespace *asNamespace();
-    Class *asClass();
-    Enum *asEnum();
-    ScopedSymbol *asScopedSymbol();
+    virtual VoidType *asVoidType() { return 0; }
+    virtual IntegerType *asIntegerType() { return 0; }
+    virtual FloatType *asFloatType() { return 0; }
+    virtual PointerType *asPointerType() { return 0; }
+    virtual PointerToMemberType *asPointerToMemberType() { return 0; }
+    virtual ReferenceType *asReferenceType() { return 0; }
+    virtual ArrayType *asArrayType() { return 0; }
+    virtual NamedType *asNamedType() { return 0; }
+    virtual Function *asFunctionType() { return 0; }
+    virtual Namespace *asNamespaceType() { return 0; }
+    virtual Class *asClassType() { return 0; }
+    virtual Enum *asEnumType() { return 0; }
 
     void accept(TypeVisitor *visitor);
     static void accept(Type *type, TypeVisitor *visitor);
-- 
GitLab