From 66f92bb58277c3cc845249c089b0bf28b9e0312e Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Mon, 16 Jan 2012 15:28:11 +0100 Subject: [PATCH] Bug 368610: Specialization of classes used as template args --- .../parser/tests/ast2/AST2TemplateTests.java | 50 +++++++++++++++++++ .../parser/cpp/semantics/CPPTemplates.java | 30 ++++++++--- 2 files changed, 73 insertions(+), 7 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java index 9d913dd1a9f..57808cc7664 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java @@ -5750,4 +5750,54 @@ public class AST2TemplateTests extends AST2BaseTest { assertEquals("A::iterator_t", ASTTypeUtil.getType(v.getType(), true)); parseAndCheckBindings(); } + + // struct S { + // int x; + // }; + // template struct iterator_base { + // S operator*(); + // }; + // template struct A { + // struct iterator : public iterator_base {}; + // }; + // void test() { + // A::iterator it; + // auto s = *it; + // s.x; // ERROR HERE: "Field 'x' could not be resolved" + // } + public void testSpecializationOfClassType_368610a() throws Exception { + parseAndCheckBindings(); + } + + // struct S { + // int x; + // }; + // template struct iterator_base { + // S operator*(); + // }; + // template struct A { + // template struct iterator : public iterator_base {}; + // }; + // void test() { + // A::iterator it; + // auto s = *it; + // s.x; // ERROR HERE: "Field 'x' could not be resolved" + // } + public void testSpecializationOfClassType_368610b() throws Exception { + parseAndCheckBindings(); + } + + // template class TT> struct CTT { + // int y; + // }; + // template struct CT { + // CTT someFunc(); + // }; + // void test2() { + // CT x; + // x.someFunc().y; + // } + public void testSpecializationOfClassType_368610c() throws Exception { + parseAndCheckBindings(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java index 4d6d2f36d97..8b514346c83 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java @@ -255,19 +255,23 @@ public class CPPTemplates { static IBinding isUsedInClassTemplateScope(ICPPClassTemplate ct, IASTName name) { try { - IScope scope; + IScope scope= null; IASTNode node= name; while (node != null) { - if (node.getPropertyInParent() == IASTFunctionDefinition.DECLARATOR) - break; + if (node.getPropertyInParent() == IASTCompositeTypeSpecifier.TYPE_NAME) + return null; if (node instanceof IASTFunctionDefinition) { name= ASTQueries.findInnermostDeclarator(((IASTFunctionDefinition) node).getDeclarator()).getName().getLastName(); + scope= CPPVisitor.getContainingScope(name); + break; + } + if (node instanceof ICPPASTCompositeTypeSpecifier) { + scope= ((ICPPASTCompositeTypeSpecifier) node).getScope(); break; } node= node.getParent(); } - scope= CPPVisitor.getContainingScope(name); while (scope != null) { if (scope instanceof ISemanticProblem) return null; @@ -1139,6 +1143,12 @@ public class CPPTemplates { } if (within != null && type instanceof IBinding) { + IType unwound= getNestedType(type, TDEF); + if (unwound instanceof ICPPClassType && unwound.isSameType(within.getSpecializedBinding())) { + // Convert (partial) class-templates (specializations) to the more specialized version. + if (within instanceof ICPPClassTemplate || !(unwound instanceof ICPPClassTemplate)) + return within; + } IBinding typeAsBinding= (IBinding) type; IBinding owner= typeAsBinding.getOwner(); if (owner instanceof IType) { @@ -1157,7 +1167,6 @@ public class CPPTemplates { } } - IType unwound= getNestedType(type, TDEF); if (unwound instanceof ICPPTemplateInstance && !(unwound instanceof ICPPDeferredClassInstance)) { // Argument of a class specialization can be a nested class subject to specialization. final ICPPTemplateInstance classInstance = (ICPPTemplateInstance) unwound; @@ -2098,8 +2107,15 @@ public class CPPTemplates { if (param instanceof ICPPTemplateTemplateParameter) { IType t= arg.getTypeValue(); - if (!(t instanceof ICPPTemplateDefinition)) - return null; + while (!(t instanceof ICPPTemplateDefinition)) { + if (t instanceof ICPPClassSpecialization) { + // Undo the effect of specializing a template when the unqualified name + // is used within the template itself. + t= ((ICPPClassSpecialization) t).getSpecializedBinding(); + } else { + return null; + } + } ICPPTemplateParameter[] pParams = null; ICPPTemplateParameter[] aParams = null;