1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-09-08 11:03:28 +02:00

Resolution of explicit use of user-defined conversions, bug 267221.

This commit is contained in:
Markus Schorn 2009-03-06 08:18:40 +00:00
parent 35e6b69536
commit a3765fa703
7 changed files with 139 additions and 12 deletions

View file

@ -4603,7 +4603,7 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
// ip = a.operator int*(); // explicit call to template operator // ip = a.operator int*(); // explicit call to template operator
// // A::operator int*() // // A::operator int*()
// } // }
public void _test14_5_2s5() throws Exception { public void test14_5_2s5() throws Exception {
parse(getAboveComment(), ParserLanguage.CPP, true, 0); parse(getAboveComment(), ParserLanguage.CPP, true, 0);
} }

View file

@ -6984,4 +6984,24 @@ public class AST2CPPTests extends AST2BaseTest {
parseAndCheckBindings(code, ParserLanguage.CPP); parseAndCheckBindings(code, ParserLanguage.CPP);
} }
// namespace ns {
// struct S {
// int a;
// };
// }
// class A {
// public:
// operator ns::S*(){return 0;};
// };
// namespace ns {
// void bla() {
// A a;
// a.operator S *();
// }
// }
public void testLookupScopeForConversionNames_267221() throws Exception {
final String code = getAboveComment();
parseAndCheckBindings(code, ParserLanguage.CPP);
}
} }

View file

@ -1116,4 +1116,24 @@ public class IndexCPPBindingResolutionBugs extends IndexBindingResolutionTestBas
buf.append('}'); buf.append('}');
return buf.toString(); return buf.toString();
} }
// namespace ns {
// struct S {
// int a;
// };
// }
// class A {
// public:
// template<typename T> operator T*(){return 0;};
// };
// namespace ns {
// void bla() {
// A a;
// a.operator S *();
// }
// }
public void testLookupScopeForConversionNames_267221() throws Exception {
getBindingFromASTName("operator S *", 12, ICPPMethod.class);
}
} }

View file

@ -2007,12 +2007,12 @@ public class CPPSemantics {
return resolveTargetedFunction(data, fns); return resolveTargetedFunction(data, fns);
} }
if (!data.forFunctionDeclaration() || data.forExplicitFunctionSpecialization()) { if (data.astName instanceof ICPPASTConversionName) {
CPPTemplates.instantiateFunctionTemplates(fns, data.getFunctionArgumentTypes(), data.astName); return resolveUserDefinedConversion(data, fns);
} }
if (data.astName instanceof ICPPASTConversionName) { if (!data.forFunctionDeclaration() || data.forExplicitFunctionSpecialization()) {
return resolveUserDefinedConversion((ICPPASTConversionName) data.astName, fns); CPPTemplates.instantiateFunctionTemplates(fns, data.getFunctionArgumentTypes(), data.astName);
} }
// Reduce our set of candidate functions to only those who have the right number of parameters // Reduce our set of candidate functions to only those who have the right number of parameters
@ -2240,11 +2240,16 @@ public class CPPSemantics {
return implicitType; return implicitType;
} }
private static IBinding resolveUserDefinedConversion(ICPPASTConversionName astName, IFunction[] fns) { private static IBinding resolveUserDefinedConversion(LookupData data, IFunction[] fns) {
ICPPASTConversionName astName= (ICPPASTConversionName) data.astName;
IType t= CPPVisitor.createType(astName.getTypeId()); IType t= CPPVisitor.createType(astName.getTypeId());
if (t == null) { if (t == null) {
return new ProblemBinding(astName, IProblemBinding.SEMANTIC_INVALID_TYPE); return new ProblemBinding(astName, IProblemBinding.SEMANTIC_INVALID_TYPE);
} }
if (!data.forFunctionDeclaration() || data.forExplicitFunctionSpecialization()) {
CPPTemplates.instantiateConversionTemplates(fns, t, data.astName);
}
IFunction unknown= null; IFunction unknown= null;
for (IFunction function : fns) { for (IFunction function : fns) {
if (function != null) { if (function != null) {

View file

@ -621,6 +621,7 @@ public class CPPTemplates {
/** /**
* Deduce arguments for a template function from the template id + the template function parameters. * Deduce arguments for a template function from the template id + the template function parameters.
* 14.8.2.1
*/ */
static private ICPPTemplateArgument[] deduceTemplateFunctionArguments(ICPPFunctionTemplate template, static private ICPPTemplateArgument[] deduceTemplateFunctionArguments(ICPPFunctionTemplate template,
ICPPTemplateArgument[] tmplArgs, IType[] fnArgs, CPPTemplateParameterMap map) throws DOMException { ICPPTemplateArgument[] tmplArgs, IType[] fnArgs, CPPTemplateParameterMap map) throws DOMException {
@ -657,6 +658,31 @@ public class CPPTemplates {
return result; return result;
} }
/**
* Deduce arguments for a user defined conversion template
* 14.8.2.3
*/
static private ICPPTemplateArgument[] deduceTemplateConversionArguments(ICPPFunctionTemplate template,
IType conversionType, CPPTemplateParameterMap map) throws DOMException {
final ICPPTemplateParameter[] tmplParams = template.getTemplateParameters();
final int length = tmplParams.length;
ICPPTemplateArgument[] result = new ICPPTemplateArgument[length];
if (!deduceTemplateParameterMap(template.getType().getReturnType(), conversionType, map)) {
return null;
}
for (int i = 0; i < length; i++) {
if (result[i] == null) {
ICPPTemplateArgument deducedArg= map.getArgument(tmplParams[i]);
if (deducedArg == null)
return null;
result[i]= deducedArg;
}
}
return result;
}
public static ICPPTemplateInstance createInstance(IBinding owner, ICPPTemplateDefinition template, public static ICPPTemplateInstance createInstance(IBinding owner, ICPPTemplateDefinition template,
CPPTemplateParameterMap tpMap, ICPPTemplateArgument[] args) { CPPTemplateParameterMap tpMap, ICPPTemplateArgument[] args) {
if (owner instanceof ICPPSpecialization) { if (owner instanceof ICPPSpecialization) {
@ -1354,6 +1380,42 @@ public class CPPTemplates {
} }
} }
static protected void instantiateConversionTemplates(IFunction[] functions, IType conversionType, IASTName name) {
boolean checkedForDependentType= false;
for (int i = 0; i < functions.length; i++) {
IFunction func = functions[i];
if (func instanceof ICPPFunctionTemplate) {
ICPPFunctionTemplate template= (ICPPFunctionTemplate) func;
functions[i]= null;
// extract template arguments and parameter types.
if (!checkedForDependentType) {
try {
if (isDependentType(conversionType)) {
functions[i]= CPPUnknownFunction.createForSample(template, name);
return;
}
checkedForDependentType= true;
} catch (DOMException e) {
return;
}
}
CPPTemplateParameterMap map= new CPPTemplateParameterMap(1);
try {
ICPPTemplateArgument[] args= deduceTemplateConversionArguments(template, conversionType, map);
if (args != null) {
IBinding instance= instantiateFunctionTemplate(template, args);
if (instance instanceof IFunction) {
functions[i]= (IFunction) instance;
}
}
} catch (DOMException e) {
// try next candidate
}
}
}
}
/** /**
* Deduces the mapping for the template parameters from the function parameters, * Deduces the mapping for the template parameters from the function parameters,
* returns <code>false</code> if there is no mapping. * returns <code>false</code> if there is no mapping.

View file

@ -786,8 +786,9 @@ public class CPPVisitor extends ASTQueries {
} else if (node instanceof IASTStatement) { } else if (node instanceof IASTStatement) {
return getContainingScope((IASTStatement) node); return getContainingScope((IASTStatement) node);
} else if (node instanceof IASTTypeId) { } else if (node instanceof IASTTypeId) {
if (node.getPropertyInParent() == ICPPASTTemplateId.TEMPLATE_ID_ARGUMENT) { ASTNodeProperty prop = node.getPropertyInParent();
node= node.getParent(); // template-id if (prop == ICPPASTTemplateId.TEMPLATE_ID_ARGUMENT || prop == ICPPASTConversionName.TYPE_ID) {
node= node.getParent(); // template-id or conversion name
while (node instanceof IASTName) { while (node instanceof IASTName) {
node= node.getParent(); node= node.getParent();
} }

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2005, 2008 QNX Software Systems and others. * Copyright (c) 2005, 2009 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -20,6 +20,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ILinkage;
import org.eclipse.cdt.core.dom.IPDOMNode; import org.eclipse.cdt.core.dom.IPDOMNode;
import org.eclipse.cdt.core.dom.IPDOMVisitor; import org.eclipse.cdt.core.dom.IPDOMVisitor;
import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.DOMException;
@ -27,6 +28,7 @@ import org.eclipse.cdt.core.dom.ast.EScopeKind;
import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.ICompositeType; import org.eclipse.cdt.core.dom.ast.ICompositeType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConversionName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
@ -37,10 +39,13 @@ import org.eclipse.cdt.core.index.IIndexBinding;
import org.eclipse.cdt.core.index.IIndexFileSet; import org.eclipse.cdt.core.index.IIndexFileSet;
import org.eclipse.cdt.core.index.IIndexName; import org.eclipse.cdt.core.index.IIndexName;
import org.eclipse.cdt.core.index.IndexFilter; import org.eclipse.cdt.core.index.IndexFilter;
import org.eclipse.cdt.core.parser.Keywords;
import org.eclipse.cdt.core.parser.util.CharArrayMap; import org.eclipse.cdt.core.parser.util.CharArrayMap;
import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassScope; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassScope;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
import org.eclipse.cdt.internal.core.index.DeclaredBindingsFilter;
import org.eclipse.cdt.internal.core.index.IIndexScope; import org.eclipse.cdt.internal.core.index.IIndexScope;
import org.eclipse.cdt.internal.core.pdom.PDOM; import org.eclipse.cdt.internal.core.pdom.PDOM;
import org.eclipse.cdt.internal.core.pdom.dom.BindingCollector; import org.eclipse.cdt.internal.core.pdom.dom.BindingCollector;
@ -51,6 +56,15 @@ import org.eclipse.core.runtime.CoreException;
* Represents the class scope for a class stored in the index. * Represents the class scope for a class stored in the index.
*/ */
class PDOMCPPClassScope implements ICPPClassScope, IIndexScope { class PDOMCPPClassScope implements ICPPClassScope, IIndexScope {
private static final IndexFilter CONVERSION_FILTER = new DeclaredBindingsFilter(ILinkage.CPP_LINKAGE_ID, true, false) {
@Override
public boolean acceptBinding(IBinding binding) throws CoreException {
return binding instanceof ICPPMethod &&
SemanticUtil.isConversionOperator(((ICPPMethod) binding)) &&
super.acceptBinding(binding);
}
};
private IPDOMCPPClassType fBinding; private IPDOMCPPClassType fBinding;
public PDOMCPPClassScope(IPDOMCPPClassType binding) { public PDOMCPPClassScope(IPDOMCPPClassType binding) {
@ -101,8 +115,13 @@ class PDOMCPPClassScope implements ICPPClassScope, IIndexScope {
} }
public IBinding[] getBindings(IASTName name, boolean resolve, boolean prefixLookup, IIndexFileSet fileSet) throws DOMException { public IBinding[] getBindings(IASTName name, boolean resolve, boolean prefixLookup, IIndexFileSet fileSet) throws DOMException {
IBinding[] result = null;
try { try {
if (name instanceof ICPPASTConversionName) {
BindingCollector visitor = new BindingCollector(fBinding.getLinkage(), Keywords.cOPERATOR, CONVERSION_FILTER, true, true);
acceptViaCache(fBinding, visitor, true);
return visitor.getBindings();
}
final char[] nameChars = name.getSimpleID(); final char[] nameChars = name.getSimpleID();
if (!prefixLookup) { if (!prefixLookup) {
if (CharArrayUtils.equals(fBinding.getNameCharArray(), nameChars)) { if (CharArrayUtils.equals(fBinding.getNameCharArray(), nameChars)) {
@ -121,11 +140,11 @@ class PDOMCPPClassScope implements ICPPClassScope, IIndexScope {
visitor.visit((IPDOMNode) getClassNameBinding()); visitor.visit((IPDOMNode) getClassNameBinding());
} }
acceptViaCache(fBinding, visitor, true); acceptViaCache(fBinding, visitor, true);
result= visitor.getBindings(); return visitor.getBindings();
} catch (CoreException e) { } catch (CoreException e) {
CCorePlugin.log(e); CCorePlugin.log(e);
} }
return result; return null;
} }
public static IBinding[] getBindingsViaCache(IPDOMCPPClassType ct, final char[] name, IndexFilter filter) throws CoreException { public static IBinding[] getBindingsViaCache(IPDOMCPPClassType ct, final char[] name, IndexFilter filter) throws CoreException {