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:
parent
92e5739ba6
commit
438a42b367
2 changed files with 62 additions and 37 deletions
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue