From f17675be1652efe3bae053516d6031a8130b8196 Mon Sep 17 00:00:00 2001 From: "Igor V. Kovalenko" Date: Mon, 27 Mar 2023 22:49:10 +0300 Subject: [PATCH] Add basic support for c++17 deduction guides --- .../internal/core/model/CModelBuilder2.java | 6 +- .../org/eclipse/cdt/core/dom/ast/IScope.java | 11 + .../dom/ast/cpp/ICPPASTDeductionGuide.java | 25 + .../ICPPClassConstructorDeductionGuide.java | 24 + ...lassConstructorTemplateDeductionGuide.java | 24 + .../ast/cpp/ICPPCopyDeductionCandidate.java | 24 + .../core/dom/ast/cpp/ICPPDeductionGuide.java | 27 ++ .../cdt/core/dom/ast/cpp/ICPPNodeFactory.java | 5 + .../cpp/ICPPUserDefinedDeductionGuide.java | 24 + .../dom/parser/cpp/CPPASTDeductionGuide.java | 35 ++ .../parser/cpp/CPPASTFunctionDeclarator.java | 20 +- .../dom/parser/cpp/CPPDeductionGuide.java | 87 ++++ .../core/dom/parser/cpp/CPPNodeFactory.java | 6 + .../core/dom/parser/cpp/CPPScope.java | 12 + .../dom/parser/cpp/GNUCPPSourceParser.java | 67 ++- .../parser/cpp/semantics/CPPSemantics.java | 445 ++++++++++++++++-- .../dom/parser/cpp/semantics/CPPVisitor.java | 20 +- .../parser/cpp/semantics/FunctionCost.java | 45 ++ .../core/index/IIndexCPPBindingConstants.java | 2 + .../composite/cpp/CPPCompositesFactory.java | 5 + .../cpp/CompositeCPPDeductionGuide.java | 29 ++ .../CompositeCPPDeductionGuideTemplate.java | 29 ++ .../pdom/dom/cpp/PDOMCPPDeductionGuide.java | 43 ++ .../cpp/PDOMCPPDeductionGuideTemplate.java | 44 ++ .../core/pdom/dom/cpp/PDOMCPPLinkage.java | 17 + 25 files changed, 1017 insertions(+), 59 deletions(-) create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTDeductionGuide.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPClassConstructorDeductionGuide.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPClassConstructorTemplateDeductionGuide.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPCopyDeductionCandidate.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPDeductionGuide.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPUserDefinedDeductionGuide.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeductionGuide.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeductionGuide.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPDeductionGuide.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPDeductionGuideTemplate.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPDeductionGuide.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPDeductionGuideTemplate.java diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelBuilder2.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelBuilder2.java index 97c13fac1f5..83db5b73b7e 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelBuilder2.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelBuilder2.java @@ -57,6 +57,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTAliasDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeductionGuide; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; @@ -544,7 +545,10 @@ public class CModelBuilder2 implements IContributedModelBuilder { return createTypeDef(parent, declSpecifier, declarator); } IASTDeclarator typeRelevant = ASTQueries.findTypeRelevantDeclarator(declarator); - if (typeRelevant instanceof IASTFunctionDeclarator) { + if (typeRelevant instanceof ICPPASTDeductionGuide) { + // TODO [cmodel] deduction guide + return null; + } else if (typeRelevant instanceof IASTFunctionDeclarator) { return createFunctionDeclaration(parent, declSpecifier, (IASTFunctionDeclarator) typeRelevant, isTemplate); } return createVariable(parent, declSpecifier, declarator, isTemplate); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IScope.java index 7912617ad2b..44baf67b66f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IScope.java @@ -118,6 +118,7 @@ public interface IScope { private boolean fPrefixLookup; private boolean fIgnorePointOfDeclaration; private boolean fArgumentDependent; + private boolean fDeductionGuidesOnly = false; public ScopeLookupData(IASTName name, boolean resolve, boolean prefixLookup) { if (name == null) @@ -172,6 +173,11 @@ public interface IScope { fArgumentDependent = argumentDependent; } + /** @since 8.1 */ + public final void setDeductionGuidesOnly(boolean deductionGuidesOnly) { + fDeductionGuidesOnly = deductionGuidesOnly; + } + public final void setLookupKey(char[] key) { fLookupKey = key; } @@ -201,6 +207,11 @@ public interface IScope { return fArgumentDependent; } + /** @since 8.1 */ + public final boolean isDeductionGuidesOnly() { + return fDeductionGuidesOnly; + } + public final IIndexFileSet getIncludedFiles() { return fTu == null ? IIndexFileSet.EMPTY : fTu.getIndexFileSet(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTDeductionGuide.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTDeductionGuide.java new file mode 100644 index 00000000000..9d3d8de30fd --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTDeductionGuide.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * 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.dom.ast.cpp; + +/** + * Deduction guide, introduced in C++17. + * + * @since 8.1 + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ + +public interface ICPPASTDeductionGuide extends ICPPASTFunctionDeclarator { +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPClassConstructorDeductionGuide.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPClassConstructorDeductionGuide.java new file mode 100644 index 00000000000..01b50e5cf21 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPClassConstructorDeductionGuide.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * 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.dom.ast.cpp; + +/** + * Marker for deduction guide synthesized from class constructor + * + * @since 8.1 + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface ICPPClassConstructorDeductionGuide { +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPClassConstructorTemplateDeductionGuide.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPClassConstructorTemplateDeductionGuide.java new file mode 100644 index 00000000000..3138ef45ecb --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPClassConstructorTemplateDeductionGuide.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * 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.dom.ast.cpp; + +/** + * Marker for deduction guide synthesized from class constructor template + * + * @since 8.1 + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface ICPPClassConstructorTemplateDeductionGuide { +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPCopyDeductionCandidate.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPCopyDeductionCandidate.java new file mode 100644 index 00000000000..11e05434ace --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPCopyDeductionCandidate.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * 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.dom.ast.cpp; + +/** + * Marker for copy deduction candidate used with Class Template Argument Deduction, introduced in C++17. + * + * @since 8.1 + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface ICPPCopyDeductionCandidate { +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPDeductionGuide.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPDeductionGuide.java new file mode 100644 index 00000000000..dccd1a91cfb --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPDeductionGuide.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * 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.dom.ast.cpp; + +/** + * Deduction guide, introduced in C++17. + * + * @since 8.1 + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface ICPPDeductionGuide extends ICPPBinding { + public static final ICPPDeductionGuide[] EMPTY_BINDING_ARRAY = {}; + + public ICPPFunction getFunctionBinding(); +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNodeFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNodeFactory.java index 9e9604c7f1f..d0db1e6d8e3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNodeFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNodeFactory.java @@ -253,6 +253,11 @@ public interface ICPPNodeFactory extends INodeFactory { public ICPPASTFoldExpression newFoldExpression(int opToken, boolean isComma, IASTExpression lhs, IASTExpression rhs); + /** + * @since 8.1 + */ + public ICPPASTDeductionGuide newDeductionGuide(); + public ICPPASTLinkageSpecification newLinkageSpecification(String literal); @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPUserDefinedDeductionGuide.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPUserDefinedDeductionGuide.java new file mode 100644 index 00000000000..5faeec23f81 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPUserDefinedDeductionGuide.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * 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.dom.ast.cpp; + +/** + * Marker for user-defined deduction guide for Class Template Argument Deduction, introduced in C++17. + * + * @since 8.1 + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface ICPPUserDefinedDeductionGuide { +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeductionGuide.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeductionGuide.java new file mode 100644 index 00000000000..c84a304b9e8 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeductionGuide.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * 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.core.dom.parser.cpp; + +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeductionGuide; + +/** + * Implementation for deduction guide. + */ +public class CPPASTDeductionGuide extends CPPASTFunctionDeclarator implements ICPPASTDeductionGuide { + public CPPASTDeductionGuide() { + } + + @Override + public CPPASTDeductionGuide copy() { + return copy(CopyStyle.withoutLocations); + } + + @Override + public CPPASTDeductionGuide copy(CopyStyle style) { + CPPASTDeductionGuide copy = new CPPASTDeductionGuide(); + return super.copy(copy, style); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionDeclarator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionDeclarator.java index c5635490efd..da248fd3fe3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionDeclarator.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionDeclarator.java @@ -73,13 +73,17 @@ public class CPPASTFunctionDeclarator extends CPPASTDeclarator implements ICPPAS @Override public CPPASTFunctionDeclarator copy(CopyStyle style) { CPPASTFunctionDeclarator copy = new CPPASTFunctionDeclarator(); - copy.varArgs = varArgs; - copy.pureVirtual = pureVirtual; - copy.isVolatile = isVolatile; - copy.isConst = isConst; - copy.isMutable = isMutable; - copy.refQualifier = refQualifier; - copy.isConstexpr = isConstexpr; + return copy(copy, style); + } + + protected T copy(T copy, CopyStyle style) { + copy.setVarArgs(varArgs); + copy.setPureVirtual(pureVirtual); + copy.setVolatile(isVolatile); + copy.setConst(isConst); + copy.setMutable(isMutable); + copy.setRefQualifier(refQualifier); + copy.setConstexpr(isConstexpr); for (IASTParameterDeclaration param : getParameters()) { copy.addParameterDeclaration(param == null ? null : param.copy(style)); @@ -97,7 +101,7 @@ public class CPPASTFunctionDeclarator extends CPPASTDeclarator implements ICPPAS for (ICPPASTVirtSpecifier virtSpecifier : getVirtSpecifiers()) { copy.addVirtSpecifier(virtSpecifier.copy(style)); } - return copy(copy, style); + return super.copy(copy, style); } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeductionGuide.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeductionGuide.java new file mode 100644 index 00000000000..3bec7217ff6 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeductionGuide.java @@ -0,0 +1,87 @@ +/******************************************************************************* + * 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.core.dom.parser.cpp; + +import org.eclipse.cdt.core.dom.ILinkage; +import org.eclipse.cdt.core.dom.ast.DOMException; +import org.eclipse.cdt.core.dom.ast.IASTDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.IScope; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPDeductionGuide; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; +import org.eclipse.core.runtime.PlatformObject; + +/** + * Represents c++17 deduction guide. + */ +public class CPPDeductionGuide extends PlatformObject implements ICPPDeductionGuide { + protected IASTDeclarator definition; + protected ICPPFunction functionBinding; + + public CPPDeductionGuide(IASTDeclarator fnDecl, ICPPFunction functionBinding) { + this.definition = fnDecl; + this.functionBinding = functionBinding; + } + + @Override + public ICPPFunction getFunctionBinding() { + return functionBinding; + } + + @Override + public String[] getQualifiedName() throws DOMException { + return functionBinding.getQualifiedName(); + } + + @Override + public char[][] getQualifiedNameCharArray() throws DOMException { + return functionBinding.getQualifiedNameCharArray(); + } + + @Override + public boolean isGloballyQualified() throws DOMException { + return functionBinding.isGloballyQualified(); + } + + @Override + public String getName() { + return functionBinding.getName(); + } + + @Override + public char[] getNameCharArray() { + return functionBinding.getNameCharArray(); + } + + @Override + public ILinkage getLinkage() { + return functionBinding.getLinkage(); + } + + @Override + public IBinding getOwner() { + return functionBinding.getOwner(); + } + + protected IASTName getASTName() { + return definition.getName().getLastName(); + } + + @Override + public IScope getScope() throws DOMException { + return CPPVisitor.getContainingScope(getASTName()); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java index a9bea5e8416..ec3d36c8aef 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java @@ -77,6 +77,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConversionName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclarator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDecltypeSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeductionGuide; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeleteExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDesignatedInitializer; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier; @@ -577,6 +578,11 @@ public class CPPNodeFactory extends NodeFactory implements ICPPNodeFactory { return new CPPASTFoldExpression(operator, fIsComma, lhs, rhs); } + @Override + public ICPPASTDeductionGuide newDeductionGuide() { + return new CPPASTDeductionGuide(); + } + @Override public ICPPASTLinkageSpecification newLinkageSpecification(String literal) { return new CPPASTLinkageSpecification(literal); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPScope.java index 6c101654a53..45bed4df4dc 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPScope.java @@ -31,6 +31,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPDeductionGuide; import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope; @@ -226,6 +227,12 @@ abstract public class CPPScope implements ICPPASTInternalScope { CCorePlugin.log(e); } } + + // Deduction guides are not visible to ordinary name lookup + if (result.length > 0) { + result = ArrayUtil.filter(result, lookup.isDeductionGuidesOnly() ? CPPSemantics.opIsDeductionGuide + : CPPSemantics.opIsNotDeductionGuide); + } } } @@ -313,6 +320,11 @@ abstract public class CPPScope implements ICPPASTInternalScope { binding = (IBinding) candidate; } + // Deduction guides are not visible to ordinary name lookup + if (lookup.isDeductionGuidesOnly() ^ binding instanceof ICPPDeductionGuide) { + return result; + } + if (binding != null) result = ArrayUtil.append(result, binding); return result; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java index d2c908bed04..9ba973e19fb 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java @@ -94,6 +94,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConversionName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclarator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDecltypeSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeductionGuide; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeleteExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDesignatedInitializer; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDesignator; @@ -2443,7 +2444,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { } if (LT(1) == IToken.tLPAREN) { - ICPPASTFunctionDeclarator dtor = functionDeclarator(true); + ICPPASTFunctionDeclarator dtor = functionDeclarator((IASTName) null, (IASTDeclSpecifier) null, true); lambdaExpr.setDeclarator(dtor); if (LT(1) == IToken.tEOC) return setRange(lambdaExpr, offset, calculateEndOffset(dtor)); @@ -4292,7 +4293,10 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { private void verifyDtor(IASTDeclSpecifier declspec, IASTDeclarator dtor, DeclarationOptions opt) throws BacktrackException { if (CPPVisitor.doesNotSpecifyType(declspec)) { - if (ASTQueries.findTypeRelevantDeclarator(dtor) instanceof IASTFunctionDeclarator) { + if (ASTQueries.findTypeRelevantDeclarator(dtor) instanceof IASTFunctionDeclarator typeRelevantDtor) { + if (typeRelevantDtor instanceof ICPPASTDeductionGuide) { + return; + } boolean isQualified = false; IASTName name = ASTQueries.findInnermostDeclarator(dtor).getName(); if (name instanceof ICPPASTQualifiedName) { @@ -4373,7 +4377,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { */ private IASTDeclarator initDeclarator(DtorStrategy strategy, IASTDeclSpecifier declspec, DeclarationOptions option) throws EndOfFileException, BacktrackException, FoundAggregateInitializer { - final IASTDeclarator dtor = declarator(strategy, option); + final IASTDeclarator dtor = declarator(strategy, declspec, option); if (option.fAllowInitializer) { final IASTDeclarator typeRelevantDtor = ASTQueries.findTypeRelevantDeclarator(dtor); if (option != DeclarationOptions.PARAMETER && typeRelevantDtor instanceof IASTFunctionDeclarator) { @@ -4767,7 +4771,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { * @throws BacktrackException * request a backtrack */ - protected IASTDeclarator declarator(DtorStrategy strategy, DeclarationOptions option) + protected IASTDeclarator declarator(DtorStrategy strategy, IASTDeclSpecifier declspec, DeclarationOptions option) throws EndOfFileException, BacktrackException { final int startingOffset = LA(1).getOffset(); int endOffset = startingOffset; @@ -4810,7 +4814,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { final IASTName declaratorName = !option.fRequireSimpleName ? qualifiedName() : identifier(); endOffset = calculateEndOffset(declaratorName); return declarator(pointerOps, hasEllipsis, declaratorName, null, startingOffset, endOffset, strategy, - option, attributes); + declspec, option, attributes); } if (lt1 == IToken.tLPAREN) { @@ -4821,7 +4825,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { final IToken mark = mark(); try { cand1 = declarator(pointerOps, hasEllipsis, getNodeFactory().newName(), null, startingOffset, - endOffset, strategy, option, attributes); + endOffset, strategy, declspec, option, attributes); if (option.fRequireAbstract || !option.fAllowNested || hasEllipsis) return cand1; @@ -4835,7 +4839,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { if (!option.fAllowNested || hasEllipsis) { if (option.fAllowAbstract) { return declarator(pointerOps, hasEllipsis, getNodeFactory().newName(), null, startingOffset, - endOffset, strategy, option, attributes); + endOffset, strategy, declspec, option, attributes); } throwBacktrack(LA(1)); } @@ -4846,10 +4850,10 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { if (LT(1) == IToken.tRPAREN) throwBacktrack(LA(1)); - final IASTDeclarator nested = declarator(DtorStrategy.PREFER_FUNCTION, option); + final IASTDeclarator nested = declarator(DtorStrategy.PREFER_FUNCTION, declspec, option); endOffset = consume(IToken.tRPAREN).getEndOffset(); final IASTDeclarator cand2 = declarator(pointerOps, hasEllipsis, getNodeFactory().newName(), nested, - startingOffset, endOffset, strategy, option, attributes); + startingOffset, endOffset, strategy, declspec, option, attributes); if (cand1 == null || cand1End == null) return cand2; final IToken cand2End = LA(1); @@ -4877,7 +4881,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { throwBacktrack(LA(1)); } return declarator(pointerOps, hasEllipsis, getNodeFactory().newName(), null, startingOffset, endOffset, - strategy, option, attributes); + strategy, declspec, option, attributes); } /** @@ -5000,15 +5004,15 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { private IASTDeclarator declarator(List pointerOps, boolean hasEllipsis, IASTName declaratorName, IASTDeclarator nestedDeclarator, int startingOffset, int endOffset, - DtorStrategy strategy, DeclarationOptions option, List attributes) - throws EndOfFileException, BacktrackException { + DtorStrategy strategy, IASTDeclSpecifier declspec, DeclarationOptions option, + List attributes) throws EndOfFileException, BacktrackException { ICPPASTDeclarator result = null; loop: while (true) { final int lt1 = LTcatchEOF(1); switch (lt1) { case IToken.tLPAREN: if (option.fAllowFunctions && strategy == DtorStrategy.PREFER_FUNCTION) { - result = functionDeclarator(false); + result = functionDeclarator(declaratorName, declspec, false); setDeclaratorID(result, hasEllipsis, declaratorName, nestedDeclarator); } break loop; @@ -5086,16 +5090,47 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { declarator.setDeclaresParameterPack(hasEllipsis); } + /** + * Parse a function declarator or a deduction guide, starting with the left parenthesis. + */ + private ICPPASTFunctionDeclarator functionDeclarator(IASTName declaratorName, IASTDeclSpecifier declspec, + boolean isLambdaDeclarator) throws EndOfFileException, BacktrackException { + final IToken mark = mark(); + + ICPPASTFunctionDeclarator fc = getNodeFactory().newFunctionDeclarator(null); + functionDeclarator(fc, isLambdaDeclarator); + + // Test if this is a deduction guide and retry with correct object type + final IASTTypeId typeId = fc.getTrailingReturnType(); + if (!isLambdaDeclarator && typeId != null && CPPVisitor.doesNotSpecifyType(declspec) && declaratorName != null + && typeId.getDeclSpecifier() instanceof IASTNamedTypeSpecifier namedTypeSpec + && namedTypeSpec.getName() instanceof ICPPASTTemplateId templateId) { + + if (CharArrayUtils.equals(templateId.getTemplateName().getLookupKey(), declaratorName.getLookupKey())) { + if (declspec instanceof ICPPASTSimpleDeclSpecifier simpleDeclSpecifier) { + // TODO: This enables auto type resolution from return type, validate implementation in CreateType() + simpleDeclSpecifier.setType(IASTSimpleDeclSpecifier.t_auto); + } + + backup(mark); + + fc = getNodeFactory().newDeductionGuide(); + functionDeclarator(fc, isLambdaDeclarator); + } + } + + return fc; + } + /** * Parse a function declarator starting with the left parenthesis. */ - private ICPPASTFunctionDeclarator functionDeclarator(boolean isLambdaDeclarator) + private void functionDeclarator(final ICPPASTFunctionDeclarator fc, boolean isLambdaDeclarator) throws EndOfFileException, BacktrackException { IToken last = consume(IToken.tLPAREN); final int startOffset = last.getOffset(); int endOffset = last.getEndOffset(); - final ICPPASTFunctionDeclarator fc = getNodeFactory().newFunctionDeclarator(null); ICPPASTParameterDeclaration pd = null; paramLoop: while (true) { switch (LT(1)) { @@ -5245,7 +5280,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { endOffset = calculateEndOffset(typeId); } - return setRange(fc, startOffset, endOffset); + setRange(fc, startOffset, endOffset); } /** diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java index 03f123ac855..f3c1cdd4b1e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java @@ -157,12 +157,16 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTWhileStatement; import org.eclipse.cdt.core.dom.ast.cpp.ICPPAliasTemplate; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBlockScope; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassConstructorDeductionGuide; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassConstructorTemplateDeductionGuide; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPCopyDeductionCandidate; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPDeductionGuide; import org.eclipse.cdt.core.dom.ast.cpp.ICPPDeferredFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; @@ -188,6 +192,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTypeParameter; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPUserDefinedDeductionGuide; import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDirective; import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable; @@ -224,10 +229,14 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBuiltinParameter; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPCompositeBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPDeferredConstructor; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPDeferredFunction; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunction; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunctionTemplate; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunctionType; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPImplicitConstructor; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPImplicitFunction; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPNamespace; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPNamespaceScope; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPParameter; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPReferenceType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPScope; @@ -274,6 +283,13 @@ public class CPPSemantics { private static final char[] CALL_FUNCTION = "call-function".toCharArray(); //$NON-NLS-1$ private static final ICPPEvaluation[] NO_INITCLAUSE_EVALUATION = {}; + public static final IUnaryPredicate opIsDeductionGuide = (argument) -> { + return argument instanceof ICPPDeductionGuide; + }; + public static final IUnaryPredicate opIsNotDeductionGuide = (argument) -> { + return !(argument instanceof ICPPDeductionGuide); + }; + // Set to true for debugging. public static boolean traceBindingResolution = false; public static int traceIndent = 0; @@ -399,6 +415,289 @@ public class CPPSemantics { return postResolution(binding, data); } + private static IBinding doClassTemplateArgumentDeduction(ICPPClassTemplate classTemplate, LookupData data) { + // Implementation common to all candidate function non-templates + class CTADDeductionCandidateProbeFunction extends CPPFunction { + ICPPFunction method; + ICPPFunctionType functionType; + + public CTADDeductionCandidateProbeFunction(ICPPFunction method) { + super(null); + this.method = method; + } + + @Override + public char[] getNameCharArray() { + return method.getNameCharArray(); + } + + @Override + public ICPPFunctionType getType() { + if (functionType == null) { + ICPPFunctionType ft = method.getType(); + functionType = new CPPFunctionType(ft.getReturnType(), ft.getParameterTypes(), + ft.getNoexceptSpecifier(), ft.isConst(), ft.isVolatile(), ft.hasRefQualifier(), + ft.isRValueReference(), ft.takesVarArgs()); + } + + return functionType; + } + + @Override + public IType[] getExceptionSpecification() { + return method.getExceptionSpecification(); + } + + @Override + public ICPPParameter[] getParameters() { + return method.getParameters(); + } + + @Override + public boolean takesVarArgs() { + return method.takesVarArgs(); + } + + @Override + public boolean hasParameterPack() { + return method.hasParameterPack(); + } + } + + // Implementation common to all candidate function templates + class CTADDeductionCandidateProbeFunctionTemplate extends CPPFunctionTemplate { + ICPPClassTemplate classTemplate; + ICPPFunction method; + boolean isClassConstructor; + private ICPPTemplateParameter[] deductionTemplateParameters; + ICPPFunctionType functionType; + + private final void resetCachedValues() { + deductionTemplateParameters = null; + functionType = null; + } + + public CTADDeductionCandidateProbeFunctionTemplate(ICPPClassTemplate classTemplate) { + super(null); + this.classTemplate = classTemplate; + } + + public CTADDeductionCandidateProbeFunctionTemplate(ICPPClassTemplate classTemplate, ICPPFunction method, + boolean isClassConstructor) { + this(classTemplate); + setMethod(method); + setIsClassConstructor(isClassConstructor); + } + + protected void setMethod(ICPPFunction method) { + this.method = method; + resetCachedValues(); // Force recalculation of type and template args + } + + protected void setIsClassConstructor(boolean isClassConstructor) { + this.isClassConstructor = isClassConstructor; + resetCachedValues(); // Force recalculation of type and template args + } + + @Override + public char[] getNameCharArray() { + return method.getNameCharArray(); + } + + @Override + public ICPPFunctionType getType() { + if (functionType == null) { + ICPPFunctionType ft = method.getType(); + IType returnType; + if (isClassConstructor) { + returnType = (ICPPClassType) classTemplate.asDeferredInstance(); + } else { + returnType = ft.getReturnType(); + } + functionType = new CPPFunctionType(returnType, ft.getParameterTypes(), ft.getNoexceptSpecifier(), + ft.isConst(), ft.isVolatile(), ft.hasRefQualifier(), ft.isRValueReference(), + ft.takesVarArgs()); + } + + return functionType; + } + + @Override + public IType[] getExceptionSpecification() { + //return method.getExceptionSpecification(); + // TODO: this requires class owner; see if exception specification is required to implement CTAD + return IType.EMPTY_TYPE_ARRAY; + } + + @Override + public ICPPParameter[] getParameters() { + return method.getParameters(); + } + + @Override + public boolean takesVarArgs() { + return method.takesVarArgs(); + } + + @Override + public boolean hasParameterPack() { + return method.hasParameterPack(); + } + + @Override + public ICPPTemplateParameter[] getTemplateParameters() { + // TODO: make sure template parameter identifiers are consistent with where parameters are coming from + // Maybe need to re-instantiate all of them? + if (deductionTemplateParameters == null) { + ICPPTemplateParameter[] candParams = ICPPTemplateParameter.EMPTY_TEMPLATE_PARAMETER_ARRAY; + if (isClassConstructor) { + candParams = ArrayUtil.addAll(candParams, classTemplate.getTemplateParameters()); + } + if (method instanceof ICPPTemplateDefinition ctorTemplate) { + candParams = ArrayUtil.addAll(candParams, ctorTemplate.getTemplateParameters()); + } + deductionTemplateParameters = ArrayUtil.trim(candParams); + } + return deductionTemplateParameters; + } + } + + // Implementation for candidate function synthesized from constructor non-template + class CTADGuideFromConstructor extends CTADDeductionCandidateProbeFunctionTemplate + implements ICPPClassConstructorDeductionGuide { + + public CTADGuideFromConstructor(ICPPClassTemplate classTemplate, ICPPFunction method) { + super(classTemplate, method, true); + } + } + + // Implementation for candidate function synthesized from constructor template + class CTADGuideFromConstructorTemplate extends CTADDeductionCandidateProbeFunctionTemplate + implements ICPPClassConstructorTemplateDeductionGuide { + + public CTADGuideFromConstructorTemplate(ICPPClassTemplate classTemplate, ICPPFunction method) { + super(classTemplate, method, true); + } + } + + // Implementation for candidate function from user-defined template deduction guide + class CTADUserDefinedGuideTemplate extends CTADDeductionCandidateProbeFunctionTemplate + implements ICPPUserDefinedDeductionGuide { + + public CTADUserDefinedGuideTemplate(ICPPClassTemplate classTemplate, ICPPTemplateDefinition method) { + super(classTemplate, (ICPPFunction) method, false); + } + } + + // Implementation for candidate function from user-defined non-template deduction guide + class CTADUserDefinedGuide extends CTADDeductionCandidateProbeFunction + implements ICPPUserDefinedDeductionGuide { + + public CTADUserDefinedGuide(ICPPFunction method) { + super(method); + } + } + + // Implementation for "copy deduction candidate" synthesized from hypothetical constructor C(C) + class CTADCopyDeductionCandidate extends CTADDeductionCandidateProbeFunctionTemplate + implements ICPPCopyDeductionCandidate { + + public CTADCopyDeductionCandidate(ICPPClassTemplate classTemplate) { + super(classTemplate); + + char[] className = classTemplate.getNameCharArray(); + + ICPPParameter[] copyDeductionCandidateParams = new ICPPParameter[] { + new CPPParameter((ICPPClassType) classTemplate.asDeferredInstance(), 0) }; + ICPPMethod copyDeductionCandidate = new CPPImplicitConstructor( + (ICPPClassScope) classTemplate.getCompositeScope(), className, copyDeductionCandidateParams, + null); + + setMethod(copyDeductionCandidate); + setIsClassConstructor(true); + } + } + + final IASTName lookupName = data.getLookupName(); + if (lookupName == null) + return classTemplate; + + char[] className = lookupName.getLookupKey(); + + ICPPConstructor[] ctors = classTemplate.getConstructors(); + + ICPPFunction[] deductionGuideCandidateFunctions = new ICPPFunction[ctors.length + 1]; + + if (ctors.length > 0) { + // Add template probe functions synthesized from class constructors + for (ICPPConstructor ctor : ctors) { + if (ctor instanceof ICPPTemplateDefinition ctorTemplate) { + deductionGuideCandidateFunctions = ArrayUtil.append(deductionGuideCandidateFunctions, + new CTADGuideFromConstructorTemplate(classTemplate, ctor)); + } else { + deductionGuideCandidateFunctions = ArrayUtil.append(deductionGuideCandidateFunctions, + new CTADGuideFromConstructor(classTemplate, ctor)); + } + } + } else { + // If class is not defined or does not declare any constructors, add hypothetical constructor C() + ICPPMethod defaultConstructor = new CPPImplicitConstructor( + (ICPPClassScope) classTemplate.getCompositeScope(), className, + ICPPParameter.EMPTY_CPPPARAMETER_ARRAY, null); + + deductionGuideCandidateFunctions = ArrayUtil.append(deductionGuideCandidateFunctions, + new CTADDeductionCandidateProbeFunctionTemplate(classTemplate, defaultConstructor, true)); + } + + deductionGuideCandidateFunctions = ArrayUtil.append(deductionGuideCandidateFunctions, + new CTADCopyDeductionCandidate(classTemplate)); + + // Add user-defined deduction guides + try { + // TODO: add support for lookup in containing class scope of classTemplate + IScope lookupScope = getContainingNamespaceScope(classTemplate, data.getTranslationUnit()); + + if (lookupScope instanceof ICPPASTInternalScope internalScope) { + + LookupData guideLookupData = new LookupData(className, null, lookupName); + guideLookupData.setDeductionGuidesOnly(true); + + IBinding[] bindings = getBindingsFromScope(internalScope, guideLookupData); + + for (IBinding binding : bindings) { + if (binding instanceof ICPPDeductionGuide guide) { + IBinding guideBinding = guide.getFunctionBinding(); + + if (guideBinding instanceof ICPPTemplateDefinition guideFunctionTemplate) { + deductionGuideCandidateFunctions = ArrayUtil.append(deductionGuideCandidateFunctions, + new CTADUserDefinedGuideTemplate(classTemplate, guideFunctionTemplate)); + } else if (guideBinding instanceof ICPPFunction guideFunction) { + deductionGuideCandidateFunctions = ArrayUtil.append(deductionGuideCandidateFunctions, + new CTADUserDefinedGuide(guideFunction)); + } + } + } + } + } catch (DOMException e) { + } + + // Perform overload resolution for initializer clause. + // Deduced class type is the return type of the function selected by overload resolution. + try { + IBinding resolved = resolveFunction(data, deductionGuideCandidateFunctions, true, false); + + if (resolved instanceof ICPPFunction selected) { + if (selected.getType().getReturnType() instanceof IBinding binding) { + return binding; + } + } + } catch (DOMException e) { + } + + // Not deduced + return null; + } + private static IBinding postResolution(IBinding binding, LookupData data) { final IASTName lookupName = data.getLookupName(); if (lookupName == null) @@ -468,40 +767,119 @@ public class CPPSemantics { */ if (binding instanceof ICPPClassTemplate && !(binding instanceof ICPPClassSpecialization) && !(binding instanceof ICPPTemplateParameter) && !(lookupName instanceof ICPPASTTemplateId)) { + ASTNodeProperty prop = lookupName.getPropertyInParent(); - if (prop != ICPPASTTemplateId.TEMPLATE_NAME && !lookupName.isQualified()) { - // You cannot use a class template name outside of the class template scope, - // mark it as a problem. - IBinding user = CPPTemplates.isUsedInClassTemplateScope((ICPPClassTemplate) binding, lookupName); - if (user instanceof ICPPClassTemplate) { - binding = ((ICPPClassTemplate) user).asDeferredInstance(); - } else if (user != null) { - binding = user; - } else { - boolean ok = false; - IASTNode node = lookupName.getParent(); - while (node != null && !ok) { - if (node instanceof ICPPASTTemplateId - || node instanceof ICPPASTTemplatedTypeTemplateParameter) { - ok = true; // Can be argument or default-value for template template parameter - break; - } else if (node instanceof IASTElaboratedTypeSpecifier) { - IASTNode parent = node.getParent(); - if (parent instanceof IASTSimpleDeclaration) { - IASTDeclSpecifier declspec = ((IASTSimpleDeclaration) parent).getDeclSpecifier(); - if (declspec instanceof ICPPASTDeclSpecifier) { - if (((ICPPASTDeclSpecifier) declspec).isFriend()) { - ok = true; // A friend class template declarations uses resolution. - break; + if (prop != ICPPASTTemplateId.TEMPLATE_NAME) { + if (!lookupName.isQualified()) { + // You cannot use a class template name outside of the class template scope, + // mark it as a problem - unless Class Template Argument Deduction needs to be done + IBinding user = CPPTemplates.isUsedInClassTemplateScope((ICPPClassTemplate) binding, lookupName); + if (user instanceof ICPPClassTemplate) { + binding = ((ICPPClassTemplate) user).asDeferredInstance(); + } else if (user != null) { + binding = user; + } else { + // Attempt class template argument deduction if appropriate + if (data.getTranslationUnit().getEnableClassTemplateArgumentDeduction()) { + if (lookupName.getParent() instanceof IASTIdExpression idExpression + && idExpression.getPropertyInParent() == IASTFunctionCallExpression.FUNCTION_NAME) { + + // Class name for class type argument deduction is a type + return doClassTemplateArgumentDeduction((ICPPClassTemplate) binding, data); + } + } + boolean ok = false; + // Attempt class template argument deduction if appropriate + if (data.getTranslationUnit().getEnableClassTemplateArgumentDeduction() + && lookupName.getParent() instanceof IASTNamedTypeSpecifier namedTypeSpecifier + && namedTypeSpecifier.getPropertyInParent() == IASTSimpleDeclaration.DECL_SPECIFIER + && namedTypeSpecifier.getParent() instanceof IASTSimpleDeclaration declaration) { + + IASTDeclarator[] declarators = declaration.getDeclarators(); + if (declarators != null && declarators.length > 0) { + IASTDeclarator declarator = declarators[0]; + + // Cannot deduce pointer or reference class template argument + if (declarator.getPointerOperators().length == 0) { + // Class name for class type argument deduction is a type + ICPPASTInitializerClause initializerClause = CPPVisitor + .getAutoInitClauseForDeclarator(declarator); + if (initializerClause != null) { + data.setFunctionArguments(false, + new ICPPASTInitializerClause[] { initializerClause }); + } else { + data.setFunctionArguments(false, NO_INITCLAUSE_EVALUATION); + } + IBinding b = doClassTemplateArgumentDeduction((ICPPClassTemplate) binding, data); + + if (b != null) { + // Deduced class template arguments + binding = b; + // No need to check other cases + ok = true; } } } } - node = node.getParent(); + + IASTNode node = lookupName.getParent(); + while (node != null && !ok) { + if (node instanceof ICPPASTTemplateId + || node instanceof ICPPASTTemplatedTypeTemplateParameter) { + ok = true; // Can be argument or default-value for template template parameter + break; + } else if (node instanceof IASTElaboratedTypeSpecifier) { + IASTNode parent = node.getParent(); + if (parent instanceof IASTSimpleDeclaration) { + IASTDeclSpecifier declspec = ((IASTSimpleDeclaration) parent).getDeclSpecifier(); + if (declspec instanceof ICPPASTDeclSpecifier) { + if (((ICPPASTDeclSpecifier) declspec).isFriend()) { + ok = true; // A friend class template declarations uses resolution. + break; + } + } + } + } + node = node.getParent(); + } + if (!ok) { + binding = new ProblemBinding(lookupName, lookupPoint, IProblemBinding.SEMANTIC_INVALID_TYPE, + data.getFoundBindings()); + } } - if (!ok) { - binding = new ProblemBinding(lookupName, lookupPoint, IProblemBinding.SEMANTIC_INVALID_TYPE, - data.getFoundBindings()); + + } else { + // Name is qualified-name + // Attempt class template argument deduction if appropriate + if (data.getTranslationUnit().getEnableClassTemplateArgumentDeduction() + && lookupName.getParent() instanceof ICPPASTQualifiedName qualifiedName + && qualifiedName.getParent() instanceof IASTNamedTypeSpecifier namedTypeSpecifier + && namedTypeSpecifier.getPropertyInParent() == IASTSimpleDeclaration.DECL_SPECIFIER + && namedTypeSpecifier.getParent() instanceof IASTSimpleDeclaration declaration) { + + IASTDeclarator[] declarators = declaration.getDeclarators(); + if (declarators != null && declarators.length > 0) { + IASTDeclarator declarator = declarators[0]; + + // Cannot deduce pointer or reference class template argument + if (declarator.getPointerOperators().length == 0) { + // Class name for class type argument deduction is a type + ICPPASTInitializerClause initializerClause = CPPVisitor + .getAutoInitClauseForDeclarator(declarator); + if (initializerClause != null) { + data.setFunctionArguments(false, + new ICPPASTInitializerClause[] { initializerClause }); + } else { + data.setFunctionArguments(false, NO_INITCLAUSE_EVALUATION); + } + IBinding b = doClassTemplateArgumentDeduction((ICPPClassTemplate) binding, data); + + if (b != null) { + // Deduced class template arguments + binding = b; + } + } + } } } } @@ -1442,6 +1820,12 @@ public class CPPSemantics { }); } + // Deduction guides are not visible to ordinary name lookup + if (bindings.length > 0) { + bindings = ArrayUtil.filter(bindings, + data.isDeductionGuidesOnly() ? opIsDeductionGuide : opIsNotDeductionGuide); + } + return expandUsingDeclarationsAndRemoveObjects(bindings, data); } @@ -1863,8 +2247,9 @@ public class CPPSemantics { declarator = declarator.getNestedDeclarator(); } if (innermost != null) { - IASTName declaratorName = innermost.getName(); - ASTInternal.addName(scope, declaratorName); + // NOTE This now may include deduction guides which are filtered later during lookup + IASTName declaratorOrDeductionGuideName = innermost.getName(); + ASTInternal.addName(scope, declaratorOrDeductionGuideName); } } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java index 6393d9cf453..9822da4813d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java @@ -117,6 +117,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorInitializer; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConversionName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclarator; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeductionGuide; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTEnumerationSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation; @@ -212,6 +213,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClosureType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPConstructor; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPConstructorTemplate; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPDeductionGuide; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPEnumeration; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPEnumerator; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPField; @@ -883,6 +885,7 @@ public class CPPVisitor extends ASTQueries { binding = scope.getBinding(name, forceResolve); } + boolean isDeductionGuide = false; boolean isFunction = false; if (parent instanceof ICPPASTFunctionDefinition) { isFunction = true; @@ -908,6 +911,9 @@ public class CPPVisitor extends ASTQueries { binding = td; } else if (typeRelevantDtor instanceof IASTFunctionDeclarator) { // Function declaration via function declarator. + if (typeRelevantDtor instanceof ICPPASTDeductionGuide) { + isDeductionGuide = true; + } isFunction = true; } else { // Looks like a variable declaration. @@ -991,9 +997,15 @@ public class CPPVisitor extends ASTQueries { } else { binding = template ? (ICPPFunction) new CPPFunctionTemplate(name) : new CPPFunction(typeRelevantDtor); } - binding = CPPSemantics.checkDeclSpecifier(binding, name, parent); - if (isFriendDecl && scope instanceof IASTInternalScope) { - ((IASTInternalScope) scope).addBinding(binding); + + if (isDeductionGuide) { + binding = new CPPDeductionGuide(typeRelevantDtor, (ICPPFunction) binding); + } else { + binding = CPPSemantics.checkDeclSpecifier(binding, name, parent); + + if (isFriendDecl && scope instanceof IASTInternalScope) { + ((IASTInternalScope) scope).addBinding(binding); + } } } @@ -2473,7 +2485,7 @@ public class CPPVisitor extends ASTQueries { return autoInitClause; } - private static ICPPASTInitializerClause getAutoInitClauseForDeclarator(IASTDeclarator declarator) { + protected static ICPPASTInitializerClause getAutoInitClauseForDeclarator(IASTDeclarator declarator) { IASTInitializer initClause = declarator.getInitializer(); return getInitClauseForInitializer(initClause); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/FunctionCost.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/FunctionCost.java index 1044779f327..d77b19e72fd 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/FunctionCost.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/FunctionCost.java @@ -28,12 +28,16 @@ import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IFunction; import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassConstructorDeductionGuide; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassConstructorTemplateDeductionGuide; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPCopyDeductionCandidate; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionTemplate; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPUserDefinedDeductionGuide; import org.eclipse.cdt.internal.core.dom.parser.cpp.OverloadableOperator; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates.TypeSelection; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.DeferredUDC; @@ -195,6 +199,10 @@ class FunctionCost { if (cmp != 0) return cmp; + cmp = compareAsDeductionGuides(f1, f2); + if (cmp != 0) + return cmp; + // At this point prefer non-index bindings return -CPPSemantics.compareByRelevance(tu, f1, f2); } @@ -205,6 +213,43 @@ class FunctionCost { return 1; } + private int compareAsDeductionGuides(ICPPFunction f1, ICPPFunction f2) { + ICPPFunction deductionCandidate = asTemplate(f1); + if (deductionCandidate == null) { + deductionCandidate = f1; + } + ICPPFunction otherDeductionCandidate = asTemplate(f2); + if (otherDeductionCandidate == null) { + otherDeductionCandidate = f2; + } + + // 16.3.3-1.12 F1 is generated from a deduction-guide and F2 is not + final boolean isUserDefinedDeductionGuide = deductionCandidate instanceof ICPPUserDefinedDeductionGuide; + final boolean otherUserDefinedDeductionGuide = otherDeductionCandidate instanceof ICPPUserDefinedDeductionGuide; + + if (isUserDefinedDeductionGuide != otherUserDefinedDeductionGuide) { + return isUserDefinedDeductionGuide ? -1 : 1; + } + + // 16.3.3-1.13 F1 is the copy deduction candidate and F2 is not + final boolean isCopyDeductionCandidate = deductionCandidate instanceof ICPPCopyDeductionCandidate; + final boolean otherCopyDeductionCandidate = otherDeductionCandidate instanceof ICPPCopyDeductionCandidate; + + if (isCopyDeductionCandidate != otherCopyDeductionCandidate) { + return isCopyDeductionCandidate ? -1 : 1; + } + + // 16.3.3-1.14 F1 is generated from a non-template constructor and F2 is generated from a constructor template + final boolean isFromNonTemplateConstructor = deductionCandidate instanceof ICPPClassConstructorDeductionGuide; + final boolean otherFromTemplateConstructor = otherDeductionCandidate instanceof ICPPClassConstructorTemplateDeductionGuide; + + if (isFromNonTemplateConstructor && otherFromTemplateConstructor) { + return -1; + } + + return 0; + } + private int overridesUsingDeclaration(ICPPFunction f1, ICPPFunction f2) { if (f1.takesVarArgs() != f2.takesVarArgs()) return 0; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexCPPBindingConstants.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexCPPBindingConstants.java index 85ab706bed1..f76e5f14ca8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexCPPBindingConstants.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexCPPBindingConstants.java @@ -77,4 +77,6 @@ public interface IIndexCPPBindingConstants { int CPP_FIELD_TEMPLATE_PARTIAL_SPECIALIZATION = IIndexBindingConstants.LAST_CONSTANT + 60; int CPP_DEFERRED_VARIABLE_INSTANCE = IIndexBindingConstants.LAST_CONSTANT + 61; int CPP_ALIAS_TEMPLATE_SPECIALIZATION = IIndexBindingConstants.LAST_CONSTANT + 62; + int CPP_DEDUCTION_GUIDE = IIndexBindingConstants.LAST_CONSTANT + 63; + int CPP_DEDUCTION_GUIDE_TEMPLATE = IIndexBindingConstants.LAST_CONSTANT + 64; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CPPCompositesFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CPPCompositesFactory.java index 9f0eb61f80a..4d2c8677980 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CPPCompositesFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CPPCompositesFactory.java @@ -36,6 +36,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecializationSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPDeductionGuide; import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumeration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; @@ -753,6 +754,8 @@ public class CPPCompositesFactory extends AbstractCompositeFactory { return new CompositeCPPConstructorTemplate(this, (ICPPConstructor) binding); } else if (binding instanceof ICPPMethod) { return new CompositeCPPMethodTemplate(this, (ICPPMethod) binding); + } else if (binding instanceof ICPPDeductionGuide guide) { + return new CompositeCPPDeductionGuideTemplate(this, guide); } else if (binding instanceof ICPPFunctionTemplate) { return new CompositeCPPFunctionTemplate(this, (ICPPFunction) binding); } else if (binding instanceof ICPPAliasTemplate) { @@ -810,6 +813,8 @@ public class CPPCompositesFactory extends AbstractCompositeFactory { } else if (binding instanceof ICPPEnumeration) { ICPPEnumeration def = (ICPPEnumeration) findOneBinding(binding); result = def == null ? null : new CompositeCPPEnumeration(this, def); + } else if (binding instanceof ICPPDeductionGuide guide) { + result = new CompositeCPPDeductionGuide(this, guide); } else if (binding instanceof ICPPFunction) { result = new CompositeCPPFunction(this, (ICPPFunction) binding); } else if (binding instanceof ICPPInternalEnumerator) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPDeductionGuide.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPDeductionGuide.java new file mode 100644 index 00000000000..6d065c8b16c --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPDeductionGuide.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * 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.core.index.composite.cpp; + +import org.eclipse.cdt.core.dom.ast.cpp.ICPPDeductionGuide; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; +import org.eclipse.cdt.internal.core.index.composite.ICompositesFactory; + +public class CompositeCPPDeductionGuide extends CompositeCPPFunction implements ICPPDeductionGuide { + public CompositeCPPDeductionGuide(ICompositesFactory cf, ICPPDeductionGuide rbinding) { + super(cf, rbinding.getFunctionBinding()); + } + + @Override + public ICPPFunction getFunctionBinding() { + return this; + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPDeductionGuideTemplate.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPDeductionGuideTemplate.java new file mode 100644 index 00000000000..e987c2a68ed --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPDeductionGuideTemplate.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * 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.core.index.composite.cpp; + +import org.eclipse.cdt.core.dom.ast.cpp.ICPPDeductionGuide; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; +import org.eclipse.cdt.internal.core.index.composite.ICompositesFactory; + +public class CompositeCPPDeductionGuideTemplate extends CompositeCPPFunctionTemplate implements ICPPDeductionGuide { + public CompositeCPPDeductionGuideTemplate(ICompositesFactory cf, ICPPDeductionGuide rbinding) { + super(cf, rbinding.getFunctionBinding()); + } + + @Override + public ICPPFunction getFunctionBinding() { + return this; + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPDeductionGuide.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPDeductionGuide.java new file mode 100644 index 00000000000..6398c45e93e --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPDeductionGuide.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * 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.core.pdom.dom.cpp; + +import org.eclipse.cdt.core.dom.ast.DOMException; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPDeductionGuide; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; +import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants; +import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage; +import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode; +import org.eclipse.core.runtime.CoreException; + +public class PDOMCPPDeductionGuide extends PDOMCPPFunction implements ICPPDeductionGuide { + public PDOMCPPDeductionGuide(PDOMLinkage linkage, long bindingRecord) { + super(linkage, bindingRecord); + } + + public PDOMCPPDeductionGuide(PDOMCPPLinkage linkage, PDOMNode parent, ICPPDeductionGuide guide) + throws CoreException, DOMException { + super(linkage, parent, guide.getFunctionBinding(), true); + } + + @Override + public int getNodeType() { + return IIndexCPPBindingConstants.CPP_DEDUCTION_GUIDE; + } + + @Override + public ICPPFunction getFunctionBinding() { + return this; + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPDeductionGuideTemplate.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPDeductionGuideTemplate.java new file mode 100644 index 00000000000..fe0b396e72b --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPDeductionGuideTemplate.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * 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.core.pdom.dom.cpp; + +import org.eclipse.cdt.core.dom.ast.DOMException; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPDeductionGuide; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionTemplate; +import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants; +import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage; +import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode; +import org.eclipse.core.runtime.CoreException; + +public class PDOMCPPDeductionGuideTemplate extends PDOMCPPFunctionTemplate implements ICPPDeductionGuide { + public PDOMCPPDeductionGuideTemplate(PDOMLinkage linkage, long bindingRecord) { + super(linkage, bindingRecord); + } + + public PDOMCPPDeductionGuideTemplate(PDOMCPPLinkage linkage, PDOMNode parent, ICPPDeductionGuide guide) + throws CoreException, DOMException { + super(linkage, parent, (ICPPFunctionTemplate) guide.getFunctionBinding()); + } + + @Override + public int getNodeType() { + return IIndexCPPBindingConstants.CPP_DEDUCTION_GUIDE_TEMPLATE; + } + + @Override + public ICPPFunction getFunctionBinding() { + return this; + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java index a937cca7739..2b48a268e21 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java @@ -60,6 +60,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPDeductionGuide; import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumeration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFieldTemplate; @@ -851,6 +852,12 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { if (parent instanceof PDOMCPPClassType || parent instanceof PDOMCPPClassSpecialization) { pdomBinding = new PDOMCPPMethod(this, parent, (ICPPMethod) binding); } + } else if (binding instanceof ICPPDeductionGuide guide) { + if (guide.getFunctionBinding() instanceof ICPPFunctionTemplate) { + pdomBinding = new PDOMCPPDeductionGuideTemplate(this, parent, guide); + } else { + pdomBinding = new PDOMCPPDeductionGuide(this, parent, guide); + } } else if (binding instanceof ICPPFunction) { pdomBinding = new PDOMCPPFunction(this, parent, (ICPPFunction) binding, true); } else if (binding instanceof ICPPNamespaceAlias) { @@ -1137,6 +1144,12 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { } else if (binding instanceof ICPPMethod) { // this must be before functions return CPPMETHOD; + } else if (binding instanceof ICPPDeductionGuide guide) { + if (guide.getFunctionBinding() instanceof ICPPFunctionTemplate) { + return CPP_DEDUCTION_GUIDE_TEMPLATE; + } else { + return CPP_DEDUCTION_GUIDE; + } } else if (binding instanceof ICPPFunction) { return CPPFUNCTION; } else if (binding instanceof ICPPUnknownBinding) { @@ -1403,6 +1416,10 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { return new PDOMCPPFieldTemplatePartialSpecialization(this, record); case CPP_ALIAS_TEMPLATE_SPECIALIZATION: return new PDOMCPPAliasTemplateSpecialization(this, record); + case CPP_DEDUCTION_GUIDE: + return new PDOMCPPDeductionGuide(this, record); + case CPP_DEDUCTION_GUIDE_TEMPLATE: + return new PDOMCPPDeductionGuideTemplate(this, record); } assert false : "nodeid= " + nodeType; //$NON-NLS-1$ return null;