From 9c97d4ae664ed354624029ccf6236815d52a972c Mon Sep 17 00:00:00 2001 From: Sergey Prigogin Date: Thu, 11 Feb 2016 18:30:39 -0800 Subject: [PATCH] Bug 486971 - Name resolution problem with alias template and parameter pack This change solves the example in the bug but I'm not sure if it works properly in other similar cases. Change-Id: I6fb6b0c2501ef1fcd25bb31fae019ec5ec0379f9 --- .../parser/tests/ast2/AST2TemplateTests.java | 38 ++++++++++++++++ .../dom/parser/cpp/InstantiationContext.java | 45 ++++++++++++++++++- .../parser/cpp/semantics/CPPTemplates.java | 23 +++++++++- 3 files changed, 102 insertions(+), 4 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 2432db2a70e..3c43622d98e 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 @@ -7247,6 +7247,44 @@ public class AST2TemplateTests extends AST2TestBase { parseAndCheckBindings(); } + // template + // struct B { + // typedef T type; + // }; + // + // template + // class C {}; + // + // template + // using D = C::type...>; + // + // template + // class Group {}; + // + // template + // D waldo1(Group); + // + // template + // D waldo2(Group, Group); + // + // template + // D waldo3(Group, Group); + // + // template + // D waldo4(Group, Group); + // + // void test() { + // Group one; + // Group two; + // waldo1(two); + // waldo2(one, two); + // waldo3(two, one); + // waldo4(two, two); + // } + public void testAliasTemplate_486971() throws Exception { + parseAndCheckBindings(); + } + // template // struct Struct {}; // diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/InstantiationContext.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/InstantiationContext.java index 906b86ca2cb..3b355b6efd8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/InstantiationContext.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/InstantiationContext.java @@ -27,6 +27,8 @@ public class InstantiationContext { private int packOffset; private final ICPPTypeSpecialization contextTypeSpecialization; private final IASTNode point; + private boolean expandPack; + private boolean packExpanded; /** * @param parameterMap mapping of template parameters to arguments, may be {@code null}. @@ -135,7 +137,7 @@ public class InstantiationContext { } /** - * Returns true if the pack offset is specified. + * Returns {@code true} if the pack offset is specified. */ public final boolean hasPackOffset() { return packOffset != -1; @@ -155,11 +157,50 @@ public class InstantiationContext { this.packOffset = packOffset; } + /** + * Returns {@code true} if a parameter pack should be expanded by substituting individual template + * arguments in place of a template parameter that represents a pack. + */ + public boolean shouldExpandPack() { + return expandPack; + } + + /** + * Sets the flag that indicates that a parameter pack should be expanded by substituting individual + * template arguments in place of a template parameter that represents a pack. + */ + public void setExpandPack(boolean expand) { + this.expandPack = expand; + } + + /** + * Returns {@code true} if individual template argument substitution in place of a template parameter that + * represents a pack actually happened. + */ + public boolean isPackExpanded() { + return packExpanded; + } + + /** + * Indicates that individual template argument substitution in place of a template parameter that + * represents a pack actually happened. + */ + public void setPackExpanded(boolean expanded) { + this.packExpanded = expanded; + } + /** * @see ICPPTemplateParameterMap#getArgument(ICPPTemplateParameter, int) */ public ICPPTemplateArgument getArgument(ICPPTemplateParameter param) { - return parameterMap.getArgument(param, packOffset); + return parameterMap == null ? null : parameterMap.getArgument(param, packOffset); + } + + /** + * @see ICPPTemplateParameterMap#getPackExpansion(ICPPTemplateParameter) + */ + public ICPPTemplateArgument[] getPackExpansion(ICPPTemplateParameter param) { + return parameterMap == null ? null : parameterMap.getPackExpansion(param); } /** 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 ddf1243574a..5d10f94389d 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 @@ -1322,6 +1322,7 @@ public class CPPTemplates { int shift = packSize - 1; ICPPTemplateArgument[] newResult= new ICPPTemplateArgument[args.length + resultShift + shift]; System.arraycopy(result, 0, newResult, 0, i + resultShift); + context.setExpandPack(true); int oldPackOffset = context.getPackOffset(); for (int j= 0; j < packSize; j++) { context.setPackOffset(j); @@ -1334,9 +1335,18 @@ public class CPPTemplates { shift = 0; break; } + if (context.isPackExpanded()) { + IType type = newArg.getTypeValue(); + if (type != null) { + type = new CPPParameterPackType(type); + newArg = new CPPTemplateTypeArgument(type); + } + context.setPackExpanded(false); + } newResult[i + resultShift + j]= newArg; } context.setPackOffset(oldPackOffset); + context.setExpandPack(false); result= newResult; resultShift += shift; continue; @@ -1668,7 +1678,7 @@ public class CPPTemplates { ICPPTemplateArgument arg= null; if (tpar.isParameterPack()) { if (context.hasPackOffset()) { - ICPPTemplateArgument[] args = context.getParameterMap().getPackExpansion(tpar); + ICPPTemplateArgument[] args = context.getPackExpansion(tpar); if (args != null) { if (context.getPackOffset() >= args.length) { return new ProblemBinding(context.getPoint(), IProblemBinding.SEMANTIC_INVALID_TYPE, @@ -1676,9 +1686,18 @@ public class CPPTemplates { } arg= args[context.getPackOffset()]; } + if (context.shouldExpandPack()) { + if (arg != null) { + IType type = arg.getTypeValue(); + if (type instanceof ICPPParameterPackType) { + arg = new CPPTemplateTypeArgument(((ICPPParameterPackType) type).getType()); + context.setPackExpanded(true); + } + } + } } } else { - arg= context.getParameterMap().getArgument(tpar); + arg= context.getArgument(tpar); } if (arg != null) {