1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-23 17:05:26 +02:00

Bug 495091 - Name resolution problem with list initialization

Bug 495227 - Implicit constructor call with list initializer is resolved
incorrectly

Change-Id: Ia163585277a7a9af85fd414d2ece43f10aef18e5
This commit is contained in:
Sergey Prigogin 2016-06-03 17:51:02 -07:00
parent dd3a45bcdf
commit 5890732542
5 changed files with 127 additions and 7 deletions

View file

@ -8899,6 +8899,34 @@ public class AST2CPPTests extends AST2TestBase {
parseAndCheckBindings();
}
// struct A {
// A();
// A(int);
// A(int, int);
// };
//
// void test() {
// A{};
// A{1};
// A{1, 2};
// }
public void testListInitializer_495227() throws Exception {
parseAndCheckBindings();
BindingAssertionHelper ah = getAssertionHelper();
IASTImplicitName name = ah.findImplicitName("A{}", 1);
IBinding binding = name.resolveBinding();
assertTrue(binding instanceof ICPPConstructor);
assertEquals(0, ((ICPPConstructor) binding).getType().getParameterTypes().length);
name = ah.findImplicitName("A{1}", 1);
binding = name.resolveBinding();
assertTrue(binding instanceof ICPPConstructor);
assertEquals(1, ((ICPPConstructor) binding).getType().getParameterTypes().length);
name = ah.findImplicitName("A{1, 2}", 1);
binding = name.resolveBinding();
assertTrue(binding instanceof ICPPConstructor);
assertEquals(2, ((ICPPConstructor) binding).getType().getParameterTypes().length);
}
// namespace std {
// template<typename T> class initializer_list;
// }

View file

@ -9436,7 +9436,7 @@ public class AST2TemplateTests extends AST2TestBase {
public void testRecursiveTemplateClass_484786() throws Exception {
parseAndCheckBindings();
}
// template <typename T>
// struct S {
// static const bool value = true;
@ -9448,4 +9448,30 @@ public class AST2TemplateTests extends AST2TestBase {
public void testDisambiguationInNoexceptSpecifier_467332() throws Exception {
parseAndCheckBindings();
}
// template<typename T, typename U>
// struct is_same {};
//
// template<typename T>
// struct is_same<T, T> {
// constexpr operator bool() { return true; }
// };
//
// template<bool>
// struct enable_if {};
//
// template<>
// struct enable_if<true> {
// typedef void type;
// };
//
// template <typename T>
// typename enable_if<is_same<T, T>{}>::type waldo(T p);
//
// void test() {
// waldo(1);
// }
public void testListInitialization_495091() throws Exception {
parseAndCheckBindings();
}
}

View file

@ -2730,9 +2730,15 @@ public class CPPTemplates {
}
return null;
}
Cost cost = Conversions.checkImplicitConversionSequence(p, a, LVALUE, UDCMode.FORBIDDEN, Context.ORDINARY, point);
if (cost == null || !cost.converts())
return null;
Cost cost = Conversions.checkImplicitConversionSequence(p, a, LVALUE, UDCMode.FORBIDDEN,
Context.ORDINARY, point);
if (cost == null || !cost.converts()) {
ICPPEvaluation eval = arg.getNonTypeEvaluation();
ICPPEvaluation newEval = CPPEvaluation.maybeApplyConversion(eval, p, point);
if (newEval == EvalFixed.INCOMPLETE && newEval != eval)
return null;
return new CPPTemplateNonTypeArgument(newEval, point);
}
return new CPPTemplateNonTypeArgument(arg.getNonTypeValue(), paramType);
}

View file

@ -19,6 +19,7 @@ import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.IValue;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameterPackType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation;
@ -109,7 +110,8 @@ public class EvalFixed extends CPPEvaluation {
@Override
public boolean isConstantExpression(IASTNode point) {
return isConstexprValue(fValue, point);
return (fType instanceof ICPPClassType && TypeTraits.isEmpty(fType, point))
|| isConstexprValue(fValue, point);
}
@Override

View file

@ -22,16 +22,21 @@ import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.IValue;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate;
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.ICPPFunction;
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.ICPPTemplateParameterMap;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation;
import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer;
import org.eclipse.cdt.internal.core.dom.parser.Value;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunction;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper.MethodKind;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation;
import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext;
import org.eclipse.core.runtime.CoreException;
@ -170,10 +175,30 @@ public class EvalTypeId extends CPPDependentEvaluation {
IType simplifiedType = SemanticUtil.getNestedType(fInputType, SemanticUtil.TDEF);
if (simplifiedType instanceof ICPPClassType) {
ICPPClassType classType = (ICPPClassType) simplifiedType;
LookupData data = new LookupData(classType.getNameCharArray(), null, point);
ICPPEvaluation[] arguments = fArguments;
ICPPConstructor[] constructors = ClassTypeHelper.getConstructors(classType, point);
if (arguments.length == 1 && arguments[0] instanceof EvalInitList) {
// List-initialization of a class (dcl.init.list-3).
if (TypeTraits.isAggregateClass(classType, point)) {
// Pretend that aggregate initialization is calling the default constructor.
return findDefaultConstructor(classType, constructors);
}
if (((EvalInitList) arguments[0]).getClauses().length == 0) {
ICPPMethod ctor = findDefaultConstructor(classType, constructors);
if (ctor != null)
return ctor;
}
ICPPConstructor[] ctors = getInitializerListConstructors(constructors, point);
if (ctors.length != 0) {
constructors = ctors;
} else {
arguments = ((EvalInitList) arguments[0]).getClauses();
}
}
LookupData data = new LookupData(classType.getNameCharArray(), null, point);
data.foundItems = constructors;
data.setFunctionArguments(false, fArguments);
data.setFunctionArguments(false, arguments);
try {
IBinding binding = CPPSemantics.resolveFunction(data, constructors, true);
if (binding instanceof ICPPFunction) {
@ -186,6 +211,39 @@ public class EvalTypeId extends CPPDependentEvaluation {
return null;
}
private ICPPConstructor findDefaultConstructor(ICPPClassType classType, ICPPConstructor[] constructors) {
for (ICPPConstructor ctor : constructors) {
if (ctor.isImplicit() && ClassTypeHelper.getMethodKind(classType, ctor) == MethodKind.DEFAULT_CTOR)
return ctor;
}
return null;
}
/**
* Returns constructors that can be called by passing a single {@code std::initializer_list}
* as an argument.
*/
private ICPPConstructor[] getInitializerListConstructors(ICPPConstructor[] constructors, IASTNode point) {
ICPPConstructor[] result = ICPPConstructor.EMPTY_CONSTRUCTOR_ARRAY;
ICPPClassTemplate template = CPPVisitor.get_initializer_list(point);
for (ICPPConstructor ctor : constructors) {
if (ctor.getRequiredArgumentCount() <= 1) {
IType[] parameterTypes = ctor.getType().getParameterTypes();
if (parameterTypes.length != 0) {
IType type = parameterTypes[0];
if (type instanceof ICPPSpecialization) {
IBinding specialized = ((ICPPSpecialization) type).getSpecializedBinding();
if (specialized instanceof ICPPClassTemplate
&& template.isSameType((IType) specialized)) {
result = ArrayUtil.append(result, ctor);
}
}
}
}
}
return ArrayUtil.trim(result);
}
@Override
public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException {
short firstBytes = ITypeMarshalBuffer.EVAL_TYPE_ID;