From 89d1521d24ab1a66a3bfa4321ef618b5de748cde Mon Sep 17 00:00:00 2001 From: Nathan Ridge Date: Mon, 16 Jan 2017 00:31:51 -0500 Subject: [PATCH] Bug 510484 - Restore the recursion protection set in CPPVariable.getInitialValue() The set was moved to EvalUtil.getVariableValue() in bug 508254, but this left some paths unprotected. This restores the set to CPPVariable.getInitialValue() (while keeping the EvalUtil one too). Change-Id: I4a579720f4bc23d41e50c484649a73c29698373d --- .../tests/IndexCPPBindingResolutionTest.java | 8 ++++ .../core/dom/parser/cpp/CPPVariable.java | 48 ++++++++++++++----- 2 files changed, 43 insertions(+), 13 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionTest.java index e5af56fd4d8..a381a7dc621 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionTest.java @@ -2452,4 +2452,12 @@ public class IndexCPPBindingResolutionTest extends IndexBindingResolutionTestBas public void testDelegatingConstructorCallInConstexprConstructor_509871() throws Exception { checkBindings(); } + + // enum class NoneType { None }; + // const NoneType None = None; + + // // empty file + public void testSelfReferencingVariable_510484() throws Exception { + checkBindings(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVariable.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVariable.java index 700d5e44b89..b08f6add520 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVariable.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVariable.java @@ -17,6 +17,9 @@ import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUti import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.REF; import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF; +import java.util.HashSet; +import java.util.Set; + import org.eclipse.cdt.core.dom.ILinkage; import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; @@ -56,6 +59,17 @@ public class CPPVariable extends PlatformObject implements ICPPInternalVariable private IType fType; private boolean fAllResolved; + /** + * The set of CPPVariable objects for which initial value computation is in progress on each thread. + * This is used to guard against recursion during initial value computation. + */ + private static final ThreadLocal> fInitialValueInProgress = new ThreadLocal>() { + @Override + protected Set initialValue() { + return new HashSet<>(); + } + }; + public CPPVariable(IASTName name) { boolean isDef = name != null && name.isDefinition(); if (name instanceof ICPPASTQualifiedName) { @@ -223,20 +237,28 @@ public class CPPVariable extends PlatformObject implements ICPPInternalVariable @Override public IValue getInitialValue() { - IValue initialValue = null; - final IType nestedType = SemanticUtil.getNestedType(getType(), TDEF | REF | CVTYPE); - if (nestedType instanceof ICPPClassType || (initialValue = VariableHelpers.getInitialValue(fDefinition, fDeclarations, getType())) == IntegralValue.UNKNOWN) { - ICPPEvaluation initEval = getInitializerEvaluation(); - if (initEval == null) { - return null; - } - if (!initEval.isValueDependent() ) { - IASTNode point = fDefinition != null ? fDefinition : fDeclarations[0]; - return initEval.getValue(point); - } - return DependentValue.create(initEval); + Set recursionProtectionSet = fInitialValueInProgress.get(); + if (!recursionProtectionSet.add(this)) { + return IntegralValue.UNKNOWN; + } + try { + IValue initialValue = null; + final IType nestedType = SemanticUtil.getNestedType(getType(), TDEF | REF | CVTYPE); + if (nestedType instanceof ICPPClassType || (initialValue = VariableHelpers.getInitialValue(fDefinition, fDeclarations, getType())) == IntegralValue.UNKNOWN) { + ICPPEvaluation initEval = getInitializerEvaluation(); + if (initEval == null) { + return null; + } + if (!initEval.isValueDependent() ) { + IASTNode point = fDefinition != null ? fDefinition : fDeclarations[0]; + return initEval.getValue(point); + } + return DependentValue.create(initEval); + } + return initialValue; + } finally { + recursionProtectionSet.remove(this); } - return initialValue; } private IASTDeclarator findDeclarator() {