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:
parent
a75ce4027b
commit
3e4e14f0d6
1 changed files with 65 additions and 87 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue