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 95fc2bb21dd..b00711fe5ec 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2013 Symbian Software Systems and others. + * Copyright (c) 2007, 2014 Symbian Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -2580,4 +2580,30 @@ public class IndexCPPTemplateResolutionTest extends IndexBindingResolutionTestBa public void testInstantiationOfFunctionInstance_437675() throws Exception { checkBindings(); } + + // struct IID { }; + // + // struct IUnknown {}; + // + // template + // class IID_DUMMY : IID { }; + // + // template + // const IID &__uuidof(T x) { return IID_DUMMY(); } + // + // static IID IID_IUnknown = {}; + // + // template + // class MYCComPtr { }; + // + // template > + // class MYCComQIPtr : public MYCComPtr {}; + // + // template<> + // class MYCComQIPtr : public MYCComPtr {}; + + // // source file is deliberately empty + public void testInfiniteRecursionMarshallingTemplateDefinition_439923() throws Exception { + checkBindings(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassInstance.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassInstance.java index 0fabcc855ab..80b44965b05 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassInstance.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassInstance.java @@ -40,12 +40,19 @@ class PDOMCPPClassInstance extends PDOMCPPClassSpecialization implements ICPPTem @SuppressWarnings("hiding") protected static final int RECORD_SIZE = PDOMCPPClassSpecialization.RECORD_SIZE + 4; - public PDOMCPPClassInstance(PDOMLinkage linkage, PDOMNode parent, ICPPClassType classType, PDOMBinding orig) + private volatile ICPPTemplateArgument[] fTemplateArguments; + + public PDOMCPPClassInstance(PDOMCPPLinkage linkage, PDOMNode parent, ICPPClassType classType, PDOMBinding orig) throws CoreException { super(linkage, parent, classType, orig); final ICPPTemplateInstance asInstance= (ICPPTemplateInstance) classType; - final long argListRec= PDOMCPPArgumentList.putArguments(this, asInstance.getTemplateArguments()); - getDB().putRecPtr(record + ARGUMENTS, argListRec); + // Defer storing of template arguments to the post-process + // to avoid infinite recursion when the evaluation of a non-type + // template argument tries to store its template definition. + // Until the post-process runs, temporarily store the input (possibly + // non-PDOM) arguments. + fTemplateArguments = asInstance.getTemplateArguments(); + linkage.new ConfigureClassInstance(this); } public PDOMCPPClassInstance(PDOMLinkage linkage, long bindingRecord) { @@ -69,12 +76,29 @@ class PDOMCPPClassInstance extends PDOMCPPClassSpecialization implements ICPPTem @Override public ICPPTemplateArgument[] getTemplateArguments() { + if (fTemplateArguments == null) { + try { + final long rec= getPDOM().getDB().getRecPtr(record + ARGUMENTS); + fTemplateArguments = PDOMCPPArgumentList.getArguments(this, rec); + } catch (CoreException e) { + CCorePlugin.log(e); + } + } + return fTemplateArguments; + } + + public void storeTemplateArguments() { try { - final long rec= getPDOM().getDB().getRecPtr(record + ARGUMENTS); - return PDOMCPPArgumentList.getArguments(this, rec); + // fTemplateArguments here are the temporarily stored, possibly non-PDOM + // arguments stored by the constructor. Construct the PDOM arguments and + // store them. + final long argListRec= PDOMCPPArgumentList.putArguments(this, fTemplateArguments); + getDB().putRecPtr(record + ARGUMENTS, argListRec); + + // Read the stored arguments next time getTemplateArguments() is called. + fTemplateArguments = null; } catch (CoreException e) { CCorePlugin.log(e); - return ICPPTemplateArgument.EMPTY_ARGUMENTS; } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassSpecialization.java index 7f49e5773a4..4fc86d161c1 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassSpecialization.java @@ -74,7 +74,7 @@ class PDOMCPPClassSpecialization extends PDOMCPPSpecialization implements } }; - public PDOMCPPClassSpecialization(PDOMLinkage linkage, PDOMNode parent, ICPPClassType classType, + public PDOMCPPClassSpecialization(PDOMCPPLinkage linkage, PDOMNode parent, ICPPClassType classType, PDOMBinding specialized) throws CoreException { super(linkage, parent, (ICPPSpecialization) classType, specialized); setFinal(classType); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPEnumerationSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPEnumerationSpecialization.java index d8719ce0e48..7a87448d77f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPEnumerationSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPEnumerationSpecialization.java @@ -57,7 +57,7 @@ class PDOMCPPEnumerationSpecialization extends PDOMCPPSpecialization private volatile IType fFixedType= ProblemBinding.NOT_INITIALIZED; private PDOMCPPEnumScope fScope; // No need for volatile, all fields of PDOMCPPEnumScope are final. - public PDOMCPPEnumerationSpecialization(PDOMLinkage linkage, PDOMNode parent, + public PDOMCPPEnumerationSpecialization(PDOMCPPLinkage linkage, PDOMNode parent, ICPPEnumeration enumeration, PDOMBinding specialized) throws CoreException { super(linkage, parent, (ICPPSpecialization) enumeration, specialized); storeProperties(enumeration); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPEnumeratorSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPEnumeratorSpecialization.java index 2044ee6b535..8ef93ddd74c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPEnumeratorSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPEnumeratorSpecialization.java @@ -34,7 +34,7 @@ class PDOMCPPEnumeratorSpecialization extends PDOMCPPSpecialization implements I @SuppressWarnings("hiding") protected static final int RECORD_SIZE = VALUE + Database.VALUE_SIZE; - public PDOMCPPEnumeratorSpecialization(PDOMLinkage linkage, PDOMNode parent, + public PDOMCPPEnumeratorSpecialization(PDOMCPPLinkage linkage, PDOMNode parent, IEnumerator enumerator, PDOMBinding specialized) throws CoreException { super(linkage, parent, (ICPPSpecialization) enumerator, specialized); storeValue(enumerator); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFieldSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFieldSpecialization.java index db16d027d68..c44b4c89f18 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFieldSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFieldSpecialization.java @@ -38,7 +38,7 @@ class PDOMCPPFieldSpecialization extends PDOMCPPSpecialization implements ICPPFi @SuppressWarnings("hiding") protected static final int RECORD_SIZE = VALUE_OFFSET + Database.VALUE_SIZE; - public PDOMCPPFieldSpecialization(PDOMLinkage linkage, PDOMNode parent, + public PDOMCPPFieldSpecialization(PDOMCPPLinkage linkage, PDOMNode parent, ICPPField field, PDOMBinding specialized) throws CoreException { super(linkage, parent, (ICPPSpecialization) field, specialized); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java index afd5ce44c3d..3ced60545d2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java @@ -324,6 +324,34 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { fTemplate.initData(fOriginalAliasedType); } } + + class ConfigureInstance implements Runnable { + PDOMCPPSpecialization fInstance; + + public ConfigureInstance(PDOMCPPSpecialization specialization) { + fInstance = specialization; + postProcesses.add(this); + } + + @Override + public void run() { + fInstance.storeTemplateParameterMap(); + } + } + + class ConfigureClassInstance implements Runnable { + PDOMCPPClassInstance fClassInstance; + + public ConfigureClassInstance(PDOMCPPClassInstance classInstance) { + fClassInstance = classInstance; + postProcesses.add(this); + } + + @Override + public void run() { + fClassInstance.storeTemplateArguments(); + } + } /** * Adds or returns existing binding for the given name. @@ -336,13 +364,26 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { IBinding binding = name.resolveBinding(); PDOMBinding pdomBinding = addBinding(binding, name); + + // Some nodes schedule some of their initialization to be done + // after the binding has been added to the PDOM, to avoid + // infinite recursion. We run those post-processes now. + // Note that we need to run it before addImplicitMethods() is + // called, since addImplicitMethods() expects the binding to + // be fully initialized. + handlePostProcesses(); + if (pdomBinding instanceof PDOMCPPClassType || pdomBinding instanceof PDOMCPPClassSpecialization) { if (binding instanceof ICPPClassType && name.isDefinition()) { addImplicitMethods(pdomBinding, (ICPPClassType) binding, name); } } - + + // Some of the nodes created during addImplicitMethods() can + // also schedule post-processes, so we need to run through + // them again. handlePostProcesses(); + return pdomBinding; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPParameterSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPParameterSpecialization.java index ad4af4ed2dd..019559813ef 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPParameterSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPParameterSpecialization.java @@ -45,7 +45,7 @@ class PDOMCPPParameterSpecialization extends PDOMCPPSpecialization implements IC fType= t; } - public PDOMCPPParameterSpecialization(PDOMLinkage linkage, PDOMCPPFunctionSpecialization parent, ICPPParameter astParam, + public PDOMCPPParameterSpecialization(PDOMCPPLinkage linkage, PDOMCPPFunctionSpecialization parent, ICPPParameter astParam, PDOMCPPParameter original, PDOMCPPParameterSpecialization next) throws CoreException { super(linkage, parent, (ICPPSpecialization) astParam, original); fType= null; // This constructor is used for adding parameters to the database, only. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPSpecialization.java index 3e825f7be11..de0c7154b22 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPSpecialization.java @@ -43,15 +43,20 @@ abstract class PDOMCPPSpecialization extends PDOMCPPBinding implements ICPPSpeci private volatile IBinding fSpecializedCache= null; private volatile ICPPTemplateParameterMap fArgMap; - public PDOMCPPSpecialization(PDOMLinkage linkage, PDOMNode parent, ICPPSpecialization spec, + public PDOMCPPSpecialization(PDOMCPPLinkage linkage, PDOMNode parent, ICPPSpecialization spec, IPDOMBinding specialized) throws CoreException { super(linkage, parent, spec.getNameCharArray()); getDB().putRecPtr(record + SPECIALIZED, specialized.getRecord()); // Specializations that are not instances have the same map as their owner. if (this instanceof ICPPTemplateInstance) { - long rec= PDOMCPPTemplateParameterMap.putMap(this, spec.getTemplateParameterMap()); - getDB().putRecPtr(record + ARGMAP, rec); + // Defer storing of template parameter map to the post-process + // to avoid infinite recursion when the evaluation of a non-type + // template argument tries to store its template definition. + // Until the post-process runs, temporarily store the input (possibly + // non-PDOM) map. + fArgMap = spec.getTemplateParameterMap(); + linkage.new ConfigureInstance(this); } try { Integer sigHash = IndexCPPSignatureUtil.getSignatureHash(spec); @@ -107,6 +112,22 @@ abstract class PDOMCPPSpecialization extends PDOMCPPBinding implements ICPPSpeci return fArgMap; } + public void storeTemplateParameterMap() { + try { + // fArgMap here is the temporarily stored, possibly non-PDOM + // map stored by the constructor. Construct the PDOM map and + // store it. + long rec= PDOMCPPTemplateParameterMap.putMap(this, fArgMap); + getDB().putRecPtr(record + ARGMAP, rec); + + // Read the stored map next time getTemplateParameterMap() + // is called. + fArgMap = null; + } catch (CoreException e) { + CCorePlugin.log(e); + } + } + @Override public int getSignatureHash() throws CoreException { return getDB().getInt(record + SIGNATURE_HASH); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPTypedefSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPTypedefSpecialization.java index dd3ee67bcea..e404bf8df73 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPTypedefSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPTypedefSpecialization.java @@ -33,7 +33,7 @@ class PDOMCPPTypedefSpecialization extends PDOMCPPSpecialization implements ITyp @SuppressWarnings("hiding") protected static final int RECORD_SIZE = TYPE_OFFSET + Database.TYPE_SIZE; - public PDOMCPPTypedefSpecialization(PDOMLinkage linkage, PDOMNode parent, ITypedef typedef, PDOMBinding specialized) + public PDOMCPPTypedefSpecialization(PDOMCPPLinkage linkage, PDOMNode parent, ITypedef typedef, PDOMBinding specialized) throws CoreException { super(linkage, parent, (ICPPSpecialization) typedef, specialized); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPUsingDeclarationSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPUsingDeclarationSpecialization.java index b7cafb643c9..f883bb4e4cd 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPUsingDeclarationSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPUsingDeclarationSpecialization.java @@ -36,7 +36,7 @@ class PDOMCPPUsingDeclarationSpecialization extends PDOMCPPSpecialization implem private volatile IBinding[] delegates; - public PDOMCPPUsingDeclarationSpecialization(PDOMLinkage linkage, PDOMNode parent, ICPPUsingDeclaration using, PDOMBinding specialized) + public PDOMCPPUsingDeclarationSpecialization(PDOMCPPLinkage linkage, PDOMNode parent, ICPPUsingDeclaration using, PDOMBinding specialized) throws CoreException { super(linkage, parent, (ICPPSpecialization) using, specialized);