diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexMultiFileTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexMultiFileTest.java index 0e9481bebb0..10ce5ef99b2 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexMultiFileTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexMultiFileTest.java @@ -10,6 +10,14 @@ *******************************************************************************/ package org.eclipse.cdt.internal.index.tests; +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.dom.IPDOMManager; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.testplugin.CProjectHelper; +import org.eclipse.cdt.core.testplugin.util.TestSourceReader; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectDescription; + import junit.framework.TestSuite; /** @@ -301,4 +309,46 @@ public class IndexMultiFileTest extends IndexBindingResolutionTestBase { public void testFriendFunctionDeclarationInNamespace_513681() throws Exception { checkBindings(); } + + // test.hpp + // #ifndef test_hpp + // #define test_hpp + // + // struct S { + // const S* x; + // }; + // + // struct Base { + // static const S field; + // }; + // struct Conjugate { + // static const S field; + // }; + // + // #endif + + //test1.cpp + //# include "test.hpp" + // + // const S Base::field = { + // &Conjugate::field + // }; + // + // const S Conjugate::field = { + // &Base::field + // }; + + //test2.cpp + // #include "test.hpp" + // + // struct Waldo { + // static const S s; + // }; + // + // const S Waldo::s = { + // &Base::field + // }; + public void testStackOverflow_514459() throws Exception { + checkBindings(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java index 051d16e9dc3..bb8b5d8a065 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java @@ -17,6 +17,7 @@ package org.eclipse.cdt.internal.core.pdom; import java.io.File; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Arrays; import java.util.BitSet; @@ -45,6 +46,7 @@ import org.eclipse.cdt.core.dom.ast.IFunction; import org.eclipse.cdt.core.dom.ast.IMacroBinding; import org.eclipse.cdt.core.dom.ast.IParameter; import org.eclipse.cdt.core.dom.ast.ITypedef; +import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.IVariable; import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumeration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; @@ -396,6 +398,7 @@ public class PDOM extends PlatformObject implements IPDOM { private final IIndexLocationConverter locationConverter; private final Map fPDOMLinkageFactoryCache; private final HashMap fResultCache= new HashMap<>(); + private final Map> fVariableResultCache= new HashMap<>(); private List listeners; protected ChangeEvent fEvent= new ChangeEvent(); @@ -1494,6 +1497,9 @@ public class PDOM extends PlatformObject implements IPDOM { synchronized (fResultCache) { fResultCache.clear(); } + synchronized (fVariableResultCache) { + fVariableResultCache.clear(); + } } @Override @@ -1544,6 +1550,28 @@ public class PDOM extends PlatformObject implements IPDOM { } } + public IValue getCachedVariableResult(Long key) { + synchronized (fVariableResultCache) { + WeakReference variableResult = fVariableResultCache.get(key); + if (variableResult != null) { + return variableResult.get(); + } + return null; + } + } + + public void removeCachedVariableResult(Long key) { + synchronized (fVariableResultCache) { + fVariableResultCache.remove(key); + } + } + + public void putCachedVariableResult(Long key, IValue result) { + synchronized (fVariableResultCache) { + fVariableResultCache.put(key, new WeakReference(result)); + } + } + public String createKeyForCache(long record, char[] name) { return new StringBuilder(name.length + 2).append((char) (record >> 16)).append((char) record).append(name).toString(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java index 36fdcc8ff35..da1e67989f1 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java @@ -659,14 +659,22 @@ public abstract class PDOMLinkage extends PDOMNamedNode implements IIndexLinkage } private void deleteValue(Database db, long offset) throws CoreException { + fPDOM.removeCachedVariableResult(offset); deleteSerializedData(db, offset, Database.VALUE_SIZE); } public IValue loadValue(long offset) throws CoreException { + Long cacheKey = Long.valueOf(offset); + IValue value = fPDOM.getCachedVariableResult(cacheKey); + if (value != null) + return value; TypeMarshalBuffer buffer = loadBuffer(offset, Database.VALUE_SIZE); if (buffer == null) return null; - return buffer.unmarshalValue(); + value = buffer.unmarshalValue(); + if (value!= null) + fPDOM.putCachedVariableResult(cacheKey, value); + return value; } public void storeEvaluation(long offset, ICPPEvaluation eval) throws CoreException {