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:
parent
35e6b69536
commit
a3765fa703
7 changed files with 139 additions and 12 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Add table
Reference in a new issue