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:
parent
9d9efe8e9d
commit
34fdfb1196
2 changed files with 107 additions and 58 deletions
|
@ -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];
|
||||
|
|
|
@ -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,36 +3281,39 @@ 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3318,6 +3321,24 @@ public class CPPSemantics {
|
|||
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) {
|
||||
|
|
Loading…
Add table
Reference in a new issue