1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-23 17:05:26 +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

@ -368,6 +368,17 @@ public class AST2TemplateTests extends AST2TestBase {
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 {
// 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.
private volatile ICPPBase[] fBases;
private volatile ICPPMethod[] ownInheritedConstructors;
private final ThreadLocal<Boolean> fComputingBases = new ThreadLocal<Boolean>() {
@Override
protected Boolean initialValue() {
return false;
}
};
public AbstractCPPClassSpecializationScope(ICPPClassSpecialization specialization) {
this.specialClass= specialization;
@ -146,48 +152,56 @@ public class AbstractCPPClassSpecializationScope implements ICPPClassSpecializat
@Override
public ICPPBase[] getBases(IASTNode point) {
if (fBases == null) {
ICPPBase[] result = ICPPBase.EMPTY_BASE_ARRAY;
ICPPBase[] bases = ClassTypeHelper.getBases(specialClass.getSpecializedBinding(), point);
if (bases.length == 0) {
fBases= bases;
} else {
final ICPPTemplateParameterMap tpmap = specialClass.getTemplateParameterMap();
for (ICPPBase base : bases) {
IBinding origClass = base.getBaseClass();
if (origClass instanceof ICPPTemplateParameter && ((ICPPTemplateParameter) origClass).isParameterPack()) {
IType[] specClasses= CPPTemplates.instantiateTypes(new IType[] { new CPPParameterPackType((IType) origClass) },
tpmap, -1, specialClass, point);
if (specClasses.length == 1 && specClasses[0] instanceof ICPPParameterPackType) {
result= ArrayUtil.append(result, base);
} else {
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);
if (fComputingBases.get()) {
return ICPPBase.EMPTY_BASE_ARRAY; // avoid recursion
}
fComputingBases.set(true);
try {
ICPPBase[] result = ICPPBase.EMPTY_BASE_ARRAY;
ICPPBase[] bases = ClassTypeHelper.getBases(specialClass.getSpecializedBinding(), point);
if (bases.length == 0) {
fBases= bases;
} else {
final ICPPTemplateParameterMap tpmap = specialClass.getTemplateParameterMap();
for (ICPPBase base : bases) {
IBinding origClass = base.getBaseClass();
if (origClass instanceof ICPPTemplateParameter && ((ICPPTemplateParameter) origClass).isParameterPack()) {
IType[] specClasses= CPPTemplates.instantiateTypes(new IType[] { new CPPParameterPackType((IType) origClass) },
tpmap, -1, specialClass, point);
if (specClasses.length == 1 && specClasses[0] instanceof ICPPParameterPackType) {
result= ArrayUtil.append(result, base);
} else {
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);
fBases= result;
return result;
} finally {
fComputingBases.set(false);
}
}
return fBases;