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:
parent
dd3a45bcdf
commit
5890732542
5 changed files with 127 additions and 7 deletions
|
@ -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;
|
||||
// }
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue