1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-24 01:15:29 +02:00

Bug 86837: Destructor via typedef.

This commit is contained in:
Markus Schorn 2010-07-02 13:12:06 +00:00
parent 6a748490e7
commit d5ea7d1248
2 changed files with 113 additions and 18 deletions

View file

@ -32,6 +32,7 @@ import org.eclipse.cdt.core.dom.ast.IVariable;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionTemplate;
import org.eclipse.cdt.core.parser.ParserLanguage;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
@ -3532,24 +3533,38 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
parse(getAboveComment(), ParserLanguage.CPP, false, 0);
}
// struct B {
// virtual ~B() { }
// };
// struct D : B {
// ~D() { }
// };
// D D_object;
// typedef B B_alias;
// B* B_ptr = &D_object;
// void f() {
// D_object.B::~B(); // calls B's destructor
// B_ptr->~B(); //calls D's destructor
// B_ptr->~B_alias(); // calls D's destructor
// B_ptr->B_alias::~B(); // calls B's destructor
// B_ptr->B_alias::~B_alias(); // error, no B_alias in class B
// }
// struct B {
// virtual ~B() { }
// };
// struct D : B {
// ~D() { }
// };
// D D_object;
// typedef B B_alias;
// B* B_ptr = &D_object;
// void f() {
// D_object.B::~B(); //1 // calls B's destructor
// B_ptr->~B(); //2 // calls D's destructor
// B_ptr->~B_alias(); //3 // calls D's destructor
// B_ptr->B_alias::~B(); //4 // calls B's destructor
// B_ptr->B_alias::~B_alias(); //5 // error, no B_alias in class B
// }
public void test12_4s12() throws Exception {
parse(getAboveComment(), ParserLanguage.CPP, false, 0);
final String code = getAboveComment();
parse(code, ParserLanguage.CPP, false, 0);
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
ICPPFunction dtor= bh.assertNonProblem("~B() {", 2);
ICPPFunction d= bh.assertNonProblem("~B(); //1", 2);
assertSame(dtor, d);
d= bh.assertNonProblem("~B(); //2", 2);
assertSame(dtor, d);
d= bh.assertNonProblem("~B_alias(); //3", 8);
assertSame(dtor, d);
d= bh.assertNonProblem("~B(); //4", 2);
assertSame(dtor, d);
bh.assertProblem("~B_alias(); //5", 8);
}
// void* operator new(size_t, void* p) { return p; }

View file

@ -165,6 +165,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTIdExpression;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTLiteralExpression;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTNameBase;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTQualifiedName;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTranslationUnit;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTypeIdExpression;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTUnaryExpression;
@ -228,7 +229,7 @@ public class CPPSemantics {
if (name instanceof CPPASTNameBase) {
((CPPASTNameBase) name).incResolutionDepth();
}
// 1: get some context info off of the name to figure out what kind of lookup we want
LookupData data = createLookupData(name, true);
@ -818,6 +819,10 @@ public class CPPSemantics {
if (data.astName == null)
return;
if (start == null && lookupDestructor(data, start)) {
return;
}
ICPPScope nextScope= null;
ICPPTemplateScope nextTmplScope= null;
if (start instanceof ICPPScope) {
@ -932,6 +937,81 @@ public class CPPSemantics {
}
}
private static boolean lookupDestructor(LookupData data, IScope start) throws DOMException {
IASTName typeDtorName= data.astName;
final char[] typeDtorChars= typeDtorName.getSimpleID();
if (typeDtorChars.length == 0 || typeDtorChars[0] != '~')
return false;
// Assume class C; typedef C T;
// When looking up ~T the strategy is to lookup T::~C in two steps:
// * First resolve 'T', then compute '~C' and resolve it.
CPPASTQualifiedName syntheticName= new CPPASTQualifiedName();
IASTNode parent= typeDtorName.getParent();
if (parent instanceof ICPPASTQualifiedName) {
ICPPASTQualifiedName dqname= (ICPPASTQualifiedName) parent;
if (dqname.getLastName() != data)
return false;
syntheticName.setFullyQualified(dqname.isFullyQualified());
IASTName[] children = dqname.getNames();
for (IASTName child : children) {
if (child != data) {
final IASTName childCopy = child.copy();
childCopy.setBinding(child.resolveBinding());
syntheticName.addName(childCopy);
}
}
syntheticName.setOffsetAndLength((ASTNode) parent);
syntheticName.setParent(parent.getParent());
syntheticName.setPropertyInParent(parent.getPropertyInParent());
} else {
syntheticName.setOffsetAndLength((ASTNode) typeDtorName);
syntheticName.setParent(parent);
syntheticName.setPropertyInParent(typeDtorName.getPropertyInParent());
}
char[] tchars= new char[typeDtorChars.length-1];
System.arraycopy(typeDtorChars, 1, tchars, 0, tchars.length);
final CPPASTName typeName = new CPPASTName(tchars);
typeName.setOffsetAndLength((ASTNode) typeDtorName);
syntheticName.addName(typeName);
final CPPASTName classDtorName = new CPPASTName(typeDtorChars);
classDtorName.setOffsetAndLength((ASTNode) typeDtorName);
syntheticName.addName(classDtorName);
IBinding type= resolveBinding(typeName);
if (!(type instanceof ITypedef))
return false;
IType t= SemanticUtil.getNestedType((ITypedef) type, TDEF);
if (t instanceof ICPPUnknownBinding || t instanceof IProblemBinding ||
!(t instanceof ICPPClassType)) {
return false;
}
ICPPClassType classType= (ICPPClassType) t;
final IScope scope = ((ICPPClassType) t).getCompositeScope();
if (scope == null) {
return false;
}
char[] classChars= classType.getNameCharArray();
char[] classDtorChars= new char[classChars.length+1];
classDtorChars[0]= '~';
System.arraycopy(classChars, 0, classDtorChars, 1, classChars.length);
classDtorName.setName(classDtorChars);
data.astName = classDtorName;
try {
lookup(data, scope);
} finally {
data.astName= typeDtorName;
}
return true;
}
/**
* Checks whether the name directly or indirectly depends on the this pointer.
*/