1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Bug 351547: Resolution of delete expressions.

This commit is contained in:
Markus Schorn 2011-07-20 12:05:13 +02:00
parent 9d9efe8e9d
commit 34fdfb1196
2 changed files with 107 additions and 58 deletions

View file

@ -18,6 +18,7 @@ import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner;
import org.eclipse.cdt.core.dom.ast.IASTNodeSelector;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
@ -367,8 +368,8 @@ public class AST2CPPImplicitNameTests extends AST2BaseTest {
// struct X {
// ~X();
// void operator delete();
// void operator delete[]();
// void operator delete(void *);
// void operator delete[](void *);
// };
//
// int test(X* x) {
@ -393,11 +394,38 @@ public class AST2CPPImplicitNameTests extends AST2BaseTest {
names = ba.getImplicitNames("delete[] x;", 6);
assertEquals(1, names.length);
assertSame(col.getName(3).resolveBinding(), names[0].resolveBinding());
assertSame(col.getName(4).resolveBinding(), names[0].resolveBinding());
ba.assertNoImplicitName("delete 1;", 6);
}
// struct A {
// void operator delete(void * a);
// };
// struct B {};
// void operator delete(void * b);
//
// void test() {
// A *a = new A;
// delete a;
//
// B* b = new B;
// delete b;
// }
public void testOverloadedDelete_Bug351547() throws Exception {
BindingAssertionHelper bh= new BindingAssertionHelper(getAboveComment(), true);
IBinding m= bh.assertNonProblem("operator delete(void * a)", 15);
IBinding f= bh.assertNonProblem("operator delete(void * b)", 15);
IASTImplicitName[] names = bh.getImplicitNames("delete a;", 6);
assertEquals(2, names.length);
assertSame(m, names[1].resolveBinding());
names = bh.getImplicitNames("delete b;", 6);
assertEquals(2, names.length);
assertSame(f, names[1].resolveBinding());
}
// struct X {}
// int test(X* x) {
// X* xs = new X[5];

View file

@ -2962,14 +2962,14 @@ public class CPPSemantics {
}
}
IASTInitializerClause[] argArray = args.toArray(new IASTInitializerClause[args.size()]);
return findOverloadedOperator(exp, argArray, type, op, LookupMode.ALL_GLOBALS);
return findOverloadedOperator(exp, argArray, type, op, LookupMode.GLOBALS_IF_NO_MEMBERS);
}
public static ICPPFunction findOverloadedOperator(ICPPASTDeleteExpression exp) {
OverloadableOperator op = OverloadableOperator.fromDeleteExpression(exp);
IType classType = getNestedClassType(exp);
IASTExpression[] args = new IASTExpression[] {createArgForType(exp, classType)};
return findOverloadedOperator(exp, args, classType, op, LookupMode.ALL_GLOBALS);
IASTExpression[] args = new IASTExpression[] {createArgForType(exp, classType), exp.getOperand()};
return findOverloadedOperator(exp, args, classType, op, LookupMode.GLOBALS_IF_NO_MEMBERS);
}
private static ICPPClassType getNestedClassType(ICPPASTDeleteExpression exp) {
@ -3228,7 +3228,7 @@ public class CPPSemantics {
return findOverloadedOperator(fieldRef, new IASTExpression[] {arg}, classType, OverloadableOperator.ARROW, LookupMode.NO_GLOBALS);
}
private static enum LookupMode {NO_GLOBALS, LIMITED_GLOBALS, ALL_GLOBALS}
private static enum LookupMode {NO_GLOBALS, GLOBALS_IF_NO_MEMBERS, LIMITED_GLOBALS, ALL_GLOBALS}
private static ICPPFunction findOverloadedOperator(IASTExpression parent, IASTInitializerClause[] args, IType methodLookupType,
OverloadableOperator operator, LookupMode mode) {
ICPPClassType callToObjectOfClassType= null;
@ -3281,43 +3281,64 @@ public class CPPSemantics {
funcName.setParent(parent);
funcName.setPropertyInParent(STRING_LOOKUP_PROPERTY);
LookupData funcData = new LookupData(funcName);
if (operator == OverloadableOperator.DELETE || operator == OverloadableOperator.DELETE_ARRAY) {
args= ArrayUtil.removeFirst(args);
}
funcData.setFunctionArguments(true, args);
funcData.ignoreMembers = true; // (13.3.1.2.3)
if (mode != LookupMode.NO_GLOBALS || callToObjectOfClassType != null) {
boolean haveMembers= methodData != null && methodData.hasResults();
if (mode == LookupMode.ALL_GLOBALS || mode == LookupMode.LIMITED_GLOBALS
|| (mode == LookupMode.GLOBALS_IF_NO_MEMBERS && !haveMembers)) {
try {
if (mode != LookupMode.NO_GLOBALS) {
IScope scope = CPPVisitor.getContainingScope(parent);
if (scope == null)
return null;
lookup(funcData, scope);
try {
doKoenigLookup(funcData);
} catch (DOMException e) {
}
// Filter with file-set
IASTTranslationUnit tu= parent.getTranslationUnit();
if (tu != null && funcData.foundItems instanceof Object[]) {
final IIndexFileSet fileSet = tu.getIndexFileSet();
if (fileSet != null) {
int j=0;
final Object[] items= (Object[]) funcData.foundItems;
for (int i = 0; i < items.length; i++) {
Object item = items[i];
items[i]= null;
if (item instanceof IIndexBinding) {
if (!fileSet.containsDeclaration((IIndexBinding) item)) {
continue;
}
IScope scope = CPPVisitor.getContainingScope(parent);
if (scope == null)
return null;
lookup(funcData, scope);
try {
doKoenigLookup(funcData);
} catch (DOMException e) {
}
// Filter with file-set
IASTTranslationUnit tu= parent.getTranslationUnit();
if (tu != null && funcData.foundItems instanceof Object[]) {
final IIndexFileSet fileSet = tu.getIndexFileSet();
if (fileSet != null) {
int j=0;
final Object[] items= (Object[]) funcData.foundItems;
for (int i = 0; i < items.length; i++) {
Object item = items[i];
items[i]= null;
if (item instanceof IIndexBinding) {
if (!fileSet.containsDeclaration((IIndexBinding) item)) {
continue;
}
items[j++]= item;
}
items[j++]= item;
}
}
}
} catch (DOMException e) {
return null;
}
if (operator == OverloadableOperator.NEW || operator == OverloadableOperator.DELETE
|| operator == OverloadableOperator.NEW_ARRAY || operator == OverloadableOperator.DELETE_ARRAY) {
// Those operators replace the built-in operator
Object[] items= (Object[]) funcData.foundItems;
int j= 0;
for (Object object : items) {
if (object instanceof ICPPFunction) {
ICPPFunction func= (ICPPFunction) object;
if (!(func instanceof CPPImplicitFunction))
items[j++]= func;
}
}
if (j>0) {
while (j < items.length)
items[j++]= null;
}
}
// 13.3.1.2.3
// However, if no operand type has class type, only those non-member functions ...
if (mode == LookupMode.LIMITED_GLOBALS) {
@ -3348,31 +3369,31 @@ public class CPPSemantics {
}
}
}
if (callToObjectOfClassType != null) {
try {
// 13.3.1.1.2 call to object of class type
ICPPMethod[] ops = SemanticUtil.getConversionOperators(callToObjectOfClassType);
for (ICPPMethod op : ops) {
if (op.isExplicit())
continue;
IFunctionType ft= op.getType();
if (ft != null) {
IType rt= SemanticUtil.getNestedType(ft.getReturnType(), SemanticUtil.TDEF);
if (rt instanceof IPointerType) {
IType ptt= SemanticUtil.getNestedType(((IPointerType) rt).getType(), SemanticUtil.TDEF);
if (ptt instanceof IFunctionType) {
IFunctionType ft2= (IFunctionType) ptt;
IBinding sf= createSurrogateCallFunction(parent.getTranslationUnit().getScope(), ft2.getReturnType(), rt, ft2.getParameterTypes());
mergeResults(funcData, sf, false);
}
}
}
}
} catch (DOMException e) {
return null;
}
}
}
if (callToObjectOfClassType != null) {
try {
// 13.3.1.1.2 call to object of class type
ICPPMethod[] ops = SemanticUtil.getConversionOperators(callToObjectOfClassType);
for (ICPPMethod op : ops) {
if (op.isExplicit())
continue;
IFunctionType ft= op.getType();
if (ft != null) {
IType rt= SemanticUtil.getNestedType(ft.getReturnType(), SemanticUtil.TDEF);
if (rt instanceof IPointerType) {
IType ptt= SemanticUtil.getNestedType(((IPointerType) rt).getType(), SemanticUtil.TDEF);
if (ptt instanceof IFunctionType) {
IFunctionType ft2= (IFunctionType) ptt;
IBinding sf= createSurrogateCallFunction(parent.getTranslationUnit().getScope(), ft2.getReturnType(), rt, ft2.getParameterTypes());
mergeResults(funcData, sf, false);
}
}
}
}
} catch (DOMException e) {
return null;
}
}
if (methodLookupType instanceof ICPPClassType || type2 instanceof ICPPClassType) {