mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 14:42:11 +02:00
Bug 508254 - Improve handling of braced-init-lists
Also avoid several exceptions in related codepaths. Change-Id: I528a123daff090033285f0ed930ac5b822100974
This commit is contained in:
parent
63e6688940
commit
cf6c25ae47
5 changed files with 76 additions and 24 deletions
|
@ -1517,6 +1517,35 @@ public class IndexCPPBindingResolutionTest extends IndexBindingResolutionTestBas
|
||||||
IFunction f2= getBindingFromASTName("f(b)", 1, IFunction.class);
|
IFunction f2= getBindingFromASTName("f(b)", 1, IFunction.class);
|
||||||
assertFalse(f1.equals(f2));
|
assertFalse(f1.equals(f2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// struct Params {
|
||||||
|
// constexpr Params(int, int) {}
|
||||||
|
// };
|
||||||
|
// struct Desc {
|
||||||
|
// Desc(const Params*, int = 0);
|
||||||
|
// };
|
||||||
|
// struct Descs {
|
||||||
|
// Desc a;
|
||||||
|
// Desc b[2];
|
||||||
|
// };
|
||||||
|
// struct S {
|
||||||
|
// static Descs waldo;
|
||||||
|
// };
|
||||||
|
// constexpr Params params[1] = {
|
||||||
|
// { 0, 0 },
|
||||||
|
// };
|
||||||
|
// struct Descs S::waldo = {
|
||||||
|
// {nullptr},
|
||||||
|
// {
|
||||||
|
// {params, 0},
|
||||||
|
// {params, 0},
|
||||||
|
// },
|
||||||
|
// };
|
||||||
|
|
||||||
|
// // empty file
|
||||||
|
public void testArrayWithOneElement_508254() throws Exception {
|
||||||
|
checkBindings();
|
||||||
|
}
|
||||||
|
|
||||||
// class A {
|
// class A {
|
||||||
// class B;
|
// class B;
|
||||||
|
|
|
@ -113,6 +113,10 @@ public final class CompositeValue implements IValue {
|
||||||
// Array size is dependent. TODO: Handle this?
|
// Array size is dependent. TODO: Handle this?
|
||||||
return IntegralValue.UNKNOWN;
|
return IntegralValue.UNKNOWN;
|
||||||
}
|
}
|
||||||
|
// More initializers than array members
|
||||||
|
if (arraySize.intValue() < initList.getClauses().length) {
|
||||||
|
return IntegralValue.ERROR;
|
||||||
|
}
|
||||||
IType elementType = type.getType();
|
IType elementType = type.getType();
|
||||||
ICPPEvaluation[] values = new ICPPEvaluation[arraySize.intValue()];
|
ICPPEvaluation[] values = new ICPPEvaluation[arraySize.intValue()];
|
||||||
for (int i = 0; i < initList.getClauses().length; i++) {
|
for (int i = 0; i < initList.getClauses().length; i++) {
|
||||||
|
|
|
@ -92,12 +92,10 @@ public class EvalInitList extends CPPDependentEvaluation {
|
||||||
if (isValueDependent()) {
|
if (isValueDependent()) {
|
||||||
return DependentValue.create(this);
|
return DependentValue.create(this);
|
||||||
}
|
}
|
||||||
if (getClauses().length > 1) {
|
if (getClauses().length >= 1) {
|
||||||
return CompositeValue.create(this);
|
return CompositeValue.create(this);
|
||||||
}
|
}
|
||||||
else if (getClauses().length == 1) {
|
else {
|
||||||
return DependentValue.create(getClauses()[0]);
|
|
||||||
} else {
|
|
||||||
return IntegralValue.UNKNOWN;
|
return IntegralValue.UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,9 +137,6 @@ public class EvalInitList extends CPPDependentEvaluation {
|
||||||
@Override
|
@Override
|
||||||
public ICPPEvaluation computeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) {
|
public ICPPEvaluation computeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) {
|
||||||
ICPPEvaluation[] clauses = fClauses;
|
ICPPEvaluation[] clauses = fClauses;
|
||||||
if (fClauses.length == 1) {
|
|
||||||
return fClauses[0].computeForFunctionCall(record, context.recordStep());
|
|
||||||
}
|
|
||||||
for (int i = 0; i < fClauses.length; i++) {
|
for (int i = 0; i < fClauses.length; i++) {
|
||||||
ICPPEvaluation clause = fClauses[i].computeForFunctionCall(record, context.recordStep());
|
ICPPEvaluation clause = fClauses[i].computeForFunctionCall(record, context.recordStep());
|
||||||
if (clause != fClauses[i]) {
|
if (clause != fClauses[i]) {
|
||||||
|
|
|
@ -13,6 +13,7 @@ import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUti
|
||||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF;
|
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
|
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
import org.eclipse.cdt.core.dom.ast.IArrayType;
|
import org.eclipse.cdt.core.dom.ast.IArrayType;
|
||||||
import org.eclipse.cdt.core.dom.ast.IPointerType;
|
import org.eclipse.cdt.core.dom.ast.IPointerType;
|
||||||
import org.eclipse.cdt.core.dom.ast.IType;
|
import org.eclipse.cdt.core.dom.ast.IType;
|
||||||
|
@ -62,26 +63,45 @@ public final class ExecDeclarator implements ICPPExecution {
|
||||||
return declaredBinding;
|
return declaredBinding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static ICPPEvaluation maybeUnwrapInitList(ICPPEvaluation eval, IType targetType, IASTNode point) {
|
||||||
|
// Only 1-element initializer lists are eligible for unwrapping.
|
||||||
|
if (!(eval instanceof EvalInitList)) {
|
||||||
|
return eval;
|
||||||
|
}
|
||||||
|
EvalInitList initList = (EvalInitList) eval;
|
||||||
|
if (initList.getClauses().length != 1) {
|
||||||
|
return eval;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Never unwrap initializers for array types.
|
||||||
|
if (isArrayType(targetType)) {
|
||||||
|
return eval;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only unwrap initializers for class types if the type of the initializer
|
||||||
|
// element matches the class type, indicating that we're calling the
|
||||||
|
// implicit copy constructor (as opposed to doing memberwise initialization).
|
||||||
|
if (isClassType(targetType)) {
|
||||||
|
if (!initList.getClauses()[0].getType(point).isSameType(targetType)) {
|
||||||
|
return eval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise unwrap.
|
||||||
|
return initList.getClauses()[0];
|
||||||
|
}
|
||||||
|
|
||||||
private ICPPEvaluation createInitialValue(IType type, ActivationRecord record, ConstexprEvaluationContext context) {
|
private ICPPEvaluation createInitialValue(IType type, ActivationRecord record, ConstexprEvaluationContext context) {
|
||||||
if (initializerEval == null) {
|
if (initializerEval == null) {
|
||||||
return createDefaultInitializedCompositeValue(type);
|
return createDefaultInitializedCompositeValue(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IType nestedType = SemanticUtil.getNestedType(type, TDEF | REF | CVTYPE);
|
||||||
|
|
||||||
ICPPEvaluation computedInitializerEval = initializerEval.computeForFunctionCall(record, context.recordStep());
|
ICPPEvaluation computedInitializerEval = initializerEval.computeForFunctionCall(record, context.recordStep());
|
||||||
|
|
||||||
// If a composite value with only one member is initialized with an initializer list,
|
// In some contexts, unwrap 1-element initializer lists.
|
||||||
// it evaluates to a EvalFixed with a Value instead of a CompositeValue because the initializer list
|
computedInitializerEval = maybeUnwrapInitList(computedInitializerEval, nestedType, context.getPoint());
|
||||||
// doesn't know that it is initializing a composite.
|
|
||||||
IType nestedType = SemanticUtil.getNestedType(type, TDEF | REF | CVTYPE);
|
|
||||||
if (isClassType(nestedType) && computedInitializerEval instanceof EvalFixed) {
|
|
||||||
EvalFixed evalFixed = (EvalFixed) computedInitializerEval;
|
|
||||||
IValue val = evalFixed.getValue();
|
|
||||||
if (!(val instanceof CompositeValue)) {
|
|
||||||
CompositeValue compVal = new CompositeValue(initializerEval, new ICPPEvaluation[]{evalFixed});
|
|
||||||
computedInitializerEval =
|
|
||||||
new EvalFixed(type, computedInitializerEval.getValueCategory(context.getPoint()), compVal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isReferenceType(type)) {
|
if (isReferenceType(type)) {
|
||||||
return createReferenceValue(record, context, computedInitializerEval);
|
return createReferenceValue(record, context, computedInitializerEval);
|
||||||
|
@ -120,7 +140,10 @@ public final class ExecDeclarator implements ICPPExecution {
|
||||||
private ICPPEvaluation createReferenceValue(ActivationRecord record, ConstexprEvaluationContext context,
|
private ICPPEvaluation createReferenceValue(ActivationRecord record, ConstexprEvaluationContext context,
|
||||||
ICPPEvaluation computedInitializerEval) {
|
ICPPEvaluation computedInitializerEval) {
|
||||||
ICPPEvaluation initValue = initializerEval;
|
ICPPEvaluation initValue = initializerEval;
|
||||||
if (!(initValue instanceof EvalBinding)) {
|
if (initValue instanceof EvalInitList) {
|
||||||
|
initValue = ((EvalInitList) initValue).getClauses()[0];
|
||||||
|
}
|
||||||
|
else if (!(initValue instanceof EvalBinding)) {
|
||||||
initValue = initializerEval.getValue(context.getPoint()).getSubValue(0);
|
initValue = initializerEval.getValue(context.getPoint()).getSubValue(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,13 +59,14 @@ public class ExecSwitch implements ICPPExecution {
|
||||||
return bodyStmtExecutions.length;
|
return bodyStmtExecutions.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSatisfiedCaseStatement(ICPPExecution stmtExec, IValue controllerValue, ActivationRecord record, ConstexprEvaluationContext context) {
|
private boolean isSatisfiedCaseStatement(ICPPExecution stmtExec, IValue controllerValue,
|
||||||
|
ActivationRecord record, ConstexprEvaluationContext context) {
|
||||||
if (stmtExec instanceof ExecCase) {
|
if (stmtExec instanceof ExecCase) {
|
||||||
ExecCase caseStmtExec = (ExecCase) stmtExec;
|
ExecCase caseStmtExec = (ExecCase) stmtExec;
|
||||||
caseStmtExec = (ExecCase) caseStmtExec.executeForFunctionCall(record, context);
|
caseStmtExec = (ExecCase) caseStmtExec.executeForFunctionCall(record, context);
|
||||||
Number caseVal = caseStmtExec.getCaseExpressionEvaluation().getValue(null).numberValue();
|
Number caseVal = caseStmtExec.getCaseExpressionEvaluation().getValue(context.getPoint()).numberValue();
|
||||||
Number controllerVal = controllerValue.numberValue();
|
Number controllerVal = controllerValue.numberValue();
|
||||||
return caseVal.equals(controllerVal);
|
return caseVal != null && controllerVal != null && caseVal.equals(controllerVal);
|
||||||
}
|
}
|
||||||
return stmtExec instanceof ExecDefault;
|
return stmtExec instanceof ExecDefault;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue