1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-08 02:06:01 +02:00

Bug 519361: wrap template<auto> types for better type resolution

https://bugs.eclipse.org/bugs/show_bug.cgi?id=519361#c28

Change-Id: I0a2f5479bb853ca26156be5b22673abdc158efab
Signed-off-by: Vlad Ivanov <vlad@ivanov.email>
This commit is contained in:
Vlad Ivanov 2018-05-11 09:54:09 +03:00 committed by Nathan Ridge
parent c16a31325b
commit 809aa57076
6 changed files with 112 additions and 3 deletions

View file

@ -0,0 +1,50 @@
/*******************************************************************************
* Copyright (c) 2018 Vlad Ivanov
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Vlad Ivanov (LabSystems) - Initial implementation
*******************************************************************************/
package org.eclipse.cdt.core.parser.tests.ast2.cxx17;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.IVariable;
import org.eclipse.cdt.internal.index.tests.IndexBindingResolutionTestBase;
public class TemplateAutoIndexTests extends IndexBindingResolutionTestBase {
public TemplateAutoIndexTests() {
setStrategy(new SinglePDOMTestStrategy(true));
}
// template<typename Type, Type v>
// struct helper {
// static Type call() {
// return nullptr;
// }
// };
//
// template<auto F>
// class call_helper {
// using functor_t = decltype(F);
//
// public:
// using type = helper<functor_t, F>;
// };
// struct Something {
// void foo() {}
// };
//
// using A = call_helper<&Something::foo>::type;
// auto waldo = A::call();
public void testTemplateAutoIndex() throws Exception {
BindingAssertionHelper helper = getAssertionHelper();
IVariable variable = helper.assertNonProblem("waldo");
IType variableType = variable.getType();
assertEquals("void (Something::*)()", variableType.toString());
}
}

View file

@ -47,4 +47,29 @@ public class TemplateAutoTests extends AST2CPPTestBase {
public void testTemplateNontypeParameterTypeDeductionParsing_519361_2() throws Exception { public void testTemplateNontypeParameterTypeDeductionParsing_519361_2() throws Exception {
parseAndCheckBindings(); parseAndCheckBindings();
} }
// template<typename Type, Type v>
// struct helper {
// static void call() {}
// };
//
// template<auto F>
// class call_helper {
// using functor_t = decltype(F);
//
// public:
// using type = helper<functor_t, F>;
// };
//
// struct Something {
// void foo() {}
// };
//
// void test() {
// using A = call_helper<&Something::foo>::type;
// A::call();
// }
public void testTemplateNontypeParameterTypeDeductionParsing_519361_3() throws Exception {
parseAndCheckBindings();
}
} }

View file

@ -13,6 +13,7 @@ package org.eclipse.cdt.internal.index.tests;
import org.eclipse.cdt.core.parser.tests.ast2.cxx14.GenericLambdaIndexTests; import org.eclipse.cdt.core.parser.tests.ast2.cxx14.GenericLambdaIndexTests;
import org.eclipse.cdt.core.parser.tests.ast2.cxx14.ReturnTypeDeductionIndexTests; import org.eclipse.cdt.core.parser.tests.ast2.cxx14.ReturnTypeDeductionIndexTests;
import org.eclipse.cdt.core.parser.tests.ast2.cxx17.TemplateAutoIndexTests;
import junit.framework.Test; import junit.framework.Test;
import junit.framework.TestSuite; import junit.framework.TestSuite;
@ -42,6 +43,9 @@ public class IndexTests extends TestSuite {
suite.addTestSuite(ReturnTypeDeductionIndexTests.class); suite.addTestSuite(ReturnTypeDeductionIndexTests.class);
suite.addTestSuite(GenericLambdaIndexTests.class); suite.addTestSuite(GenericLambdaIndexTests.class);
// C++17 index test suites
suite.addTestSuite(TemplateAutoIndexTests.class);
IndexCPPBindingResolutionBugs.addTests(suite); IndexCPPBindingResolutionBugs.addTests(suite);
IndexCPPBindingResolutionTest.addTests(suite); IndexCPPBindingResolutionTest.addTests(suite);
IndexGPPBindingResolutionTest.addTests(suite); IndexGPPBindingResolutionTest.addTests(suite);

View file

@ -28,7 +28,10 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter;
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.IntegralValue;
import org.eclipse.cdt.internal.core.dom.parser.ValueFactory; import org.eclipse.cdt.internal.core.dom.parser.ValueFactory;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPDependentEvaluation;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.TypeOfDependentExpression;
/** /**
* Binding for a non-type template parameter. * Binding for a non-type template parameter.
@ -110,6 +113,14 @@ public class CPPTemplateNonTypeParameter extends CPPTemplateParameter
} }
parent= parent.getParent(); parent= parent.getParent();
} }
// C++17 template<auto>
if (type instanceof CPPPlaceholderType) {
CPPDependentEvaluation eval = new EvalBinding(this, null, getPrimaryDeclaration());
TypeOfDependentExpression replacementType = new TypeOfDependentExpression(eval);
replacementType.setForTemplateAuto(true);
type = replacementType;
}
} }
return type; return type;
} }

View file

@ -2883,10 +2883,13 @@ public class CPPTemplates {
return null; return null;
} }
if (paramType instanceof CPPPlaceholderType) { if (paramType instanceof TypeOfDependentExpression) {
// Partial support for C++17 template <auto> // Partial support for C++17 template <auto>
TypeOfDependentExpression type = (TypeOfDependentExpression) paramType;
if (type.isForTemplateAuto()) {
return arg; return arg;
} }
}
Cost cost = Conversions.checkImplicitConversionSequence(p, a, LVALUE, UDCMode.FORBIDDEN, Cost cost = Conversions.checkImplicitConversionSequence(p, a, LVALUE, UDCMode.FORBIDDEN,
Context.ORDINARY); Context.ORDINARY);

View file

@ -29,6 +29,7 @@ public class TypeOfDependentExpression extends CPPUnknownBinding implements ICPP
private final ICPPEvaluation fEvaluation; private final ICPPEvaluation fEvaluation;
// Whether this represents a decltype(expr), or a dependent type in another context. // Whether this represents a decltype(expr), or a dependent type in another context.
private boolean fIsForDecltype; private boolean fIsForDecltype;
private boolean fIsForTemplateAuto;
public TypeOfDependentExpression(ICPPEvaluation evaluation) { public TypeOfDependentExpression(ICPPEvaluation evaluation) {
this(evaluation, true); this(evaluation, true);
@ -38,6 +39,7 @@ public class TypeOfDependentExpression extends CPPUnknownBinding implements ICPP
super(null); super(null);
fEvaluation = evaluation; fEvaluation = evaluation;
fIsForDecltype = isForDecltype; fIsForDecltype = isForDecltype;
fIsForTemplateAuto = false;
} }
public ICPPEvaluation getEvaluation() { public ICPPEvaluation getEvaluation() {
@ -52,6 +54,14 @@ public class TypeOfDependentExpression extends CPPUnknownBinding implements ICPP
fIsForDecltype = isForDecltype; fIsForDecltype = isForDecltype;
} }
public boolean isForTemplateAuto() {
return fIsForTemplateAuto;
}
public void setForTemplateAuto(boolean isForTemplateAuto) {
fIsForTemplateAuto = isForTemplateAuto;
}
@Override @Override
public boolean isSameType(IType type) { public boolean isSameType(IType type) {
return type instanceof TypeOfDependentExpression return type instanceof TypeOfDependentExpression
@ -80,6 +90,9 @@ public class TypeOfDependentExpression extends CPPUnknownBinding implements ICPP
if (fIsForDecltype) { if (fIsForDecltype) {
firstBytes |= ITypeMarshalBuffer.FLAG1; firstBytes |= ITypeMarshalBuffer.FLAG1;
} }
if (fIsForTemplateAuto) {
firstBytes |= ITypeMarshalBuffer.FLAG2;
}
buffer.putShort(firstBytes); buffer.putShort(firstBytes);
buffer.marshalEvaluation(fEvaluation, false); buffer.marshalEvaluation(fEvaluation, false);
} }
@ -88,7 +101,10 @@ public class TypeOfDependentExpression extends CPPUnknownBinding implements ICPP
ICPPEvaluation eval= buffer.unmarshalEvaluation(); ICPPEvaluation eval= buffer.unmarshalEvaluation();
if (eval != null) { if (eval != null) {
boolean isForDecltype = (firstBytes & ITypeMarshalBuffer.FLAG1) != 0; boolean isForDecltype = (firstBytes & ITypeMarshalBuffer.FLAG1) != 0;
return new TypeOfDependentExpression(eval, isForDecltype); boolean isForTemplateAuto = (firstBytes & ITypeMarshalBuffer.FLAG2) != 0;
TypeOfDependentExpression expression = new TypeOfDependentExpression(eval, isForDecltype);
expression.setForTemplateAuto(isForTemplateAuto);
return expression;
} }
return ProblemType.UNKNOWN_FOR_EXPRESSION; return ProblemType.UNKNOWN_FOR_EXPRESSION;
} }