1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-22 06:02:11 +02:00

Bug 491834 - Revert the earlier attempt to guard against infinite recursion in HeuristicResolver

Change-Id: I22bd9deb13824a82f081c12051770f8d314b11e6
This commit is contained in:
Nathan Ridge 2016-04-21 01:39:23 -04:00
parent a75ce4027b
commit 3e4e14f0d6

View file

@ -100,15 +100,6 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownType;
* implementing more advanced heuristics that could deal with this. * implementing more advanced heuristics that could deal with this.
*/ */
public class HeuristicResolver { public class HeuristicResolver {
// Infrastructure to protect against infinite recursion in heuristic resolution.
private static final int RESOLUTION_DEPTH_LIMIT = 32;
private static final ThreadLocal<Integer> fResolutionDepth = new ThreadLocal<Integer>() {
@Override
protected Integer initialValue() {
return 0;
}
};
/** /**
* Given a dependent type, heuristically tries to find a concrete scope (i.e. not an unknown scope) * Given a dependent type, heuristically tries to find a concrete scope (i.e. not an unknown scope)
* for it. * for it.
@ -394,90 +385,77 @@ public class HeuristicResolver {
* Helper function for {@link #resolveUnknownType} which does one round of resolution. * Helper function for {@link #resolveUnknownType} which does one round of resolution.
*/ */
private static IType resolveUnknownTypeOnce(ICPPUnknownType type, Set<HeuristicLookup> lookupSet, private static IType resolveUnknownTypeOnce(ICPPUnknownType type, Set<HeuristicLookup> lookupSet,
IASTNode point) { IASTNode point) {
// Guard against infinite recursion. if (type instanceof ICPPDeferredClassInstance) {
int resolutionDepth = fResolutionDepth.get(); ICPPDeferredClassInstance deferredInstance = (ICPPDeferredClassInstance) type;
if (resolutionDepth > RESOLUTION_DEPTH_LIMIT) { return deferredInstance.getClassTemplate();
return type; } else if (type instanceof TypeOfDependentExpression) {
} ICPPEvaluation evaluation = ((TypeOfDependentExpression) type).getEvaluation();
// Increment the resolution depth for the duration of this call. if (evaluation instanceof EvalUnary) {
fResolutionDepth.set(resolutionDepth + 1); EvalUnary unary = (EvalUnary) evaluation;
// Handle the common case of a dependent type representing the result of
try { // dereferencing another dependent type.
if (type instanceof ICPPDeferredClassInstance) { if (unary.getOperator() == IASTUnaryExpression.op_star) {
ICPPDeferredClassInstance deferredInstance = (ICPPDeferredClassInstance) type; IType argument = unary.getArgument().getType(point);
return deferredInstance.getClassTemplate(); if (argument instanceof ICPPUnknownType) {
} else if (type instanceof TypeOfDependentExpression) { IType resolved = resolveUnknownType((ICPPUnknownType) argument, point);
ICPPEvaluation evaluation = ((TypeOfDependentExpression) type).getEvaluation(); if (resolved instanceof IPointerType) {
if (evaluation instanceof EvalUnary) { return ((IPointerType) resolved).getType();
EvalUnary unary = (EvalUnary) evaluation;
// Handle the common case of a dependent type representing the result of
// dereferencing another dependent type.
if (unary.getOperator() == IASTUnaryExpression.op_star) {
IType argument = unary.getArgument().getType(point);
if (argument instanceof ICPPUnknownType) {
IType resolved = resolveUnknownType((ICPPUnknownType) argument, point);
if (resolved instanceof IPointerType) {
return ((IPointerType) resolved).getType();
}
} }
} }
} else if (evaluation instanceof EvalID) {
EvalID id = (EvalID) evaluation;
ICPPEvaluation fieldOwner = id.getFieldOwner();
if (fieldOwner != null) {
IType fieldOwnerType = fieldOwner.getType(point);
IBinding[] candidates = lookInside(fieldOwnerType, id.isPointerDeref(), id.getName(),
id.getTemplateArgs(), lookupSet, point);
if (candidates.length == 1) {
return typeForBinding(candidates[0]);
}
}
} else if (evaluation instanceof EvalFunctionCall) {
EvalFunctionCall evalFunctionCall = (EvalFunctionCall) evaluation;
ICPPEvaluation function = evalFunctionCall.getArguments()[0];
IType functionType = function.getType(point);
if (functionType instanceof ICPPUnknownType) {
functionType = resolveUnknownType((ICPPUnknownType) functionType, point);
}
return ExpressionTypes.typeFromFunctionCall(functionType);
} else if (evaluation instanceof EvalMemberAccess) {
IBinding member = ((EvalMemberAccess) evaluation).getMember();
// Presumably the type will be unknown. That's fine, it will be
// resolved during subsequent resolution rounds.
return typeForBinding(member);
} }
// TODO(nathanridge): Handle more cases. } else if (evaluation instanceof EvalID) {
} else if (type instanceof ICPPUnknownMemberClass) { EvalID id = (EvalID) evaluation;
ICPPUnknownMemberClass member = (ICPPUnknownMemberClass) type; ICPPEvaluation fieldOwner = id.getFieldOwner();
IType ownerType = member.getOwnerType(); if (fieldOwner != null) {
IBinding[] candidates = lookInside(ownerType, false, member.getNameCharArray(), null, IType fieldOwnerType = fieldOwner.getType(point);
lookupSet, point); IBinding[] candidates = lookInside(fieldOwnerType, id.isPointerDeref(), id.getName(),
if (candidates.length == 1) { id.getTemplateArgs(), lookupSet, point);
if (candidates[0] instanceof IType) { if (candidates.length == 1) {
IType result = (IType) candidates[0]; return typeForBinding(candidates[0]);
if (type instanceof ICPPUnknownMemberClassInstance) {
ICPPTemplateArgument[] args = ((ICPPUnknownMemberClassInstance) type).getArguments();
if (result instanceof ICPPClassTemplate) {
result = (IType) CPPTemplates.instantiate((ICPPClassTemplate) result, args, point);
} else if (result instanceof ICPPAliasTemplate) {
result = (IType) CPPTemplates.instantiateAliasTemplate((ICPPAliasTemplate) result,
args, point);
} else if (result instanceof ICPPAliasTemplateInstance) {
// TODO(nathanridge): Remove this branch once we properly represent
// specializations of alias templates (which will then implement
// ICPPAliasTemplate and be caught by the previous branch).
result = (IType) CPPTemplates.instantiateAliasTemplateInstance(
(ICPPAliasTemplateInstance) result, args, point);
}
}
return result;
} }
} }
} else if (evaluation instanceof EvalFunctionCall) {
EvalFunctionCall evalFunctionCall = (EvalFunctionCall) evaluation;
ICPPEvaluation function = evalFunctionCall.getArguments()[0];
IType functionType = function.getType(point);
if (functionType instanceof ICPPUnknownType) {
functionType = resolveUnknownType((ICPPUnknownType) functionType, point);
}
return ExpressionTypes.typeFromFunctionCall(functionType);
} else if (evaluation instanceof EvalMemberAccess) {
IBinding member = ((EvalMemberAccess) evaluation).getMember();
// Presumably the type will be unknown. That's fine, it will be
// resolved during subsequent resolution rounds.
return typeForBinding(member);
}
// TODO(nathanridge): Handle more cases.
} else if (type instanceof ICPPUnknownMemberClass) {
ICPPUnknownMemberClass member = (ICPPUnknownMemberClass) type;
IType ownerType = member.getOwnerType();
IBinding[] candidates = lookInside(ownerType, false, member.getNameCharArray(), null,
lookupSet, point);
if (candidates.length == 1) {
if (candidates[0] instanceof IType) {
IType result = (IType) candidates[0];
if (type instanceof ICPPUnknownMemberClassInstance) {
ICPPTemplateArgument[] args = ((ICPPUnknownMemberClassInstance) type).getArguments();
if (result instanceof ICPPClassTemplate) {
result = (IType) CPPTemplates.instantiate((ICPPClassTemplate) result, args, point);
} else if (result instanceof ICPPAliasTemplate) {
result = (IType) CPPTemplates.instantiateAliasTemplate((ICPPAliasTemplate) result,
args, point);
} else if (result instanceof ICPPAliasTemplateInstance) {
// TODO(nathanridge): Remove this branch once we properly represent
// specializations of alias templates (which will then implement
// ICPPAliasTemplate and be caught by the previous branch).
result = (IType) CPPTemplates.instantiateAliasTemplateInstance(
(ICPPAliasTemplateInstance) result, args, point);
}
}
return result;
}
} }
} finally {
// Restore original resolution depth.
fResolutionDepth.set(resolutionDepth);
} }
return null; return null;
} }