summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathan Ridge2013-05-26 21:00:12 (EDT)
committer Sergey Prigogin2013-05-28 00:45:30 (EDT)
commit57260c389d6b25d3e8aceacb93b95e94ff840974 (patch)
treee860c275d7821a0fa1e2b35300130e280fcc7fe8
parent22c6fd0c89093e9152a15d415d0af16fd7a5e146 (diff)
downloadorg.eclipse.cdt-57260c389d6b25d3e8aceacb93b95e94ff840974.zip
org.eclipse.cdt-57260c389d6b25d3e8aceacb93b95e94ff840974.tar.gz
org.eclipse.cdt-57260c389d6b25d3e8aceacb93b95e94ff840974.tar.bz2
Bug 409094 - Incorrect partial ordering of function templatesrefs/changes/64/13164/3
Change-Id: Ia4e56f8662c93810776e88932d0a44358f7d5577 Reviewed-on: https://git.eclipse.org/r/13164 Reviewed-by: Sergey Prigogin <eclipse.sprigogin@gmail.com> IP-Clean: Sergey Prigogin <eclipse.sprigogin@gmail.com> Tested-by: Sergey Prigogin <eclipse.sprigogin@gmail.com>
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java49
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java81
2 files changed, 128 insertions, 2 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 e41264c..47320e7 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
@@ -4503,10 +4503,57 @@ public class AST2TemplateTests extends AST2TestBase {
// int main() {
// foo(0);
// }
- public void testFunctionTemplatePartialOrdering_388805() throws Exception {
+ public void testFunctionTemplateOrdering_388805() throws Exception {
+ parseAndCheckBindings();
+ }
+
+ // template <typename T>
+ // struct identity {
+ // typedef T type;
+ // };
+ //
+ // template <typename T>
+ // void foo(typename identity<T>::type);
+ //
+ // template <typename T>
+ // void foo(T);
+ //
+ // int main() {
+ // foo<int>(0); // ERROR HERE
+ // }
+ public void testFunctionTemplateOrdering_409094a() throws Exception {
parseAndCheckBindings();
}
+ // template <typename T>
+ // struct identity {
+ // typedef T type;
+ // };
+ //
+ // template <typename> struct W;
+ //
+ // template <typename T>
+ // struct A {
+ // typedef typename identity<T>::type type1;
+ // typedef W<type1> type2;
+ // };
+ //
+ // template<typename T>
+ // void foo(typename identity<T>::type);
+ //
+ // template <class T>
+ // void foo(T);
+ //
+ // struct waldo {};
+ //
+ // int main() {
+ // waldo w;
+ // foo<waldo>(w); // ERROR HERE
+ // }
+ public void testFunctionTemplateOrdering_409094b() throws Exception {
+ parseAndCheckBindings();
+ }
+
// template<typename T> class CT {};
// template<int I> class CTI {};
//
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java
index a698a90..fa1f084 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java
@@ -59,6 +59,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTemplateParameter;
+import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer;
import org.eclipse.cdt.internal.core.dom.parser.Value;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerToMemberType;
@@ -70,6 +71,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateTypeArgument;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
+import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownMember;
/**
* Algorithms for deducing template arguments in various contexts.
@@ -425,6 +427,7 @@ public class TemplateArgumentDeduction {
int result= 0;
TemplateArgumentDeduction deduct= new TemplateArgumentDeduction(tmplPars, new CPPTemplateParameterMap(0), new CPPTemplateParameterMap(fnParCount), 0);
IType fnParPack= null;
+ Set<Integer> usedTemplateParIds= new HashSet<Integer>();
for (int j= 0; j < fnArgCount; j++) {
IType par;
if (fnParPack != null) {
@@ -445,18 +448,94 @@ public class TemplateArgumentDeduction {
}
IType arg = fnArgs[j];
+ addReferencedTemplateParameters(par, usedTemplateParIds);
int cmpSpecialized= deduceForPartialOrdering(par, arg, deduct, point);
if (cmpSpecialized < 0)
return cmpSpecialized;
if (cmpSpecialized > 0)
result= cmpSpecialized;
}
- return result;
+ return verifyDeductionForPartialOrdering(tmplPars, usedTemplateParIds, deduct.fDeducedArgs) ? result : -1;
} catch (DOMException e) {
}
return -1;
}
+
+ private static void addReferencedTemplateParameters(IType t, Set<Integer> usedTemplateParIds) {
+ while (true) {
+ if (t instanceof ICPPTemplateParameter) {
+ usedTemplateParIds.add(((ICPPTemplateParameter) t).getParameterID());
+ return;
+ } else if (t instanceof ICPPFunctionType) {
+ final ICPPFunctionType ft = (ICPPFunctionType) t;
+ for (IType par : ft.getParameterTypes())
+ addReferencedTemplateParameters(par, usedTemplateParIds);
+ t = ft.getReturnType();
+ } else if (t instanceof ICPPPointerToMemberType) {
+ ICPPPointerToMemberType ptmt = (ICPPPointerToMemberType) t;
+ addReferencedTemplateParameters(ptmt.getMemberOfClass(), usedTemplateParIds);
+ t = ptmt.getType();
+ } else if (t instanceof ICPPTemplateInstance) {
+ ICPPTemplateInstance inst = (ICPPTemplateInstance) t;
+ for (ICPPTemplateArgument arg : inst.getTemplateArguments()) {
+ if (arg instanceof CPPTemplateTypeArgument)
+ addReferencedTemplateParameters(arg.getTypeValue(), usedTemplateParIds);
+ else
+ addReferencedTemplateParameters(arg.getNonTypeValue(), usedTemplateParIds);
+ }
+ if (inst.getTemplateDefinition() instanceof IType) {
+ t = (IType) inst.getTemplateDefinition();
+ } else {
+ return;
+ }
+ } else if (t instanceof ICPPUnknownMember) {
+ t = ((ICPPUnknownMember) t).getOwnerType();
+ } else if (t instanceof ITypeContainer) {
+ if (t instanceof IArrayType)
+ addReferencedTemplateParameters(((IArrayType) t).getSize(), usedTemplateParIds);
+ t = ((ITypeContainer) t).getType();
+ } else {
+ return;
+ }
+ }
+ }
+ private static void addReferencedTemplateParameters(IValue v, Set<Integer> usedTemplatePars) {
+ if (v != null && v.getEvaluation() instanceof EvalBinding) {
+ IBinding binding = ((EvalBinding) v.getEvaluation()).getBinding();
+ if (binding instanceof ICPPTemplateParameter) {
+ usedTemplatePars.add(((ICPPTemplateParameter) binding).getParameterID());
+ }
+ }
+ }
+
+ /**
+ * 14.8.2.4-11 [temp.deduction.partial]
+ * In most cases, all template parameters must have values in order for deduction to succeed,
+ * but for partial ordering purposes a template parameter may remain without a value provided
+ * it is not used in the types being used for partial ordering.
+ */
+ private static boolean verifyDeductionForPartialOrdering(ICPPTemplateParameter[] pars,
+ Set<Integer> usedParIds, CPPTemplateParameterMap tpMap) {
+ for (ICPPTemplateParameter tpar : pars) {
+ if (usedParIds.contains(tpar.getParameterID())) {
+ if (tpar.isParameterPack()) {
+ ICPPTemplateArgument[] deducedArgs = tpMap.getPackExpansion(tpar);
+ if (deducedArgs != null) {
+ for (ICPPTemplateArgument arg : deducedArgs) {
+ if (arg == null)
+ return false;
+ }
+ }
+ } else {
+ if (tpMap.getArgument(tpar) == null)
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
private static int deduceForPartialOrdering(IType par, IType arg, TemplateArgumentDeduction deduct, IASTNode point) throws DOMException {
par= getNestedType(par, TDEF);
arg= getNestedType(arg, TDEF);