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:
parent
6a748490e7
commit
d5ea7d1248
2 changed files with 113 additions and 18 deletions
|
@ -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; }
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
Loading…
Add table
Reference in a new issue