1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-23 08:55:25 +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
// // A::operator int*()
// }
public void _test14_5_2s5() throws Exception {
public void test14_5_2s5() throws Exception {
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
}

View file

@ -6984,4 +6984,24 @@ public class AST2CPPTests extends AST2BaseTest {
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('}');
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);
}
if (!data.forFunctionDeclaration() || data.forExplicitFunctionSpecialization()) {
CPPTemplates.instantiateFunctionTemplates(fns, data.getFunctionArgumentTypes(), data.astName);
if (data.astName instanceof ICPPASTConversionName) {
return resolveUserDefinedConversion(data, fns);
}
if (data.astName instanceof ICPPASTConversionName) {
return resolveUserDefinedConversion((ICPPASTConversionName) data.astName, fns);
if (!data.forFunctionDeclaration() || data.forExplicitFunctionSpecialization()) {
CPPTemplates.instantiateFunctionTemplates(fns, data.getFunctionArgumentTypes(), data.astName);
}
// 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;
}
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());
if (t == null) {
return new ProblemBinding(astName, IProblemBinding.SEMANTIC_INVALID_TYPE);
}
if (!data.forFunctionDeclaration() || data.forExplicitFunctionSpecialization()) {
CPPTemplates.instantiateConversionTemplates(fns, t, data.astName);
}
IFunction unknown= null;
for (IFunction function : fns) {
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.
* 14.8.2.1
*/
static private ICPPTemplateArgument[] deduceTemplateFunctionArguments(ICPPFunctionTemplate template,
ICPPTemplateArgument[] tmplArgs, IType[] fnArgs, CPPTemplateParameterMap map) throws DOMException {
@ -657,6 +658,31 @@ public class CPPTemplates {
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,
CPPTemplateParameterMap tpMap, ICPPTemplateArgument[] args) {
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,
* 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) {
return getContainingScope((IASTStatement) node);
} else if (node instanceof IASTTypeId) {
if (node.getPropertyInParent() == ICPPASTTemplateId.TEMPLATE_ID_ARGUMENT) {
node= node.getParent(); // template-id
ASTNodeProperty prop = node.getPropertyInParent();
if (prop == ICPPASTTemplateId.TEMPLATE_ID_ARGUMENT || prop == ICPPASTConversionName.TYPE_ID) {
node= node.getParent(); // template-id or conversion name
while (node instanceof IASTName) {
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
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -20,6 +20,7 @@ import java.util.ArrayList;
import java.util.List;
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.IPDOMVisitor;
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.IBinding;
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.ICPPClassTemplatePartialSpecialization;
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.IIndexName;
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.CharArrayUtils;
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.SemanticUtil;
import org.eclipse.cdt.internal.core.index.DeclaredBindingsFilter;
import org.eclipse.cdt.internal.core.index.IIndexScope;
import org.eclipse.cdt.internal.core.pdom.PDOM;
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.
*/
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;
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 {
IBinding[] result = null;
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();
if (!prefixLookup) {
if (CharArrayUtils.equals(fBinding.getNameCharArray(), nameChars)) {
@ -121,11 +140,11 @@ class PDOMCPPClassScope implements ICPPClassScope, IIndexScope {
visitor.visit((IPDOMNode) getClassNameBinding());
}
acceptViaCache(fBinding, visitor, true);
result= visitor.getBindings();
return visitor.getBindings();
} catch (CoreException e) {
CCorePlugin.log(e);
}
return result;
return null;
}
public static IBinding[] getBindingsViaCache(IPDOMCPPClassType ct, final char[] name, IndexFilter filter) throws CoreException {