diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPImplicitNameTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPImplicitNameTests.java index 70f6b939bcf..40ddef7549d 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPImplicitNameTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPImplicitNameTests.java @@ -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]; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java index 822b794a9ce..dfa676eeb50 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java @@ -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) {