From f1f9ddf0f70bdc5a4960803b47c6137a5d2486d4 Mon Sep 17 00:00:00 2001 From: Nathan Ridge Date: Sun, 5 Nov 2017 23:49:47 -0500 Subject: [PATCH] Bug 514363 - Fix constexpr evaluation of assignment into array element The computation had a bug where the array decayed to a pointer, and we tried to use the pointer's value as a composite value, instead of the underlying array's value. Change-Id: I9510d28e04deb0b8ef835e2857f8b513d11d1d72 --- .../tests/IndexCPPTemplateResolutionTest.java | 13 +++++++++++++ .../core/dom/parser/cpp/semantics/EvalBinary.java | 14 +++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java index d3631045cdf..4ae606e5b46 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java @@ -3140,4 +3140,17 @@ public class IndexCPPTemplateResolutionTest extends IndexBindingResolutionTestBa public void testRegression_516338() throws Exception { checkBindings(); } + + // struct Foo { + // char value[1]; + // constexpr Foo() : value{0} { + // value[0] = 0; // Indexer fails here. + // } + // }; + // constexpr auto foo = Foo{}; + + // // empty file + public void testAssignmentToMemberArrayElement_514363() throws Exception { + checkBindings(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinary.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinary.java index 8e878f83ea8..4169813f585 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinary.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinary.java @@ -491,7 +491,19 @@ public class EvalBinary extends CPPDependentEvaluation { Number numericValue = fixed2.getValue().numberValue(); if (numericValue == null) return EvalFixed.INCOMPLETE; - return new EvalCompositeAccess(fixed1, numericValue.intValue()); + ICPPEvaluation composite = fixed1; + int arrayIndex = numericValue.intValue(); + if (fixed1 instanceof EvalPointer) { + ICPPEvaluation elementEval = ((EvalPointer) fixed1).getTargetEvaluation(); + if (elementEval instanceof EvalCompositeAccess) { + // 'composite' will now be the underlying array that the pointer points into. + // Since the pointer may not point at the beginning of the array, the array + // index needs to be shifted by the pointer's position. + composite = ((EvalCompositeAccess) elementEval).getParent(); + arrayIndex += ((EvalPointer) fixed1).getPosition(); + } + } + return new EvalCompositeAccess(composite, arrayIndex); } else if ((isArray(fixed1) || isArray(fixed2)) && (hasIntType(fixed1) || hasIntType(fixed2))) { int offset = hasIntType(fixed1) ? fixed1.getValue().numberValue().intValue() : fixed2.getValue().numberValue().intValue(); EvalCompositeAccess evalCompositeAccess = new EvalCompositeAccess(isArray(fixed1) ? fixed1 : fixed2, offset);