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:
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
|
||||
// // A::operator int*()
|
||||
// }
|
||||
public void _test14_5_2s5() throws Exception {
|
||||
public void test14_5_2s5() throws Exception {
|
||||
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Add table
Reference in a new issue