1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-07 17:56:01 +02:00

Bug 535548 - Infinite recursion loading function whose return type refers to a parameter from the index

Change-Id: Ibff680983cc8ac0bd9d33d8f2247a9f0ca2fe2f3
This commit is contained in:
Nathan Ridge 2018-06-25 00:37:30 -04:00
parent fae039b629
commit f4178eb1f8
7 changed files with 62 additions and 21 deletions

View file

@ -3219,4 +3219,15 @@ public class IndexCPPTemplateResolutionTest extends IndexBindingResolutionTestBa
public void testClassCastException_533216() throws Exception { public void testClassCastException_533216() throws Exception {
checkBindings(); checkBindings();
} }
// template <int N>
// struct array {};
//
// template <class... Ts>
// auto make_array(Ts... ts) -> array<sizeof...(ts)>;
// auto x = make_array(2);
public void testRecursion_535548() throws Exception {
checkBindings();
}
} }

View file

@ -22,7 +22,8 @@ import org.eclipse.core.runtime.CoreException;
*/ */
public class ProblemFunctionType extends ProblemType implements ICPPFunctionType { public class ProblemFunctionType extends ProblemType implements ICPPFunctionType {
@SuppressWarnings("hiding") @SuppressWarnings("hiding")
public static final IType RECURSION_IN_LOOKUP = new ProblemFunctionType(BINDING_RECURSION_IN_LOOKUP); public static final ICPPFunctionType RECURSION_IN_LOOKUP = new ProblemFunctionType(BINDING_RECURSION_IN_LOOKUP);
public static final ICPPFunctionType NOT_PERSISTED = new ProblemFunctionType(TYPE_NOT_PERSISTED);
public ProblemFunctionType(int id) { public ProblemFunctionType(int id) {
super(id); super(id);

View file

@ -26,6 +26,7 @@ public class ProblemType implements IProblemType, ISerializableType {
public static final IType CANNOT_DEDUCE_DECLTYPE_AUTO_TYPE = new ProblemType(TYPE_CANNOT_DEDUCE_DECLTYPE_AUTO_TYPE); public static final IType CANNOT_DEDUCE_DECLTYPE_AUTO_TYPE = new ProblemType(TYPE_CANNOT_DEDUCE_DECLTYPE_AUTO_TYPE);
public static final IType ENUMERATION_EXPECTED = new ProblemType(TYPE_ENUMERATION_EXPECTED); public static final IType ENUMERATION_EXPECTED = new ProblemType(TYPE_ENUMERATION_EXPECTED);
public static final IType NO_NAME = new ProblemType(TYPE_NO_NAME); public static final IType NO_NAME = new ProblemType(TYPE_NO_NAME);
public static final IType NOT_PERSISTED = new ProblemType(TYPE_NOT_PERSISTED);
public static final IType RECURSION_IN_LOOKUP = new ProblemType(BINDING_RECURSION_IN_LOOKUP); public static final IType RECURSION_IN_LOOKUP = new ProblemType(BINDING_RECURSION_IN_LOOKUP);
public static final IType UNKNOWN_FOR_EXPRESSION = new ProblemType(TYPE_UNKNOWN_FOR_EXPRESSION); public static final IType UNKNOWN_FOR_EXPRESSION = new ProblemType(TYPE_UNKNOWN_FOR_EXPRESSION);
public static final IType UNRESOLVED_NAME = new ProblemType(TYPE_UNRESOLVED_NAME); public static final IType UNRESOLVED_NAME = new ProblemType(TYPE_UNRESOLVED_NAME);

View file

@ -167,7 +167,6 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPMethodSpecialization;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPMethodTemplateSpecialization; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPMethodTemplateSpecialization;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPParameterPackType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPParameterPackType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPParameterSpecialization; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPParameterSpecialization;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPlaceholderType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerToMemberType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerToMemberType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateDefinition; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateDefinition;

View file

@ -17,6 +17,8 @@ package org.eclipse.cdt.internal.core.pdom.dom;
import java.lang.ref.Reference; import java.lang.ref.Reference;
import java.lang.ref.SoftReference; import java.lang.ref.SoftReference;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.cdt.core.dom.IPDOMVisitor; import org.eclipse.cdt.core.dom.IPDOMVisitor;
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
@ -41,6 +43,7 @@ import org.eclipse.cdt.core.parser.util.CharArrayMap;
import org.eclipse.cdt.internal.core.dom.parser.ASTInternal; import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer;
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding; import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
import org.eclipse.cdt.internal.core.dom.parser.ProblemType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution;
import org.eclipse.cdt.internal.core.index.IIndexBindingConstants; import org.eclipse.cdt.internal.core.index.IIndexBindingConstants;
@ -77,6 +80,17 @@ public abstract class PDOMLinkage extends PDOMNamedNode implements IIndexLinkage
private final PDOM fPDOM; private final PDOM fPDOM;
private final Database fDatabase; private final Database fDatabase;
/**
* The set of types currently being loaded from the index on each thread, represented as record numbers.
* This is used to guard against infinite recursion while loading types.
*/
private static final ThreadLocal<Set<Long>> fLoadTypeInProgress = new ThreadLocal<Set<Long>>() {
@Override
protected Set<Long> initialValue() {
return new HashSet<>();
}
};
public PDOMLinkage(PDOM pdom, long record) { public PDOMLinkage(PDOM pdom, long record) {
super(null, record); super(null, record);
fPDOM= pdom; fPDOM= pdom;
@ -550,6 +564,11 @@ public abstract class PDOMLinkage extends PDOMNamedNode implements IIndexLinkage
} }
public IType loadType(long offset) throws CoreException { public IType loadType(long offset) throws CoreException {
Set<Long> recursionProtectionSet = fLoadTypeInProgress.get();
if (!recursionProtectionSet.add(offset)) {
return ProblemType.NOT_PERSISTED;
}
try {
final Database db= getDB(); final Database db= getDB();
final byte firstByte= db.getByte(offset); final byte firstByte= db.getByte(offset);
byte[] data= null; byte[] data= null;
@ -567,6 +586,9 @@ public abstract class PDOMLinkage extends PDOMNamedNode implements IIndexLinkage
break; break;
} }
return new TypeMarshalBuffer(this, data).unmarshalType(); return new TypeMarshalBuffer(this, data).unmarshalType();
} finally {
recursionProtectionSet.remove(offset);
}
} }
public void storeBinding(long offset, IBinding binding) throws CoreException { public void storeBinding(long offset, IBinding binding) throws CoreException {

View file

@ -333,10 +333,17 @@ class PDOMCPPFunction extends PDOMCPPBinding implements ICPPFunction, IPDOMOverl
public final ICPPFunctionType getType() { public final ICPPFunctionType getType() {
if (fType == null) { if (fType == null) {
try { try {
fType = (ICPPFunctionType) getLinkage().loadType(record + FUNCTION_TYPE); IType type = getLinkage().loadType(record + FUNCTION_TYPE);
if (type instanceof ICPPFunctionType) {
fType = (ICPPFunctionType) type;
} else {
// Something went wrong while loading the type and we didn't
// get a function type. Treat it similar to an exception.
fType = ProblemFunctionType.NOT_PERSISTED;
}
} catch (CoreException e) { } catch (CoreException e) {
CCorePlugin.log(e); CCorePlugin.log(e);
fType = new ProblemFunctionType(ISemanticProblem.TYPE_NOT_PERSISTED); fType = ProblemFunctionType.NOT_PERSISTED;
} }
} }
return fType; return fType;