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