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.IASTImplicitNameOwner;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTNodeSelector;
|
import org.eclipse.cdt.core.dom.ast.IASTNodeSelector;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
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.ICPPConstructor;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||||
|
@ -367,8 +368,8 @@ public class AST2CPPImplicitNameTests extends AST2BaseTest {
|
||||||
|
|
||||||
// struct X {
|
// struct X {
|
||||||
// ~X();
|
// ~X();
|
||||||
// void operator delete();
|
// void operator delete(void *);
|
||||||
// void operator delete[]();
|
// void operator delete[](void *);
|
||||||
// };
|
// };
|
||||||
//
|
//
|
||||||
// int test(X* x) {
|
// int test(X* x) {
|
||||||
|
@ -393,11 +394,38 @@ public class AST2CPPImplicitNameTests extends AST2BaseTest {
|
||||||
|
|
||||||
names = ba.getImplicitNames("delete[] x;", 6);
|
names = ba.getImplicitNames("delete[] x;", 6);
|
||||||
assertEquals(1, names.length);
|
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);
|
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 {}
|
// struct X {}
|
||||||
// int test(X* x) {
|
// int test(X* x) {
|
||||||
// X* xs = new X[5];
|
// X* xs = new X[5];
|
||||||
|
|
|
@ -2962,14 +2962,14 @@ public class CPPSemantics {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IASTInitializerClause[] argArray = args.toArray(new IASTInitializerClause[args.size()]);
|
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) {
|
public static ICPPFunction findOverloadedOperator(ICPPASTDeleteExpression exp) {
|
||||||
OverloadableOperator op = OverloadableOperator.fromDeleteExpression(exp);
|
OverloadableOperator op = OverloadableOperator.fromDeleteExpression(exp);
|
||||||
IType classType = getNestedClassType(exp);
|
IType classType = getNestedClassType(exp);
|
||||||
IASTExpression[] args = new IASTExpression[] {createArgForType(exp, classType)};
|
IASTExpression[] args = new IASTExpression[] {createArgForType(exp, classType), exp.getOperand()};
|
||||||
return findOverloadedOperator(exp, args, classType, op, LookupMode.ALL_GLOBALS);
|
return findOverloadedOperator(exp, args, classType, op, LookupMode.GLOBALS_IF_NO_MEMBERS);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ICPPClassType getNestedClassType(ICPPASTDeleteExpression exp) {
|
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);
|
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,
|
private static ICPPFunction findOverloadedOperator(IASTExpression parent, IASTInitializerClause[] args, IType methodLookupType,
|
||||||
OverloadableOperator operator, LookupMode mode) {
|
OverloadableOperator operator, LookupMode mode) {
|
||||||
ICPPClassType callToObjectOfClassType= null;
|
ICPPClassType callToObjectOfClassType= null;
|
||||||
|
@ -3281,36 +3281,39 @@ public class CPPSemantics {
|
||||||
funcName.setParent(parent);
|
funcName.setParent(parent);
|
||||||
funcName.setPropertyInParent(STRING_LOOKUP_PROPERTY);
|
funcName.setPropertyInParent(STRING_LOOKUP_PROPERTY);
|
||||||
LookupData funcData = new LookupData(funcName);
|
LookupData funcData = new LookupData(funcName);
|
||||||
|
if (operator == OverloadableOperator.DELETE || operator == OverloadableOperator.DELETE_ARRAY) {
|
||||||
|
args= ArrayUtil.removeFirst(args);
|
||||||
|
}
|
||||||
funcData.setFunctionArguments(true, args);
|
funcData.setFunctionArguments(true, args);
|
||||||
funcData.ignoreMembers = true; // (13.3.1.2.3)
|
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 {
|
try {
|
||||||
if (mode != LookupMode.NO_GLOBALS) {
|
IScope scope = CPPVisitor.getContainingScope(parent);
|
||||||
IScope scope = CPPVisitor.getContainingScope(parent);
|
if (scope == null)
|
||||||
if (scope == null)
|
return null;
|
||||||
return null;
|
lookup(funcData, scope);
|
||||||
lookup(funcData, scope);
|
try {
|
||||||
try {
|
doKoenigLookup(funcData);
|
||||||
doKoenigLookup(funcData);
|
} catch (DOMException e) {
|
||||||
} catch (DOMException e) {
|
}
|
||||||
}
|
// Filter with file-set
|
||||||
// Filter with file-set
|
IASTTranslationUnit tu= parent.getTranslationUnit();
|
||||||
IASTTranslationUnit tu= parent.getTranslationUnit();
|
if (tu != null && funcData.foundItems instanceof Object[]) {
|
||||||
if (tu != null && funcData.foundItems instanceof Object[]) {
|
final IIndexFileSet fileSet = tu.getIndexFileSet();
|
||||||
final IIndexFileSet fileSet = tu.getIndexFileSet();
|
if (fileSet != null) {
|
||||||
if (fileSet != null) {
|
int j=0;
|
||||||
int j=0;
|
final Object[] items= (Object[]) funcData.foundItems;
|
||||||
final Object[] items= (Object[]) funcData.foundItems;
|
for (int i = 0; i < items.length; i++) {
|
||||||
for (int i = 0; i < items.length; i++) {
|
Object item = items[i];
|
||||||
Object item = items[i];
|
items[i]= null;
|
||||||
items[i]= null;
|
if (item instanceof IIndexBinding) {
|
||||||
if (item instanceof IIndexBinding) {
|
if (!fileSet.containsDeclaration((IIndexBinding) item)) {
|
||||||
if (!fileSet.containsDeclaration((IIndexBinding) item)) {
|
continue;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
items[j++]= item;
|
|
||||||
}
|
}
|
||||||
|
items[j++]= item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3318,6 +3321,24 @@ public class CPPSemantics {
|
||||||
return null;
|
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
|
// 13.3.1.2.3
|
||||||
// However, if no operand type has class type, only those non-member functions ...
|
// However, if no operand type has class type, only those non-member functions ...
|
||||||
if (mode == LookupMode.LIMITED_GLOBALS) {
|
if (mode == LookupMode.LIMITED_GLOBALS) {
|
||||||
|
@ -3348,31 +3369,31 @@ public class CPPSemantics {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (callToObjectOfClassType != null) {
|
if (callToObjectOfClassType != null) {
|
||||||
try {
|
try {
|
||||||
// 13.3.1.1.2 call to object of class type
|
// 13.3.1.1.2 call to object of class type
|
||||||
ICPPMethod[] ops = SemanticUtil.getConversionOperators(callToObjectOfClassType);
|
ICPPMethod[] ops = SemanticUtil.getConversionOperators(callToObjectOfClassType);
|
||||||
for (ICPPMethod op : ops) {
|
for (ICPPMethod op : ops) {
|
||||||
if (op.isExplicit())
|
if (op.isExplicit())
|
||||||
continue;
|
continue;
|
||||||
IFunctionType ft= op.getType();
|
IFunctionType ft= op.getType();
|
||||||
if (ft != null) {
|
if (ft != null) {
|
||||||
IType rt= SemanticUtil.getNestedType(ft.getReturnType(), SemanticUtil.TDEF);
|
IType rt= SemanticUtil.getNestedType(ft.getReturnType(), SemanticUtil.TDEF);
|
||||||
if (rt instanceof IPointerType) {
|
if (rt instanceof IPointerType) {
|
||||||
IType ptt= SemanticUtil.getNestedType(((IPointerType) rt).getType(), SemanticUtil.TDEF);
|
IType ptt= SemanticUtil.getNestedType(((IPointerType) rt).getType(), SemanticUtil.TDEF);
|
||||||
if (ptt instanceof IFunctionType) {
|
if (ptt instanceof IFunctionType) {
|
||||||
IFunctionType ft2= (IFunctionType) ptt;
|
IFunctionType ft2= (IFunctionType) ptt;
|
||||||
IBinding sf= createSurrogateCallFunction(parent.getTranslationUnit().getScope(), ft2.getReturnType(), rt, ft2.getParameterTypes());
|
IBinding sf= createSurrogateCallFunction(parent.getTranslationUnit().getScope(), ft2.getReturnType(), rt, ft2.getParameterTypes());
|
||||||
mergeResults(funcData, sf, false);
|
mergeResults(funcData, sf, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (DOMException e) {
|
} catch (DOMException e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (methodLookupType instanceof ICPPClassType || type2 instanceof ICPPClassType) {
|
if (methodLookupType instanceof ICPPClassType || type2 instanceof ICPPClassType) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue