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 7331d5a0477..e7ba33287a9 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 @@ -112,6 +112,12 @@ public abstract class AST2TestBase extends SemanticTestBase { return true; } }, + STDCPP17 { + @Override + public boolean isUseGNUExtensions() { + return false; + } + }, STDCPP20 { @Override public boolean isUseGNUExtensions() { @@ -128,6 +134,7 @@ public abstract class AST2TestBase extends SemanticTestBase { private static final ScannerInfo GNU_SCANNER_INFO = new ScannerInfo(getGnuMap()); private static final ScannerInfo SCANNER_INFO = new ScannerInfo(getStdMap()); + private static final ScannerInfo STDCPP17_SCANNER_INFO = new ScannerInfo(getStdCpp17Map()); private static final ScannerInfo STDCPP20_SCANNER_INFO = new ScannerInfo(getStdCpp20Map()); private static Map getGnuMap() { @@ -154,10 +161,18 @@ public abstract class AST2TestBase extends SemanticTestBase { return map; } - private static Map getStdCpp20Map() { + private static Map getStdCpp17Map() { Map map = getStdMap(); + map.put("__cpp_deduction_guides", "201703L"); + return map; + } + + private static Map getStdCpp20Map() { + Map map = getStdCpp17Map(); map.put("__cpp_impl_three_way_comparison", "201907L"); map.put("__cpp_char8_t", "201811L"); + // TODO: C++20 features + //map.put("__cpp_deduction_guides", "201907L"); return map; } @@ -241,6 +256,8 @@ public abstract class AST2TestBase extends SemanticTestBase { switch (scannerKind) { case GNU: return GNU_SCANNER_INFO; + case STDCPP17: + return STDCPP17_SCANNER_INFO; case STDCPP20: return STDCPP20_SCANNER_INFO; case STD: diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/cxx17/DeductionGuideTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/cxx17/DeductionGuideTest.java new file mode 100644 index 00000000000..bf8b545a576 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/cxx17/DeductionGuideTest.java @@ -0,0 +1,190 @@ +/******************************************************************************* + * Copyright (c) 2023 Igor V. Kovalenko. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Igor V. Kovalenko - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.core.parser.tests.ast2.cxx17; + +import static org.eclipse.cdt.core.parser.tests.ast2.CommonCPPTypes.char_; +import static org.eclipse.cdt.core.parser.tests.ast2.CommonCPPTypes.double_; +import static org.eclipse.cdt.core.parser.tests.ast2.CommonCPPTypes.int_; + +import org.eclipse.cdt.core.dom.ast.IPointerType; +import org.eclipse.cdt.core.dom.ast.IProblemType; +import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.IVariable; +import org.eclipse.cdt.core.parser.ParserLanguage; +import org.eclipse.cdt.core.parser.tests.ast2.AST2CPPTestBase; + +/** + * AST tests for C++17 deduction guides. + */ +public class DeductionGuideTest extends AST2CPPTestBase { + + // template struct S { + // template S(S s) : value(s.value) {} + // S(T v) : value(v) {} + // T value; + // }; + // + // //template S(T t) -> S; + // template S(char) -> S; // invalid candidate, T cannot be deduced + // S(int) -> S; + // + // void f() { + // auto dchar = S('1').value; + // auto dint = S(1).value; + // double dv = S(1).value; + // int iv = S(1).value; + // + // auto sdouble = S(); + // auto ddouble = S(1); + // + // S copy = ddouble; + // S init{ddouble}; + // S convert(ddouble); + // } + public void testDeductionGuideBasic() throws Exception { + BindingAssertionHelper bh = getAssertionHelper(ParserLanguage.CPP, ScannerKind.STDCPP17); + assertType(bh.assertNonProblem("dchar = S", 5), char_); + assertType(bh.assertNonProblem("dint = S", 4), double_); + assertType(bh.assertNonProblem("dv = S", 2), double_); + assertType(bh.assertNonProblem("iv = S", 2), int_); + + IVariable varDouble = bh.assertNonProblem("sdouble = S", 7); + assertType(bh.assertNonProblem("ddouble = S", 7), varDouble.getType()); + + assertType(bh.assertNonProblem("copy = ddouble", 4), varDouble.getType()); + + assertType(bh.assertNonProblem("init{", 4), varDouble.getType()); + + assertType(bh.assertNonProblem("convert(", 7), varDouble.getType()); + } + + // template struct S { + // S(T v) : value(v) {} + // T value; + // }; + // + // //template S(T t) -> S; + // template S(char) -> S; + // S(int) -> S; + // + // void f() { + // auto dchar = S('1').value; + // auto dint = S(1).value; + // double dv = S(1).value; + // int iv = S(1).value; + // } + public void testDeductionGuideWithDefaultTemplateArg() throws Exception { + BindingAssertionHelper bh = getAssertionHelper(ParserLanguage.CPP, ScannerKind.STDCPP17); + assertType(bh.assertNonProblem("dchar = S", 5), char_); + assertType(bh.assertNonProblem("dint = S", 4), double_); + assertType(bh.assertNonProblem("dv = S", 2), double_); + assertType(bh.assertNonProblem("iv = S", 2), int_); + } + + // template struct S; // No definition + // + // S(char) -> S; + // S(int) -> S; + // + // void f() { + // auto schar = S(); + // auto dchar = S('1'); + // auto sdouble = S(); + // auto ddouble = S(1); + // S copy = ddouble; + // S init{ddouble}; + // S convert(ddouble); + // } + public void testDeductionGuideWithTemplateDeclaration() throws Exception { + BindingAssertionHelper bh = getAssertionHelper(ParserLanguage.CPP, ScannerKind.STDCPP17); + + IVariable varChar = bh.assertNonProblem("schar = S", 5); + assertType(bh.assertNonProblem("dchar = S", 5), varChar.getType()); + + IVariable varDouble = bh.assertNonProblem("sdouble = S", 7); + assertType(bh.assertNonProblem("ddouble = S", 7), varDouble.getType()); + + assertType(bh.assertNonProblem("copy = ddouble", 4), varDouble.getType()); + + assertType(bh.assertNonProblem("init{", 4), varDouble.getType()); + + assertType(bh.assertNonProblem("convert(", 7), varDouble.getType()); + } + + // template + // struct UniquePtr + // { + // UniquePtr(T* t); + // }; + // + // UniquePtr dp{new auto(2.0)}; + // auto da = dp; + public void testMinimal() throws Exception { + parseAndCheckBindings(ScannerKind.STDCPP17); + } + + // template struct S { + // S(); + // }; + // + // S sInt; + // + // S s1; + // + // S() -> S; + // + // S s2; + public void testDeduceFromEmptyInitializer() throws Exception { + BindingAssertionHelper bh = getAssertionHelper(ParserLanguage.CPP, ScannerKind.STDCPP17); + IVariable varSInt = bh.assertNonProblem("sInt", 4); + bh.assertProblem("S s1", 1); + bh.assertNonProblem("S s2", 1); + assertType(bh.assertNonProblem("s2", 2), varSInt.getType()); + } + + // template + // struct S + // { + // S(T t); + // template S(U u); + // }; + // + // S(char c) -> S; + // S(int i) -> S; + // + // auto v = S(1); + public void testViaFunctionSetFromConstructors() throws Exception { + parseAndCheckBindings(ScannerKind.STDCPP17); + } + + // template struct S{}; + // + // S* pointer; + public void testNoDeductionForPointer() throws Exception { + BindingAssertionHelper bh = getAssertionHelper(ParserLanguage.CPP, ScannerKind.STDCPP17); + IType pointedType = ((IPointerType) ((IVariable) bh.assertNonProblem("pointer")).getType()).getType(); + assertTrue(pointedType instanceof IProblemType); + bh.assertProblem("S*", 1); + } + + // template struct S; + // + // S* pointer; + public void testNoDeductionForPointerNoDefinition() throws Exception { + BindingAssertionHelper bh = getAssertionHelper(ParserLanguage.CPP, ScannerKind.STDCPP17); + IType pointedType = ((IPointerType) ((IVariable) bh.assertNonProblem("pointer")).getType()).getType(); + assertTrue(pointedType instanceof IProblemType); + bh.assertProblem("S*", 1); + } +} diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexDeductionGuideTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexDeductionGuideTest.java new file mode 100644 index 00000000000..2baa4231d82 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexDeductionGuideTest.java @@ -0,0 +1,139 @@ +/******************************************************************************* + * Copyright (c) 2023 Igor V. Kovalenko. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Igor V. Kovalenko - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.index.tests; + +import static org.eclipse.cdt.core.parser.tests.ast2.CommonCPPTypes.char_; +import static org.eclipse.cdt.core.parser.tests.ast2.CommonCPPTypes.double_; +import static org.eclipse.cdt.core.parser.tests.ast2.CommonCPPTypes.int_; + +import org.eclipse.cdt.core.dom.ast.IVariable; +import org.eclipse.cdt.core.testplugin.TestScannerProvider; + +import junit.framework.TestSuite; + +/** + * AST tests for C++17 deduction guides via PDOM. + */ +public abstract class IndexDeductionGuideTest extends IndexBindingResolutionTestBase { + private static void cxx17SetUp() { + // Enable deduction guides via C++17 feature detection macro + TestScannerProvider.sDefinedSymbols.put("__cpp_deduction_guides", "201703L"); + } + + private static void cxx17TearDown() { + TestScannerProvider.clear(); + } + + public class Cxx17ReferencedProject extends ReferencedProject { + public Cxx17ReferencedProject() { + super(true /* cpp */); + } + + @Override + public void setUp() throws Exception { + cxx17SetUp(); + super.setUp(); + } + + @Override + public void tearDown() throws Exception { + super.tearDown(); + cxx17TearDown(); + } + } + + public class Cxx17SinglePDOMTestStrategy extends SinglePDOMTestStrategy { + public Cxx17SinglePDOMTestStrategy() { + super(true /* cpp */); + } + + @Override + public void setUp() throws Exception { + cxx17SetUp(); + super.setUp(); + } + + @Override + public void tearDown() throws Exception { + super.tearDown(); + cxx17TearDown(); + } + } + + public static class IndexDeductionGuideTestSingleProject extends IndexDeductionGuideTest { + public IndexDeductionGuideTestSingleProject() { + setStrategy(new Cxx17SinglePDOMTestStrategy()); + } + + public static TestSuite suite() { + return suite(IndexDeductionGuideTestSingleProject.class); + } + } + + public static class IndexDeductionGuideTestProjectWithDepProj extends IndexDeductionGuideTest { + public IndexDeductionGuideTestProjectWithDepProj() { + setStrategy(new Cxx17ReferencedProject()); + } + + public static TestSuite suite() { + return suite(IndexDeductionGuideTestProjectWithDepProj.class); + } + } + + public static void addTests(TestSuite suite) { + suite.addTest(IndexDeductionGuideTestSingleProject.suite()); + suite.addTest(IndexDeductionGuideTestProjectWithDepProj.suite()); + } + + // template struct S { + // template S(S s) : value(s.value) {} + // S(T v) : value(v) {} + // T value; + // }; + // + // //template S(T t) -> S; + // template S(char) -> S; // invalid candidate, T cannot be deduced + // S(int) -> S; + + // void f() { + // auto dchar = S('1').value; + // auto dint = S(1).value; + // double dv = S(1).value; + // int iv = S(1).value; + // + // auto sdouble = S(); + // auto ddouble = S(1); + // + // S copy = ddouble; + // S init{ddouble}; + // S convert(ddouble); + // } + // + // constexpr size_t value = sizeof(ddouble.value); + public void testDeductionGuideBasicHeader() throws Exception { + assertType(getBindingFromASTName("dchar = S", 5), char_); + assertType(getBindingFromASTName("dint = S", 4), double_); + assertType(getBindingFromASTName("dv = S", 2), double_); + assertType(getBindingFromASTName("iv = S", 2), int_); + + IVariable varDouble = (IVariable) getBindingFromASTName("sdouble = S", 7); + assertType(getBindingFromASTName("ddouble = S", 7), varDouble.getType()); + + assertType(getBindingFromASTName("copy = ddouble", 4), varDouble.getType()); + + assertType(getBindingFromASTName("init{", 4), varDouble.getType()); + + assertType(getBindingFromASTName("convert(", 7), varDouble.getType()); + } +}