From 6a9a8d409d3a5103ff8c234abdc4565d24fe5144 Mon Sep 17 00:00:00 2001 From: Michael Uhl Date: Thu, 5 Nov 2020 13:47:17 +0100 Subject: [PATCH] Bug 567217 - template functions with lvalue and rvalue parameters of template tests added. Change-Id: I1fbbb45c6d895505a66ad917b1342365118e28d0 --- .../ast2/AST2TemplateLValueRValueTests.java | 878 ++++++++++++++++++ .../core/parser/tests/ast2/AST2TestBase.java | 13 +- .../semantics/TemplateArgumentDeduction.java | 44 +- 3 files changed, 922 insertions(+), 13 deletions(-) create mode 100644 core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateLValueRValueTests.java diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateLValueRValueTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateLValueRValueTests.java new file mode 100644 index 00000000000..a0598857c48 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateLValueRValueTests.java @@ -0,0 +1,878 @@ +package org.eclipse.cdt.core.parser.tests.ast2; + +import static org.eclipse.cdt.core.parser.ParserLanguage.CPP; + +import java.io.IOException; + +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunction; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunctionInstance; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunctionTemplate; +import org.eclipse.cdt.internal.core.parser.ParserException; + +public class AST2TemplateLValueRValueTests extends AST2CPPTestBase { + + public AST2TemplateLValueRValueTests() { + } + + public AST2TemplateLValueRValueTests(String name) { + super(name); + } + + // class clazz { + // }; + // + // template void demo(C &&cont) + // { + // } + // + // template void demo(C &cont) + // { + // } + // + // clazz getClazz() + // { + // clazz c; + // return c; + // } + // + // void testLValue() + // { + // clazz c; + // demo(c); + // } + // + // void testRValue() + // { + // demo(getClazz()); + // } + public void test_lvalue_rvalue_caller_templateLvalue_templateRvalue_function() throws Exception { + parseAndCheckBindings(); + BindingAssertionHelper helper = getAssertionHelper(); + CPPFunctionTemplate targetLvalue = helper.assertNonProblem("demo(C &cont)", "demo"); + CPPFunctionTemplate targetRvalue = helper.assertNonProblem("demo(C &&cont)", "demo"); + CPPFunctionInstance actualTargetLvalue = helper.assertNonProblem("demo(c)", "demo"); + CPPFunctionInstance actualTargetRvalue = helper.assertNonProblem("demo(getClazz())", "demo"); + assertEquals(targetLvalue, actualTargetLvalue.getTemplateDefinition()); + assertEquals(targetRvalue, actualTargetRvalue.getTemplateDefinition()); + } + + // class clazz { + // }; + // + // typedef clazz clazzz; + // + // template void demo(C &&cont) + // { + // } + // + // template void demo(C &cont) + // { + // } + // + // clazz getClazz() + // { + // clazzz c; + // return c; + // } + // + // void testLValue() + // { + // clazzz c; + // demo(c); + // } + // + // void testRValue() + // { + // demo(getClazz()); + // } + public void test_lvalueTypedef_rvalueTypedef_caller_templateLvalue_templateRvalue_function() throws Exception { + parseAndCheckBindings(); + + BindingAssertionHelper helper = getAssertionHelper(); + CPPFunctionTemplate targetLvalue = helper.assertNonProblem("demo(C &cont)", "demo"); + CPPFunctionTemplate targetRvalue = helper.assertNonProblem("demo(C &&cont)", "demo"); + CPPFunctionInstance actualTargetLvalue = helper.assertNonProblem("demo(c)", "demo"); + CPPFunctionInstance actualTargetRvalue = helper.assertNonProblem("demo(getClazz())", "demo"); + assertEquals(targetLvalue, actualTargetLvalue.getTemplateDefinition()); + assertEquals(targetRvalue, actualTargetRvalue.getTemplateDefinition()); + } + + // class clazz { + // }; + // + // template + // using Ref = C&; + // + // template void demo(C &&cont) + // { + // } + // + // template void demo(Ref cont) + // { + // } + // + // clazz getClazz() + // { + // clazz c; + // return c; + // } + // + // void testLValue() + // { + // clazz c; + // demo(c); + // } + // + // void testRValue() + // { + // demo(getClazz()); + // } + public void test_lvalueTypedefRef_rvalueTypedefRef_caller_templateLvalue_templateRvalue_function() + throws Exception { + parseAndCheckBindings(); + + BindingAssertionHelper helper = getAssertionHelper(); + CPPFunctionTemplate targetLvalue = helper.assertNonProblem("demo(Ref cont)", "demo"); + CPPFunctionTemplate targetRvalue = helper.assertNonProblem("demo(C &&cont)", "demo"); + CPPFunctionInstance actualTargetLvalue = helper.assertNonProblem("demo(c)", "demo"); + CPPFunctionInstance actualTargetRvalue = helper.assertNonProblem("demo(getClazz())", "demo"); + assertEquals(targetLvalue, actualTargetLvalue.getTemplateDefinition()); + assertEquals(targetRvalue, actualTargetRvalue.getTemplateDefinition()); + } + + // class clazz { + // }; + // + // typedef clazz & clazzRef; + // + // template void demo(C &&cont) + // { + // } + // + // template void demo(clazzRef cont) + // { + // } + // + // clazz getClazz() + // { + // clazz c; + // return c; + // } + // + // void testLValue() + // { + // clazz c; + // demo(c); + // } + // + // void testRValue() + // { + // demo(getClazz()); + // } + public void test_lvalueTypedefRef_rvalueTypedefRef_caller_templateTpedefLvalue_templateRvalue_function() + throws Exception { + parseAndCheckBindings(); + + BindingAssertionHelper helper = getAssertionHelper(); + CPPFunctionTemplate targetLvalue = helper.assertNonProblem("demo(clazzRef cont)", "demo"); + CPPFunctionTemplate targetRvalue = helper.assertNonProblem("demo(C &&cont)", "demo"); + CPPFunctionTemplate actualTargetLvalue = helper.assertNonProblem("demo(c)", "demo"); + CPPFunctionInstance actualTargetRvalue = helper.assertNonProblem("demo(getClazz())", "demo"); + assertEquals(targetLvalue, actualTargetLvalue); + assertEquals(targetRvalue, actualTargetRvalue.getTemplateDefinition()); + } + + // template void demo(C &&cont) + // { + // } + // + // template void demo(C &cont) + // { + // } + // + // void demo(int &&cont) + // { + // } + // + // void demo(int &cont) + // { + // } + // + // int main() + // { + // int c; + // demo(c); + // } + public void test_lvalue_rvalue_caller_templateLvalue_templateRvalue_lvalue_function() throws Exception { + parseAndCheckBindings(); + + BindingAssertionHelper helper = getAssertionHelper(); + CPPFunction intendedTarget = helper.assertNonProblem("demo(int &cont)", "demo"); + CPPFunction actualTarget = helper.assertNonProblem("demo(c)", "demo"); + assertEquals(intendedTarget, actualTarget); + } + + // class clazz { + // }; + // + // void demo(clazz &&cont) + // { + // } + // + // void testLValue() + // { + // clazz c; + // demo(c); + // } + public void test_lvalue_caller_rvalue_function() throws Exception { + parseAndCheckBindingsForOneProblem(); + } + + // class clazz { + // }; + // + // void demo(clazz &cont) + // { + // } + // + // void testLValue() + // { + // clazz c; + // demo(c); + // } + public void test_lvalue_caller_lvalue_function() throws Exception { + parseAndCheckBindings(); + } + + // class clazz { + // }; + // + // void demo(clazz &&cont) + // { + // } + // + // void demo(clazz &cont) + // { + // } + // + // + // clazz getClazz() + // { + // clazz c; + // return c; + // } + // + // void testRValue() + // { + // demo(getClazz()); + // } + public void test_rvalue_caller_lvalue_rvalue_function() throws Exception { + parseAndCheckBindings(); + } + + // class clazz { + // }; + // + // template void demo(C &&cont) + // { + // } + // + // void demo(clazz &cont) + // { + // } + // + // void testLValue() + // { + // clazz c; + // demo(c); + // } + public void test_lvalue_caller_templateRvalue_lvalue_function() throws Exception { + parseAndCheckBindings(); + } + + // class clazz { + // }; + // + // template void demo(C &&cont) + // { + // } + // + // void demo(clazz &cont) + // { + // } + // + // clazz getClazz() + // { + // clazz c; + // return c; + // } + // + // void testRValue() + // { + // demo(getClazz()); + // } + public void test_rvalue_caller_templateRvalue_lvalue_function() throws Exception { + parseAndCheckBindings(); + } + + // class clazz { + // }; + // + // void demo(clazz &cont) + // { + // } + // clazz getClazz() + // { + // clazz c; + // return c; + // } + // + // void testRValue() + // { + // demo(getClazz()); + // } + public void test_rvalue_caller_lvalue_function() throws Exception { + parseAndCheckBindingsForOneProblem(); + } + + // class clazz { + // }; + // + // void demo(clazz &&cont) + // { + // } + // clazz getClazz() + // { + // clazz c; + // return c; + // } + // + // void testRValue() + // { + // demo(getClazz()); + // } + public void test_rvalue_caller_rvalue_function() throws Exception { + parseAndCheckBindings(); + } + + // class clazz { + // }; + // + // template void demo(C &cont) + // { + // } + // clazz getClazz() + // { + // clazz c; + // return c; + // } + // + // void testRValue() + // { + // demo(getClazz()); + // } + public void test_rvalue_caller_templateLvalue_function() throws Exception { + parseAndCheckBindingsForOneProblem(); + } + + // class clazz { + // }; + // + // template void demo(C &&cont) + // { + // } + // + // clazz getClazz() + // { + // clazz c; + // return c; + // } + // + // void testRValue() + // { + // demo(getClazz()); + // } + public void test_rvalue_caller_templateRvalue_function() throws Exception { + parseAndCheckBindings(); + } + + // class clazz { + // }; + // + // template void demo(C &&cont) + // { + // } + // + // clazz getClazz() + // { + // clazz c; + // return c; + // } + // + // void testRValue() + // { + // demo(getClazz()); + // } + public void test_templatedRvalue_caller__templateRvalue_lvalue_function() throws Exception { + parseAndCheckBindings(); + } + + // class clazz { + // }; + // + // template void demo(C &&cont) + // { + // } + // + // void demo(clazz &cont) { + // } + // + // void testLValue() + // { + // clazz c; + // demo(c); + // } + public void test_templatedLvalue_caller__templateRvalue_lvalue_function() throws Exception { + parseAndCheckBindingsForProblem(); + } + + // class clazz { + // }; + // + // template void demo(C &cont) + // { + // } + // + // void demo(clazz &cont) { + // } + // + // void testLValue() + // { + // clazz c; + // demo(c); + // } + public void test_lvalue_caller_templateLvalue_lvalue_function() throws Exception { + parseAndCheckBindings(); + } + + // class clazz { + // }; + // + // template void demo(C &cont) + // { + // } + // + // void demo(clazz &cont) { + // } + // + // clazz getClazz() + // { + // clazz c; + // return c; + // } + // + // void testRValue() + // { + // demo(getClazz()); + // } + public void test_rvalue_caller_templateLvalue_lvalue_function() throws Exception { + parseAndCheckBindingsForOneProblem(); + } + + // class clazz { + // }; + // + // template void demo(C &cont) + // { + // } + // + // void demo(clazz &cont) { + // } + // + // clazz getClazz() + // { + // clazz c; + // return c; + // } + // + // void testRValue() + // { + // demo(getClazz()); + // } + public void test_templatedRvalue_caller_templatedLValue_lvalAST2TemplateRValueRValueTestsue_function() + throws Exception { + parseAndCheckBindingsForProblem(); + } + + // class clazz { + // }; + // + // template void demo(C &cont) + // { + // } + // + // void demo(clazz &cont) { + // } + // + // void testRValue() + // { + // clazz c; + // demo(c); + // } + public void test_templatedLvalue_caller_templatedLValue_lvalue_function() throws Exception { + parseAndCheckBindings(); + } + + // class clazz { + // }; + // + // template void demo(C &&cont) + // { + // } + // + // void demo(clazz &&cont) { + // } + // + // void testLValue() + // { + // clazz c; + // demo(c); + // } + public void test_lvalue_caller_templatedRvalue_rvalue_function() throws Exception { + parseAndCheckBindings(); + } + + // class clazz { + // }; + // + // template void demo(C &&cont) + // { + // } + // + // void demo(clazz &&cont) { + // } + // + // clazz getClazz() + // { + // clazz c; + // return c; + // } + // + // void testRValue() + // { + // demo(getClazz()); + // } + public void test_rvalue_caller_templatedRvalue_rvalue_function() throws Exception { + parseAndCheckBindings(); + } + + // class clazz { + // }; + // + // template void demo(C &&cont) + // { + // } + // + // void demo(clazz &&cont) { + // } + // + // clazz getClazz() + // { + // clazz c; + // return c; + // } + // + // void testRValue() + // { + // demo(getClazz()); + // } + public void test_templatedRvalue_caller_templatedRvalue_rvalue_function() throws Exception { + parseAndCheckBindings(); + } + + // class clazz { + // }; + // + // template void demo(C &&cont) + // { + // } + // + // void demo(clazz &&cont) { + // } + // + // void testLValue() + // { + // clazz c; + // demo(c); + // } + public void test_templatedLvalue_caller_templatedRvalue_rvalue_function() throws Exception { + parseAndCheckBindingsForProblem(); + } + + // class clazz { + // }; + // + // template void demo(C &cont) + // { + // } + // + // void demo(clazz &&cont) { + // } + // + // void testLValue() + // { + // clazz c; + // demo(c); + // } + public void test_lvalue_caller_templatedLvalue_rvalue_function() throws Exception { + parseAndCheckBindings(); + } + + // class clazz { + // }; + // + // template void demo(C &cont) + // { + // } + // + // void demo(clazz &&cont) { + // } + // + // clazz getClazz() + // { + // clazz c; + // return c; + // } + // + // void testRValue() + // { + // demo(getClazz()); + // } + public void test_rvalue_caller_templatedLvalue_rvalue_function() throws Exception { + parseAndCheckBindings(); + } + + // class clazz { + // }; + // + // template void demo(C &cont) + // { + // } + // + // void demo(clazz &&cont) { + // } + // + // clazz getClazz() + // { + // clazz c; + // return c; + // } + // + // void testRValue() + // { + // demo(getClazz()); + // } + public void test_templatedRvalue_caller_templatedLvalue_rvalue_function() throws Exception { + parseAndCheckBindingsForProblem(); + } + + // class clazz { + // }; + // + // template void demo(C &cont) + // { + // } + // + // void demo(clazz &&cont) { + // } + // + // void testRValue() + // { + // clazz c; + // demo(c); + // } + public void test_templatedLvalue_caller_templatedLvalue_rvalue_function() throws Exception { + parseAndCheckBindings(); + } + + // class clazz { + // }; + // + // template void demo(C &cont) + // { + // } + // + // template void demo(C &&cont) + // { + // } + // + // void testLValue() + // { + // clazz c; + // demo(c); + // } + public void test_lvalue_caller_templatedLvalue_templatedRvalue_function() throws Exception { + parseAndCheckBindings(); + } + + // class clazz { + // }; + // + // template void demo(C &cont) + // { + // } + // + // template void demo(C &&cont) + // { + // } + // + // clazz getClazz() + // { + // clazz c; + // return c; + // } + // + // void testRValue() + // { + // demo(getClazz()); + // } + public void test_rvalue_caller_templatedLvalue_templatedRvalue_function() throws Exception { + parseAndCheckBindings(); + } + + // class clazz { + // }; + // + // template void demo(C &cont) + // { + // } + // + // template void demo(C &&cont) + // { + // } + // + // clazz getClazz() + // { + // clazz c; + // return c; + // } + // + // void testRValue() + // { + // demo(getClazz()); + // } + public void test_templatedRvalue_caller_templatedLvalue_templatedRvalue_function() throws Exception { + parseAndCheckBindings(); + } + + // class clazz { + // }; + // + // template void demo(C &cont) + // { + // } + // + // template void demo(C &&cont) + // { + // } + // + // void testLValue() + // { + // clazz c; + // demo(c); + // } + public void test_templatedLvalue_caller_templatedLvalue_templatedRvalue_function() throws Exception { + parseAndCheckBindings(); + } + + // class clazz { + // }; + // + // template void demo(C &cont) + // { + // } + // + // clazz getClazz() + // { + // clazz c; + // return c; + // } + // + // void testRValue() + // { + // demo(getClazz()); + // } + public void test_templatedRvalue_caller_templatedLvalue_function() throws Exception { + parseAndCheckBindingsForProblem(); + } + + // class clazz { + // }; + // + // template void demo(C &&cont) + // { + // } + // + // clazz getClazz() + // { + // clazz c; + // return c; + // } + // + // void testRValue() + // { + // demo(getClazz()); + // } + public void test_templatedRvalue_caller_templatedRvalue_function() throws Exception { + parseAndCheckBindings(); + } + + // class clazz { + // }; + // + // template void demo(C &cont) + // { + // } + // + // void testLValue() + // { + // clazz c; + // demo(c); + // } + public void test_templatedLvalue_caller_templatedLvalue_function() throws Exception { + parseAndCheckBindings(); + } + + // class clazz { + // }; + // + // template void demo(C &&cont) + // { + // } + // + // void testLValue() + // { + // clazz c; + // demo(c); + // } + public void test_templatedLvalue_caller_templatedRvalue_function() throws Exception { + parseAndCheckBindingsForProblem(); + } + + private void parseAndCheckBindingsForOneProblem() throws IOException, ParserException { + final String code = getAboveComment(); + IASTTranslationUnit tu = parse(code, CPP, true, false); + NameCollector nc = new NameCollector(); + tu.accept(nc); + assertProblemBindings(nc, 1); + } + + private void parseAndCheckBindingsForProblem() throws IOException, ParserException { + final String code = getAboveComment(); + IASTTranslationUnit tu = parse(code, CPP, true, false); + NameCollector nc = new NameCollector(); + tu.accept(nc); + assertProblemBindings(nc); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TestBase.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TestBase.java index 569c4fbdede..ee0d36b4f8b 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TestBase.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TestBase.java @@ -532,12 +532,23 @@ public class AST2TestBase extends SemanticTestBase { final protected void assertProblemBindings(NameCollector col, int count) { int sum = 0; for (IASTName n : col.nameList) { - if (n.resolveBinding() instanceof IProblemBinding) + if (n.resolveBinding() instanceof IProblemBinding) { ++sum; + } } assertEquals(count, sum); } + final protected void assertProblemBindings(NameCollector col) { + int sum = 0; + for (IASTName n : col.nameList) { + if (n.resolveBinding() instanceof IProblemBinding) { + ++sum; + } + } + assertTrue(sum > 0); + } + final protected T getDeclaration(IASTTranslationUnit tu, int i_decl) { Class tclass; IASTDeclaration[] decls = tu.getDeclarations(); 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 2910f25211b..5a9f4ab9059 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 @@ -572,25 +572,45 @@ public class TemplateArgumentDeduction { return true; } - private static int deduceForPartialOrdering(IType par, IType arg, TemplateArgumentDeduction deduct) + private static int deduceForPartialOrdering(IType parOrig, IType argOrig, TemplateArgumentDeduction deduct) throws DOMException { - par = getNestedType(par, TDEF); - arg = getNestedType(arg, TDEF); + IType parNested = getNestedType(parOrig, TDEF); + IType argNested = getNestedType(argOrig, TDEF); boolean isMoreCVQualified = false; - if (par instanceof ICPPReferenceType && arg instanceof ICPPReferenceType) { - par = getNestedType(par, REF | TDEF); - arg = getNestedType(arg, REF | TDEF); - CVQualifier cvp = getCVQualifier(par); - CVQualifier cva = getCVQualifier(arg); + boolean preferForLValueRef = false; + if (parNested instanceof ICPPReferenceType && argNested instanceof ICPPReferenceType) { + preferForLValueRef = compareRValueRValueTemplateFunctions(parNested, argNested); + parNested = getNestedType(parNested, REF | TDEF); + argNested = getNestedType(argNested, REF | TDEF); + CVQualifier cvp = getCVQualifier(parNested); + CVQualifier cva = getCVQualifier(argNested); isMoreCVQualified = cva.isMoreQualifiedThan(cvp); } - par = getNestedType(par, TDEF | REF | ALLCVQ); - arg = getNestedType(arg, TDEF | REF | ALLCVQ); + parNested = getNestedType(parNested, TDEF | REF | ALLCVQ); + argNested = getNestedType(argNested, TDEF | REF | ALLCVQ); - if (!deduct.fromType(par, arg, false, false)) + if (!deduct.fromType(parNested, argNested, false, false)) return -1; - return isMoreCVQualified ? 1 : 0; + return (isMoreCVQualified || preferForLValueRef) ? 1 : 0; + } + + private static boolean compareRValueRValueTemplateFunctions(final IType f1, final IType f2) { + ICPPReferenceType fstTp = (ICPPReferenceType) f1; + ICPPReferenceType sndTp = (ICPPReferenceType) f2; + + boolean fstRv = fstTp.isRValueReference(); + boolean sndRv = sndTp.isRValueReference(); + + if (fstRv != sndRv) { + return fstRv; + } + + return false; + } + + private static boolean isReferenceType(IType fstSpecP) { + return ICPPReferenceType.class.isAssignableFrom(fstSpecP.getClass()); } /**