1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-10 17:55:39 +02:00

Bug 418996 - Guard against infinite recursion in

AbstractCPPClassSpecializationBases.getBases()

Change-Id: I84d56a12d4a2133d93bf54f5a70a1e801b981878
Signed-off-by: Nathan Ridge <zeratul976@hotmail.com>
Reviewed-on: https://git.eclipse.org/r/26781
Tested-by: Hudson CI
Reviewed-by: Sergey Prigogin <eclipse.sprigogin@gmail.com>
Tested-by: Sergey Prigogin <eclipse.sprigogin@gmail.com>
This commit is contained in:
Nathan Ridge 2014-05-17 21:42:03 -04:00 committed by Sergey Prigogin
parent 92e5739ba6
commit 438a42b367
2 changed files with 62 additions and 37 deletions

View file

@ -369,6 +369,17 @@ public class AST2TemplateTests extends AST2TestBase {
assertInstances(col, T1, 6); assertInstances(col, T1, 6);
} }
// template<typename _A_>
// struct A : public _A_::member_t {};
//
// struct B : public A<B>{};
public void testStackOverflowInBaseComputation_418996() throws Exception {
BindingAssertionHelper helper = getAssertionHelper();
ICPPClassType B = helper.assertNonProblem("A<B>", 4);
// Check that this line does not cause a StackOverflowError.
ClassTypeHelper.getBases(B, null);
}
// template < class T > class A { // template < class T > class A {
// void f(); // void f();
// }; // };

View file

@ -54,6 +54,12 @@ public class AbstractCPPClassSpecializationScope implements ICPPClassSpecializat
// The following fields are used by the PDOM bindings and need to be volatile. // The following fields are used by the PDOM bindings and need to be volatile.
private volatile ICPPBase[] fBases; private volatile ICPPBase[] fBases;
private volatile ICPPMethod[] ownInheritedConstructors; private volatile ICPPMethod[] ownInheritedConstructors;
private final ThreadLocal<Boolean> fComputingBases = new ThreadLocal<Boolean>() {
@Override
protected Boolean initialValue() {
return false;
}
};
public AbstractCPPClassSpecializationScope(ICPPClassSpecialization specialization) { public AbstractCPPClassSpecializationScope(ICPPClassSpecialization specialization) {
this.specialClass= specialization; this.specialClass= specialization;
@ -146,48 +152,56 @@ public class AbstractCPPClassSpecializationScope implements ICPPClassSpecializat
@Override @Override
public ICPPBase[] getBases(IASTNode point) { public ICPPBase[] getBases(IASTNode point) {
if (fBases == null) { if (fBases == null) {
ICPPBase[] result = ICPPBase.EMPTY_BASE_ARRAY; if (fComputingBases.get()) {
ICPPBase[] bases = ClassTypeHelper.getBases(specialClass.getSpecializedBinding(), point); return ICPPBase.EMPTY_BASE_ARRAY; // avoid recursion
if (bases.length == 0) { }
fBases= bases; fComputingBases.set(true);
} else { try {
final ICPPTemplateParameterMap tpmap = specialClass.getTemplateParameterMap(); ICPPBase[] result = ICPPBase.EMPTY_BASE_ARRAY;
for (ICPPBase base : bases) { ICPPBase[] bases = ClassTypeHelper.getBases(specialClass.getSpecializedBinding(), point);
IBinding origClass = base.getBaseClass(); if (bases.length == 0) {
if (origClass instanceof ICPPTemplateParameter && ((ICPPTemplateParameter) origClass).isParameterPack()) { fBases= bases;
IType[] specClasses= CPPTemplates.instantiateTypes(new IType[] { new CPPParameterPackType((IType) origClass) }, } else {
tpmap, -1, specialClass, point); final ICPPTemplateParameterMap tpmap = specialClass.getTemplateParameterMap();
if (specClasses.length == 1 && specClasses[0] instanceof ICPPParameterPackType) { for (ICPPBase base : bases) {
result= ArrayUtil.append(result, base); IBinding origClass = base.getBaseClass();
} else { if (origClass instanceof ICPPTemplateParameter && ((ICPPTemplateParameter) origClass).isParameterPack()) {
for (IType specClass : specClasses) { IType[] specClasses= CPPTemplates.instantiateTypes(new IType[] { new CPPParameterPackType((IType) origClass) },
ICPPBase specBase = base.clone(); tpmap, -1, specialClass, point);
specClass = SemanticUtil.getUltimateType(specClass, false); if (specClasses.length == 1 && specClasses[0] instanceof ICPPParameterPackType) {
if (specClass instanceof IBinding && !(specClass instanceof IProblemBinding)) { result= ArrayUtil.append(result, base);
specBase.setBaseClass((IBinding) specClass); } else {
result = ArrayUtil.append(result, specBase); for (IType specClass : specClasses) {
ICPPBase specBase = base.clone();
specClass = SemanticUtil.getUltimateType(specClass, false);
if (specClass instanceof IBinding && !(specClass instanceof IProblemBinding)) {
specBase.setBaseClass((IBinding) specClass);
result = ArrayUtil.append(result, specBase);
}
} }
} }
continue;
}
if (origClass instanceof IType) {
ICPPBase specBase = base.clone();
ICPPClassSpecialization specializationContext = specialClass;
if (specialClass.getOwner() instanceof ICPPClassSpecialization) {
specializationContext = (ICPPClassSpecialization) specialClass.getOwner();
}
IType specClass= CPPTemplates.instantiateType((IType) origClass, tpmap, -1, specializationContext, point);
specClass = SemanticUtil.getUltimateType(specClass, false);
if (specClass instanceof IBinding && !(specClass instanceof IProblemBinding)) {
specBase.setBaseClass((IBinding) specClass);
}
result = ArrayUtil.append(result, specBase);
} }
continue;
}
if (origClass instanceof IType) {
ICPPBase specBase = base.clone();
ICPPClassSpecialization specializationContext = specialClass;
if (specialClass.getOwner() instanceof ICPPClassSpecialization) {
specializationContext = (ICPPClassSpecialization) specialClass.getOwner();
}
IType specClass= CPPTemplates.instantiateType((IType) origClass, tpmap, -1, specializationContext, point);
specClass = SemanticUtil.getUltimateType(specClass, false);
if (specClass instanceof IBinding && !(specClass instanceof IProblemBinding)) {
specBase.setBaseClass((IBinding) specClass);
}
result = ArrayUtil.append(result, specBase);
} }
result= ArrayUtil.trim(result);
fBases= result;
return result;
} }
result= ArrayUtil.trim(result); } finally {
fBases= result; fComputingBases.set(false);
return result;
} }
} }
return fBases; return fBases;