1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-21 21:52:10 +02:00

Add basic support for c++17 deduction guides

This commit is contained in:
Igor V. Kovalenko 2023-03-27 22:49:10 +03:00 committed by Jonah Graham
parent aafb1d951a
commit f17675be16
25 changed files with 1017 additions and 59 deletions

View file

@ -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;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; 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.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.ICPPASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
@ -544,7 +545,10 @@ public class CModelBuilder2 implements IContributedModelBuilder {
return createTypeDef(parent, declSpecifier, declarator); return createTypeDef(parent, declSpecifier, declarator);
} }
IASTDeclarator typeRelevant = ASTQueries.findTypeRelevantDeclarator(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 createFunctionDeclaration(parent, declSpecifier, (IASTFunctionDeclarator) typeRelevant, isTemplate);
} }
return createVariable(parent, declSpecifier, declarator, isTemplate); return createVariable(parent, declSpecifier, declarator, isTemplate);

View file

@ -118,6 +118,7 @@ public interface IScope {
private boolean fPrefixLookup; private boolean fPrefixLookup;
private boolean fIgnorePointOfDeclaration; private boolean fIgnorePointOfDeclaration;
private boolean fArgumentDependent; private boolean fArgumentDependent;
private boolean fDeductionGuidesOnly = false;
public ScopeLookupData(IASTName name, boolean resolve, boolean prefixLookup) { public ScopeLookupData(IASTName name, boolean resolve, boolean prefixLookup) {
if (name == null) if (name == null)
@ -172,6 +173,11 @@ public interface IScope {
fArgumentDependent = argumentDependent; fArgumentDependent = argumentDependent;
} }
/** @since 8.1 */
public final void setDeductionGuidesOnly(boolean deductionGuidesOnly) {
fDeductionGuidesOnly = deductionGuidesOnly;
}
public final void setLookupKey(char[] key) { public final void setLookupKey(char[] key) {
fLookupKey = key; fLookupKey = key;
} }
@ -201,6 +207,11 @@ public interface IScope {
return fArgumentDependent; return fArgumentDependent;
} }
/** @since 8.1 */
public final boolean isDeductionGuidesOnly() {
return fDeductionGuidesOnly;
}
public final IIndexFileSet getIncludedFiles() { public final IIndexFileSet getIncludedFiles() {
return fTu == null ? IIndexFileSet.EMPTY : fTu.getIndexFileSet(); return fTu == null ? IIndexFileSet.EMPTY : fTu.getIndexFileSet();
} }

View file

@ -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 {
}

View file

@ -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 {
}

View file

@ -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 {
}

View file

@ -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 {
}

View file

@ -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();
}

View file

@ -253,6 +253,11 @@ public interface ICPPNodeFactory extends INodeFactory {
public ICPPASTFoldExpression newFoldExpression(int opToken, boolean isComma, IASTExpression lhs, public ICPPASTFoldExpression newFoldExpression(int opToken, boolean isComma, IASTExpression lhs,
IASTExpression rhs); IASTExpression rhs);
/**
* @since 8.1
*/
public ICPPASTDeductionGuide newDeductionGuide();
public ICPPASTLinkageSpecification newLinkageSpecification(String literal); public ICPPASTLinkageSpecification newLinkageSpecification(String literal);
@Override @Override

View file

@ -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 {
}

View file

@ -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);
}
}

View file

@ -73,13 +73,17 @@ public class CPPASTFunctionDeclarator extends CPPASTDeclarator implements ICPPAS
@Override @Override
public CPPASTFunctionDeclarator copy(CopyStyle style) { public CPPASTFunctionDeclarator copy(CopyStyle style) {
CPPASTFunctionDeclarator copy = new CPPASTFunctionDeclarator(); CPPASTFunctionDeclarator copy = new CPPASTFunctionDeclarator();
copy.varArgs = varArgs; return copy(copy, style);
copy.pureVirtual = pureVirtual; }
copy.isVolatile = isVolatile;
copy.isConst = isConst; protected <T extends CPPASTFunctionDeclarator> T copy(T copy, CopyStyle style) {
copy.isMutable = isMutable; copy.setVarArgs(varArgs);
copy.refQualifier = refQualifier; copy.setPureVirtual(pureVirtual);
copy.isConstexpr = isConstexpr; copy.setVolatile(isVolatile);
copy.setConst(isConst);
copy.setMutable(isMutable);
copy.setRefQualifier(refQualifier);
copy.setConstexpr(isConstexpr);
for (IASTParameterDeclaration param : getParameters()) { for (IASTParameterDeclaration param : getParameters()) {
copy.addParameterDeclaration(param == null ? null : param.copy(style)); copy.addParameterDeclaration(param == null ? null : param.copy(style));
@ -97,7 +101,7 @@ public class CPPASTFunctionDeclarator extends CPPASTDeclarator implements ICPPAS
for (ICPPASTVirtSpecifier virtSpecifier : getVirtSpecifiers()) { for (ICPPASTVirtSpecifier virtSpecifier : getVirtSpecifiers()) {
copy.addVirtSpecifier(virtSpecifier.copy(style)); copy.addVirtSpecifier(virtSpecifier.copy(style));
} }
return copy(copy, style); return super.copy(copy, style);
} }
@Override @Override

View file

@ -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());
}
}

View file

@ -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.ICPPASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclarator; 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.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.ICPPASTDeleteExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDesignatedInitializer; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDesignatedInitializer;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier; 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); return new CPPASTFoldExpression(operator, fIsComma, lhs, rhs);
} }
@Override
public ICPPASTDeductionGuide newDeductionGuide() {
return new CPPASTDeductionGuide();
}
@Override @Override
public ICPPASTLinkageSpecification newLinkageSpecification(String literal) { public ICPPASTLinkageSpecification newLinkageSpecification(String literal) {
return new CPPASTLinkageSpecification(literal); return new CPPASTLinkageSpecification(literal);

View file

@ -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.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId; 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.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.ICPPEnumScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope;
@ -226,6 +227,12 @@ abstract public class CPPScope implements ICPPASTInternalScope {
CCorePlugin.log(e); 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; binding = (IBinding) candidate;
} }
// Deduction guides are not visible to ordinary name lookup
if (lookup.isDeductionGuidesOnly() ^ binding instanceof ICPPDeductionGuide) {
return result;
}
if (binding != null) if (binding != null)
result = ArrayUtil.append(result, binding); result = ArrayUtil.append(result, binding);
return result; return result;

View file

@ -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.ICPPASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclarator; 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.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.ICPPASTDeleteExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDesignatedInitializer; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDesignatedInitializer;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDesignator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDesignator;
@ -2443,7 +2444,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
} }
if (LT(1) == IToken.tLPAREN) { if (LT(1) == IToken.tLPAREN) {
ICPPASTFunctionDeclarator dtor = functionDeclarator(true); ICPPASTFunctionDeclarator dtor = functionDeclarator((IASTName) null, (IASTDeclSpecifier) null, true);
lambdaExpr.setDeclarator(dtor); lambdaExpr.setDeclarator(dtor);
if (LT(1) == IToken.tEOC) if (LT(1) == IToken.tEOC)
return setRange(lambdaExpr, offset, calculateEndOffset(dtor)); return setRange(lambdaExpr, offset, calculateEndOffset(dtor));
@ -4292,7 +4293,10 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
private void verifyDtor(IASTDeclSpecifier declspec, IASTDeclarator dtor, DeclarationOptions opt) private void verifyDtor(IASTDeclSpecifier declspec, IASTDeclarator dtor, DeclarationOptions opt)
throws BacktrackException { throws BacktrackException {
if (CPPVisitor.doesNotSpecifyType(declspec)) { 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; boolean isQualified = false;
IASTName name = ASTQueries.findInnermostDeclarator(dtor).getName(); IASTName name = ASTQueries.findInnermostDeclarator(dtor).getName();
if (name instanceof ICPPASTQualifiedName) { if (name instanceof ICPPASTQualifiedName) {
@ -4373,7 +4377,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
*/ */
private IASTDeclarator initDeclarator(DtorStrategy strategy, IASTDeclSpecifier declspec, DeclarationOptions option) private IASTDeclarator initDeclarator(DtorStrategy strategy, IASTDeclSpecifier declspec, DeclarationOptions option)
throws EndOfFileException, BacktrackException, FoundAggregateInitializer { throws EndOfFileException, BacktrackException, FoundAggregateInitializer {
final IASTDeclarator dtor = declarator(strategy, option); final IASTDeclarator dtor = declarator(strategy, declspec, option);
if (option.fAllowInitializer) { if (option.fAllowInitializer) {
final IASTDeclarator typeRelevantDtor = ASTQueries.findTypeRelevantDeclarator(dtor); final IASTDeclarator typeRelevantDtor = ASTQueries.findTypeRelevantDeclarator(dtor);
if (option != DeclarationOptions.PARAMETER && typeRelevantDtor instanceof IASTFunctionDeclarator) { if (option != DeclarationOptions.PARAMETER && typeRelevantDtor instanceof IASTFunctionDeclarator) {
@ -4767,7 +4771,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
* @throws BacktrackException * @throws BacktrackException
* request a backtrack * request a backtrack
*/ */
protected IASTDeclarator declarator(DtorStrategy strategy, DeclarationOptions option) protected IASTDeclarator declarator(DtorStrategy strategy, IASTDeclSpecifier declspec, DeclarationOptions option)
throws EndOfFileException, BacktrackException { throws EndOfFileException, BacktrackException {
final int startingOffset = LA(1).getOffset(); final int startingOffset = LA(1).getOffset();
int endOffset = startingOffset; int endOffset = startingOffset;
@ -4810,7 +4814,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
final IASTName declaratorName = !option.fRequireSimpleName ? qualifiedName() : identifier(); final IASTName declaratorName = !option.fRequireSimpleName ? qualifiedName() : identifier();
endOffset = calculateEndOffset(declaratorName); endOffset = calculateEndOffset(declaratorName);
return declarator(pointerOps, hasEllipsis, declaratorName, null, startingOffset, endOffset, strategy, return declarator(pointerOps, hasEllipsis, declaratorName, null, startingOffset, endOffset, strategy,
option, attributes); declspec, option, attributes);
} }
if (lt1 == IToken.tLPAREN) { if (lt1 == IToken.tLPAREN) {
@ -4821,7 +4825,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
final IToken mark = mark(); final IToken mark = mark();
try { try {
cand1 = declarator(pointerOps, hasEllipsis, getNodeFactory().newName(), null, startingOffset, cand1 = declarator(pointerOps, hasEllipsis, getNodeFactory().newName(), null, startingOffset,
endOffset, strategy, option, attributes); endOffset, strategy, declspec, option, attributes);
if (option.fRequireAbstract || !option.fAllowNested || hasEllipsis) if (option.fRequireAbstract || !option.fAllowNested || hasEllipsis)
return cand1; return cand1;
@ -4835,7 +4839,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
if (!option.fAllowNested || hasEllipsis) { if (!option.fAllowNested || hasEllipsis) {
if (option.fAllowAbstract) { if (option.fAllowAbstract) {
return declarator(pointerOps, hasEllipsis, getNodeFactory().newName(), null, startingOffset, return declarator(pointerOps, hasEllipsis, getNodeFactory().newName(), null, startingOffset,
endOffset, strategy, option, attributes); endOffset, strategy, declspec, option, attributes);
} }
throwBacktrack(LA(1)); throwBacktrack(LA(1));
} }
@ -4846,10 +4850,10 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
if (LT(1) == IToken.tRPAREN) if (LT(1) == IToken.tRPAREN)
throwBacktrack(LA(1)); 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(); endOffset = consume(IToken.tRPAREN).getEndOffset();
final IASTDeclarator cand2 = declarator(pointerOps, hasEllipsis, getNodeFactory().newName(), nested, 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) if (cand1 == null || cand1End == null)
return cand2; return cand2;
final IToken cand2End = LA(1); final IToken cand2End = LA(1);
@ -4877,7 +4881,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
throwBacktrack(LA(1)); throwBacktrack(LA(1));
} }
return declarator(pointerOps, hasEllipsis, getNodeFactory().newName(), null, startingOffset, endOffset, 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<? extends IASTPointerOperator> pointerOps, boolean hasEllipsis, private IASTDeclarator declarator(List<? extends IASTPointerOperator> pointerOps, boolean hasEllipsis,
IASTName declaratorName, IASTDeclarator nestedDeclarator, int startingOffset, int endOffset, IASTName declaratorName, IASTDeclarator nestedDeclarator, int startingOffset, int endOffset,
DtorStrategy strategy, DeclarationOptions option, List<IASTAttributeSpecifier> attributes) DtorStrategy strategy, IASTDeclSpecifier declspec, DeclarationOptions option,
throws EndOfFileException, BacktrackException { List<IASTAttributeSpecifier> attributes) throws EndOfFileException, BacktrackException {
ICPPASTDeclarator result = null; ICPPASTDeclarator result = null;
loop: while (true) { loop: while (true) {
final int lt1 = LTcatchEOF(1); final int lt1 = LTcatchEOF(1);
switch (lt1) { switch (lt1) {
case IToken.tLPAREN: case IToken.tLPAREN:
if (option.fAllowFunctions && strategy == DtorStrategy.PREFER_FUNCTION) { if (option.fAllowFunctions && strategy == DtorStrategy.PREFER_FUNCTION) {
result = functionDeclarator(false); result = functionDeclarator(declaratorName, declspec, false);
setDeclaratorID(result, hasEllipsis, declaratorName, nestedDeclarator); setDeclaratorID(result, hasEllipsis, declaratorName, nestedDeclarator);
} }
break loop; break loop;
@ -5086,16 +5090,47 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
declarator.setDeclaresParameterPack(hasEllipsis); 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. * 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 { throws EndOfFileException, BacktrackException {
IToken last = consume(IToken.tLPAREN); IToken last = consume(IToken.tLPAREN);
final int startOffset = last.getOffset(); final int startOffset = last.getOffset();
int endOffset = last.getEndOffset(); int endOffset = last.getEndOffset();
final ICPPASTFunctionDeclarator fc = getNodeFactory().newFunctionDeclarator(null);
ICPPASTParameterDeclaration pd = null; ICPPASTParameterDeclaration pd = null;
paramLoop: while (true) { paramLoop: while (true) {
switch (LT(1)) { switch (LT(1)) {
@ -5245,7 +5280,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
endOffset = calculateEndOffset(typeId); endOffset = calculateEndOffset(typeId);
} }
return setRange(fc, startOffset, endOffset); setRange(fc, startOffset, endOffset);
} }
/** /**

View file

@ -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.ICPPAliasTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase; 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.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.ICPPClassScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization; 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.ICPPClassTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecialization; 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.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; 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.ICPPDeferredFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; 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.ICPPTemplateScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTemplateParameter; 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.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.ICPPUsingDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDirective; import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDirective;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable; 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.CPPCompositeBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPDeferredConstructor; 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.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.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.CPPImplicitFunction;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPNamespace; 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.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.CPPPointerType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPReferenceType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPReferenceType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPScope; 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 char[] CALL_FUNCTION = "call-function".toCharArray(); //$NON-NLS-1$
private static final ICPPEvaluation[] NO_INITCLAUSE_EVALUATION = {}; private static final ICPPEvaluation[] NO_INITCLAUSE_EVALUATION = {};
public static final IUnaryPredicate<IBinding> opIsDeductionGuide = (argument) -> {
return argument instanceof ICPPDeductionGuide;
};
public static final IUnaryPredicate<IBinding> opIsNotDeductionGuide = (argument) -> {
return !(argument instanceof ICPPDeductionGuide);
};
// Set to true for debugging. // Set to true for debugging.
public static boolean traceBindingResolution = false; public static boolean traceBindingResolution = false;
public static int traceIndent = 0; public static int traceIndent = 0;
@ -399,6 +415,289 @@ public class CPPSemantics {
return postResolution(binding, data); 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) { private static IBinding postResolution(IBinding binding, LookupData data) {
final IASTName lookupName = data.getLookupName(); final IASTName lookupName = data.getLookupName();
if (lookupName == null) if (lookupName == null)
@ -468,40 +767,119 @@ public class CPPSemantics {
*/ */
if (binding instanceof ICPPClassTemplate && !(binding instanceof ICPPClassSpecialization) if (binding instanceof ICPPClassTemplate && !(binding instanceof ICPPClassSpecialization)
&& !(binding instanceof ICPPTemplateParameter) && !(lookupName instanceof ICPPASTTemplateId)) { && !(binding instanceof ICPPTemplateParameter) && !(lookupName instanceof ICPPASTTemplateId)) {
ASTNodeProperty prop = lookupName.getPropertyInParent(); ASTNodeProperty prop = lookupName.getPropertyInParent();
if (prop != ICPPASTTemplateId.TEMPLATE_NAME && !lookupName.isQualified()) { if (prop != ICPPASTTemplateId.TEMPLATE_NAME) {
// You cannot use a class template name outside of the class template scope, if (!lookupName.isQualified()) {
// mark it as a problem. // You cannot use a class template name outside of the class template scope,
IBinding user = CPPTemplates.isUsedInClassTemplateScope((ICPPClassTemplate) binding, lookupName); // mark it as a problem - unless Class Template Argument Deduction needs to be done
if (user instanceof ICPPClassTemplate) { IBinding user = CPPTemplates.isUsedInClassTemplateScope((ICPPClassTemplate) binding, lookupName);
binding = ((ICPPClassTemplate) user).asDeferredInstance(); if (user instanceof ICPPClassTemplate) {
} else if (user != null) { binding = ((ICPPClassTemplate) user).asDeferredInstance();
binding = user; } else if (user != null) {
} else { binding = user;
boolean ok = false; } else {
IASTNode node = lookupName.getParent(); // Attempt class template argument deduction if appropriate
while (node != null && !ok) { if (data.getTranslationUnit().getEnableClassTemplateArgumentDeduction()) {
if (node instanceof ICPPASTTemplateId if (lookupName.getParent() instanceof IASTIdExpression idExpression
|| node instanceof ICPPASTTemplatedTypeTemplateParameter) { && idExpression.getPropertyInParent() == IASTFunctionCallExpression.FUNCTION_NAME) {
ok = true; // Can be argument or default-value for template template parameter
break; // Class name for class type argument deduction is a type
} else if (node instanceof IASTElaboratedTypeSpecifier) { return doClassTemplateArgumentDeduction((ICPPClassTemplate) binding, data);
IASTNode parent = node.getParent(); }
if (parent instanceof IASTSimpleDeclaration) { }
IASTDeclSpecifier declspec = ((IASTSimpleDeclaration) parent).getDeclSpecifier(); boolean ok = false;
if (declspec instanceof ICPPASTDeclSpecifier) { // Attempt class template argument deduction if appropriate
if (((ICPPASTDeclSpecifier) declspec).isFriend()) { if (data.getTranslationUnit().getEnableClassTemplateArgumentDeduction()
ok = true; // A friend class template declarations uses resolution. && lookupName.getParent() instanceof IASTNamedTypeSpecifier namedTypeSpecifier
break; && 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, } else {
data.getFoundBindings()); // 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); return expandUsingDeclarationsAndRemoveObjects(bindings, data);
} }
@ -1863,8 +2247,9 @@ public class CPPSemantics {
declarator = declarator.getNestedDeclarator(); declarator = declarator.getNestedDeclarator();
} }
if (innermost != null) { if (innermost != null) {
IASTName declaratorName = innermost.getName(); // NOTE This now may include deduction guides which are filtered later during lookup
ASTInternal.addName(scope, declaratorName); IASTName declaratorOrDeductionGuideName = innermost.getName();
ASTInternal.addName(scope, declaratorOrDeductionGuideName);
} }
} }
} }

View file

@ -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.ICPPASTConversionName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier; 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.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.ICPPASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTEnumerationSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTEnumerationSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation; 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.CPPClosureType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPConstructor; 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.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.CPPEnumeration;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPEnumerator; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPEnumerator;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPField; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPField;
@ -883,6 +885,7 @@ public class CPPVisitor extends ASTQueries {
binding = scope.getBinding(name, forceResolve); binding = scope.getBinding(name, forceResolve);
} }
boolean isDeductionGuide = false;
boolean isFunction = false; boolean isFunction = false;
if (parent instanceof ICPPASTFunctionDefinition) { if (parent instanceof ICPPASTFunctionDefinition) {
isFunction = true; isFunction = true;
@ -908,6 +911,9 @@ public class CPPVisitor extends ASTQueries {
binding = td; binding = td;
} else if (typeRelevantDtor instanceof IASTFunctionDeclarator) { } else if (typeRelevantDtor instanceof IASTFunctionDeclarator) {
// Function declaration via function declarator. // Function declaration via function declarator.
if (typeRelevantDtor instanceof ICPPASTDeductionGuide) {
isDeductionGuide = true;
}
isFunction = true; isFunction = true;
} else { } else {
// Looks like a variable declaration. // Looks like a variable declaration.
@ -991,9 +997,15 @@ public class CPPVisitor extends ASTQueries {
} else { } else {
binding = template ? (ICPPFunction) new CPPFunctionTemplate(name) : new CPPFunction(typeRelevantDtor); binding = template ? (ICPPFunction) new CPPFunctionTemplate(name) : new CPPFunction(typeRelevantDtor);
} }
binding = CPPSemantics.checkDeclSpecifier(binding, name, parent);
if (isFriendDecl && scope instanceof IASTInternalScope) { if (isDeductionGuide) {
((IASTInternalScope) scope).addBinding(binding); 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; return autoInitClause;
} }
private static ICPPASTInitializerClause getAutoInitClauseForDeclarator(IASTDeclarator declarator) { protected static ICPPASTInitializerClause getAutoInitClauseForDeclarator(IASTDeclarator declarator) {
IASTInitializer initClause = declarator.getInitializer(); IASTInitializer initClause = declarator.getInitializer();
return getInitClauseForInitializer(initClause); return getInitClauseForInitializer(initClause);
} }

View file

@ -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.IBinding;
import org.eclipse.cdt.core.dom.ast.IFunction; import org.eclipse.cdt.core.dom.ast.IFunction;
import org.eclipse.cdt.core.dom.ast.IType; 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.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.ICPPFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionTemplate; 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.ICPPFunctionType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; 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.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.OverloadableOperator;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates.TypeSelection; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates.TypeSelection;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.DeferredUDC; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.DeferredUDC;
@ -195,6 +199,10 @@ class FunctionCost {
if (cmp != 0) if (cmp != 0)
return cmp; return cmp;
cmp = compareAsDeductionGuides(f1, f2);
if (cmp != 0)
return cmp;
// At this point prefer non-index bindings // At this point prefer non-index bindings
return -CPPSemantics.compareByRelevance(tu, f1, f2); return -CPPSemantics.compareByRelevance(tu, f1, f2);
} }
@ -205,6 +213,43 @@ class FunctionCost {
return 1; 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) { private int overridesUsingDeclaration(ICPPFunction f1, ICPPFunction f2) {
if (f1.takesVarArgs() != f2.takesVarArgs()) if (f1.takesVarArgs() != f2.takesVarArgs())
return 0; return 0;

View file

@ -77,4 +77,6 @@ public interface IIndexCPPBindingConstants {
int CPP_FIELD_TEMPLATE_PARTIAL_SPECIALIZATION = IIndexBindingConstants.LAST_CONSTANT + 60; int CPP_FIELD_TEMPLATE_PARTIAL_SPECIALIZATION = IIndexBindingConstants.LAST_CONSTANT + 60;
int CPP_DEFERRED_VARIABLE_INSTANCE = IIndexBindingConstants.LAST_CONSTANT + 61; int CPP_DEFERRED_VARIABLE_INSTANCE = IIndexBindingConstants.LAST_CONSTANT + 61;
int CPP_ALIAS_TEMPLATE_SPECIALIZATION = IIndexBindingConstants.LAST_CONSTANT + 62; 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;
} }

View file

@ -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.ICPPClassTemplatePartialSpecializationSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; 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.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.ICPPEnumScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumeration; 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.ICPPField;
@ -753,6 +754,8 @@ public class CPPCompositesFactory extends AbstractCompositeFactory {
return new CompositeCPPConstructorTemplate(this, (ICPPConstructor) binding); return new CompositeCPPConstructorTemplate(this, (ICPPConstructor) binding);
} else if (binding instanceof ICPPMethod) { } else if (binding instanceof ICPPMethod) {
return new CompositeCPPMethodTemplate(this, (ICPPMethod) binding); return new CompositeCPPMethodTemplate(this, (ICPPMethod) binding);
} else if (binding instanceof ICPPDeductionGuide guide) {
return new CompositeCPPDeductionGuideTemplate(this, guide);
} else if (binding instanceof ICPPFunctionTemplate) { } else if (binding instanceof ICPPFunctionTemplate) {
return new CompositeCPPFunctionTemplate(this, (ICPPFunction) binding); return new CompositeCPPFunctionTemplate(this, (ICPPFunction) binding);
} else if (binding instanceof ICPPAliasTemplate) { } else if (binding instanceof ICPPAliasTemplate) {
@ -810,6 +813,8 @@ public class CPPCompositesFactory extends AbstractCompositeFactory {
} else if (binding instanceof ICPPEnumeration) { } else if (binding instanceof ICPPEnumeration) {
ICPPEnumeration def = (ICPPEnumeration) findOneBinding(binding); ICPPEnumeration def = (ICPPEnumeration) findOneBinding(binding);
result = def == null ? null : new CompositeCPPEnumeration(this, def); result = def == null ? null : new CompositeCPPEnumeration(this, def);
} else if (binding instanceof ICPPDeductionGuide guide) {
result = new CompositeCPPDeductionGuide(this, guide);
} else if (binding instanceof ICPPFunction) { } else if (binding instanceof ICPPFunction) {
result = new CompositeCPPFunction(this, (ICPPFunction) binding); result = new CompositeCPPFunction(this, (ICPPFunction) binding);
} else if (binding instanceof ICPPInternalEnumerator) { } else if (binding instanceof ICPPInternalEnumerator) {

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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.ICPPClassTemplatePartialSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; 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.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.ICPPEnumeration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFieldTemplate; 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) { if (parent instanceof PDOMCPPClassType || parent instanceof PDOMCPPClassSpecialization) {
pdomBinding = new PDOMCPPMethod(this, parent, (ICPPMethod) binding); 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) { } else if (binding instanceof ICPPFunction) {
pdomBinding = new PDOMCPPFunction(this, parent, (ICPPFunction) binding, true); pdomBinding = new PDOMCPPFunction(this, parent, (ICPPFunction) binding, true);
} else if (binding instanceof ICPPNamespaceAlias) { } else if (binding instanceof ICPPNamespaceAlias) {
@ -1137,6 +1144,12 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
} else if (binding instanceof ICPPMethod) { } else if (binding instanceof ICPPMethod) {
// this must be before functions // this must be before functions
return CPPMETHOD; 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) { } else if (binding instanceof ICPPFunction) {
return CPPFUNCTION; return CPPFUNCTION;
} else if (binding instanceof ICPPUnknownBinding) { } else if (binding instanceof ICPPUnknownBinding) {
@ -1403,6 +1416,10 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
return new PDOMCPPFieldTemplatePartialSpecialization(this, record); return new PDOMCPPFieldTemplatePartialSpecialization(this, record);
case CPP_ALIAS_TEMPLATE_SPECIALIZATION: case CPP_ALIAS_TEMPLATE_SPECIALIZATION:
return new PDOMCPPAliasTemplateSpecialization(this, record); 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$ assert false : "nodeid= " + nodeType; //$NON-NLS-1$
return null; return null;