Skip to content

Commit a9538a1

Browse files
committed
Add basic support for c++20 concepts and constraints
1 parent 62c1f68 commit a9538a1

File tree

48 files changed

+1479
-51
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+1479
-51
lines changed

core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TestBase.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2004, 2016 IBM Corporation and others.
2+
* Copyright (c) 2004, 2016, 2025 IBM Corporation and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0
@@ -158,6 +158,7 @@ private static Map<String, String> getStdCpp20Map() {
158158
Map<String, String> map = getStdMap();
159159
map.put("__cpp_impl_three_way_comparison", "201907L");
160160
map.put("__cpp_char8_t", "201811L");
161+
map.put("__cpp_concepts", "201907L");
161162
return map;
162163
}
163164

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 Igor V. Kovalenko.
3+
*
4+
* This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* Igor V. Kovalenko - initial API and implementation
13+
*******************************************************************************/
14+
package org.eclipse.cdt.core.parser.tests.ast2.cxx20;
15+
16+
import org.eclipse.cdt.core.parser.tests.ast2.AST2CPPTestBase;
17+
18+
/**
19+
* AST tests for C++20 requires expressions.
20+
*/
21+
public class ConceptsTests extends AST2CPPTestBase {
22+
// template<typename T>
23+
// concept A = true;
24+
//
25+
// template<typename T>
26+
// concept B = A<T>;
27+
//
28+
// template<typename T>
29+
// concept C = requires {
30+
// true;
31+
// };
32+
public void testConceptDefinitionExpressions() throws Exception {
33+
parseAndCheckBindings(ScannerKind.STDCPP20);
34+
}
35+
36+
// template<typename T>
37+
// void x() requires true;
38+
//
39+
// template<typename T>
40+
// void y() requires requires () {
41+
// true;
42+
// };
43+
//
44+
// template<typename T>
45+
// void z() requires true && false;
46+
public void testFunctionDeclarationTrailingRequiresClauseTrue() throws Exception {
47+
parseAndCheckBindings(ScannerKind.STDCPP20);
48+
}
49+
50+
// template<typename T>
51+
// concept A = false;
52+
// template<typename T>
53+
// concept B = true;
54+
// template<typename T>
55+
// concept C = true;
56+
//
57+
// template<typename T>
58+
// void x() requires true && false {}
59+
//
60+
// template<typename T>
61+
// void x_c() requires C<T> {}
62+
//
63+
// template<typename T>
64+
// void x_abc() requires A<T> || B<T> && C<T> {}
65+
public void testFunctionDefinitionTrailingRequiresClause() throws Exception {
66+
parseAndCheckBindings(ScannerKind.STDCPP20);
67+
}
68+
69+
// template<typename T>
70+
// concept A = false;
71+
// template<typename T>
72+
// concept B = true;
73+
// template<typename T>
74+
// concept C = true;
75+
//
76+
// template<typename T>
77+
// requires A<T> || B<T> && C<T>
78+
// void x() {}
79+
public void testTemplateHeadRequiresClause() throws Exception {
80+
parseAndCheckBindings(ScannerKind.STDCPP20);
81+
}
82+
83+
// template<typename T>
84+
// requires requires { true; }
85+
// void x() {}
86+
public void testTemplateHeadAdHocRequiresExpression() throws Exception {
87+
parseAndCheckBindings(ScannerKind.STDCPP20);
88+
}
89+
90+
// template<typename T>
91+
// constexpr bool value = requires () { true; };
92+
public void testInitializerRequiresExpression() throws Exception {
93+
parseAndCheckBindings(ScannerKind.STDCPP20);
94+
}
95+
96+
// template<typename T>
97+
// constexpr bool x() {
98+
// if constexpr(requires { true; }) {
99+
// return true;
100+
// } else {
101+
// return false;
102+
// }
103+
// }
104+
public void testConstexprIfRequiresExpression() throws Exception {
105+
parseAndCheckBindings(ScannerKind.STDCPP20);
106+
}
107+
108+
// template<typename T>
109+
// concept A = false;
110+
// template<typename T>
111+
// concept B = true;
112+
// template<typename T>
113+
// concept C = true;
114+
//
115+
// template<A U>
116+
// void f_a(U a_u);
117+
// template<A U1, B U2, C U3>
118+
// void f_abc(U1 a_u1, U2 b_u2, U3 c_u3);
119+
public void testTemplateArgumentTypeConstraint() throws Exception {
120+
parseAndCheckBindings(ScannerKind.STDCPP20);
121+
}
122+
123+
// template<typename T>
124+
// concept A = false;
125+
// namespace Outer {
126+
// template<typename T>
127+
// concept B = true;
128+
// namespace Inner {
129+
// template<typename T>
130+
// concept C = true;
131+
// }
132+
// }
133+
//
134+
// template<A U1, Outer::B U2, Outer::Inner::C U3>
135+
// void f_abc(U1 a_u1, U2 b_u2, U3 c_u3);
136+
public void testTemplateArgumentTypeConstraintFromNamespace() throws Exception {
137+
parseAndCheckBindings(ScannerKind.STDCPP20);
138+
}
139+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 Igor V. Kovalenko.
3+
*
4+
* This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* Igor V. Kovalenko - initial API and implementation
13+
*******************************************************************************/
14+
package org.eclipse.cdt.internal.index.tests;
15+
16+
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConceptDefinition;
17+
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConcept;
18+
import org.eclipse.cdt.core.testplugin.TestScannerProvider;
19+
20+
import junit.framework.TestSuite;
21+
22+
/**
23+
* AST tests for C++20 concepts via PDOM.
24+
*/
25+
public abstract class IndexConceptTest extends IndexBindingResolutionTestBase {
26+
public static class SingleProject extends IndexConceptTest {
27+
public SingleProject() {
28+
setStrategy(new SinglePDOMTestStrategy(true /* cpp */));
29+
}
30+
31+
public static TestSuite suite() {
32+
return suite(SingleProject.class);
33+
}
34+
}
35+
36+
public static class SingleProjectReindexed extends IndexConceptTest {
37+
public SingleProjectReindexed() {
38+
setStrategy(new SinglePDOMReindexedTestStrategy(true /* cpp */));
39+
}
40+
41+
public static TestSuite suite() {
42+
return suite(SingleProjectReindexed.class);
43+
}
44+
}
45+
46+
public static class ProjectWithDepProj extends IndexConceptTest {
47+
public ProjectWithDepProj() {
48+
setStrategy(new ReferencedProject(true /* cpp */));
49+
}
50+
51+
public static TestSuite suite() {
52+
return suite(ProjectWithDepProj.class);
53+
}
54+
}
55+
56+
private static void cxx20SetUp() {
57+
TestScannerProvider.sDefinedSymbols.put("__cpp_concepts", "201907L");
58+
}
59+
60+
@Override
61+
public void setUp() throws Exception {
62+
cxx20SetUp();
63+
super.setUp();
64+
}
65+
66+
public static void addTests(TestSuite suite) {
67+
suite.addTest(SingleProject.suite());
68+
suite.addTest(SingleProjectReindexed.suite());
69+
suite.addTest(ProjectWithDepProj.suite());
70+
}
71+
72+
// template<typename T>
73+
// concept A = true;
74+
75+
// template<typename T>
76+
// concept B = A<T>;
77+
public void testConceptDefinitionFromHeader() throws Exception {
78+
checkBindings();
79+
80+
ICPPConcept concept = getBindingFromASTName("B = A<T>", 1);
81+
ICPPASTConceptDefinition decl = concept.getConceptDefinition();
82+
}
83+
}

core/org.eclipse.cdt.core/META-INF/MANIFEST.MF

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
22
Bundle-ManifestVersion: 2
33
Bundle-Name: %pluginName
44
Bundle-SymbolicName: org.eclipse.cdt.core; singleton:=true
5-
Bundle-Version: 9.2.100.qualifier
5+
Bundle-Version: 9.2.200.qualifier
66
Bundle-Activator: org.eclipse.cdt.core.CCorePlugin
77
Bundle-Vendor: %providerName
88
Bundle-Localization: plugin

core/org.eclipse.cdt.core/browser/org/eclipse/cdt/internal/core/browser/IndexModelUtil.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2006, 2015 QNX Software Systems and others.
2+
* Copyright (c) 2006, 2015, 2025 QNX Software Systems and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0
@@ -32,6 +32,7 @@
3232
import org.eclipse.cdt.core.dom.ast.IVariable;
3333
import org.eclipse.cdt.core.dom.ast.cpp.ICPPAliasTemplate;
3434
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
35+
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConcept;
3536
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
3637
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceAlias;
3738
import org.eclipse.cdt.core.index.IIndexMacroContainer;
@@ -91,6 +92,10 @@ public static boolean bindingHasCElementType(IBinding binding, int[] kinds) {
9192
if (binding instanceof IEnumerator)
9293
return true;
9394
break;
95+
case ICElement.C_CONCEPT:
96+
if (binding instanceof ICPPConcept)
97+
return true;
98+
break;
9499
}
95100
}
96101
return false;
@@ -152,6 +157,9 @@ public static int getElementType(IBinding binding) {
152157
if (binding instanceof IParameter) {
153158
elementType = ICElement.C_VARIABLE_LOCAL;
154159
}
160+
if (binding instanceof ICPPConcept) {
161+
elementType = ICElement.C_CONCEPT;
162+
}
155163
return elementType;
156164
}
157165

core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICElement.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2000, 2014 QNX Software Systems and others.
2+
* Copyright (c) 2000, 2014, 2025 QNX Software Systems and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0
@@ -249,6 +249,12 @@ public interface ICElement extends IAdaptable {
249249
*/
250250
static final int C_PRAGMA = 95;
251251

252+
/**
253+
* a C++ concept.
254+
* @since 9.2
255+
*/
256+
static final int C_CONCEPT = 96;
257+
252258
/**
253259
* @deprecated use {@link IMethodDeclaration#isConstructor()}
254260
* @noreference This field is not intended to be referenced by clients.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 Igor V. Kovalenko.
3+
*
4+
* This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* Igor V. Kovalenko - initial API and implementation
13+
*******************************************************************************/
14+
package org.eclipse.cdt.core.model;
15+
16+
/**
17+
* Represents a C++ concept.
18+
*
19+
* @noextend This interface is not intended to be extended by clients.
20+
* @noimplement This interface is not intended to be implemented by clients.
21+
*
22+
* @since 9.2
23+
*/
24+
public interface IConcept extends IDeclaration, ITemplate {
25+
26+
}

0 commit comments

Comments
 (0)