1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Bug 355304: Argument deduction for explicit function template specialization.

This commit is contained in:
Markus Schorn 2011-08-23 15:41:16 +02:00
parent 49342dc9bf
commit 64c383952a
12 changed files with 475 additions and 439 deletions

View file

@ -9480,4 +9480,16 @@ public class AST2CPPTests extends AST2BaseTest {
public void testAmbiguityResolution_Bug354599() throws Exception { public void testAmbiguityResolution_Bug354599() throws Exception {
parseAndCheckBindings(); parseAndCheckBindings();
} }
// void (g)(char);
// void (g )(int);
// void (g )(int);
public void testFunctionRedeclarations() throws Exception {
BindingAssertionHelper bh= getAssertionHelper();
IFunction g1= bh.assertNonProblem("g)", 1);
IFunction g2= bh.assertNonProblem("g )", 1);
IFunction g3= bh.assertNonProblem("g )", 1);
assertNotSame(g1, g2);
assertSame(g2, g3);
}
} }

View file

@ -5454,4 +5454,16 @@ public class AST2TemplateTests extends AST2BaseTest {
public void testTemplateTemplateParameterMatching_352859() throws Exception { public void testTemplateTemplateParameterMatching_352859() throws Exception {
parseAndCheckBindings(); parseAndCheckBindings();
} }
// template<typename T> T f();
// template<> int f() {
// return 0;
// }
public void testArgumentDeductionFromReturnTypeOfExplicitSpecialization_355304() throws Exception {
parseAndCheckBindings();
BindingAssertionHelper bh= new BindingAssertionHelper(getAboveComment(), true);
ICPPFunctionTemplate template= bh.assertNonProblem("f();", 1);
ICPPTemplateInstance inst= bh.assertNonProblem("f() {", 1);
assertSame(template, inst.getTemplateDefinition());
}
} }

View file

@ -11,18 +11,23 @@
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.pdom.tests; package org.eclipse.cdt.internal.pdom.tests;
import java.util.Arrays;
import java.util.List;
import junit.framework.Test; import junit.framework.Test;
import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.IPDOMManager; import org.eclipse.cdt.core.dom.IPDOMManager;
import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionTemplate; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
import org.eclipse.cdt.core.index.IndexFilter; import org.eclipse.cdt.core.index.IndexFilter;
import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.testplugin.CProjectHelper; import org.eclipse.cdt.core.testplugin.CProjectHelper;
import org.eclipse.cdt.core.testplugin.CTestPlugin; import org.eclipse.cdt.core.testplugin.CTestPlugin;
import org.eclipse.cdt.core.testplugin.util.TestSourceReader; import org.eclipse.cdt.core.testplugin.util.TestSourceReader;
import org.eclipse.cdt.internal.core.CCoreInternals; import org.eclipse.cdt.internal.core.CCoreInternals;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInstanceCache;
import org.eclipse.cdt.internal.core.index.IIndexFragment; import org.eclipse.cdt.internal.core.index.IIndexFragment;
import org.eclipse.cdt.internal.core.pdom.PDOM; import org.eclipse.cdt.internal.core.pdom.PDOM;
import org.eclipse.cdt.internal.core.pdom.indexer.IndexerPreferences; import org.eclipse.cdt.internal.core.pdom.indexer.IndexerPreferences;
@ -96,7 +101,15 @@ public class CPPFunctionTemplateTests extends PDOMTestBase {
ICPPFunctionTemplate fooX= (ICPPFunctionTemplate) bs[b ? 0 : 1]; ICPPFunctionTemplate fooX= (ICPPFunctionTemplate) bs[b ? 0 : 1];
ICPPFunctionTemplate fooAB= (ICPPFunctionTemplate) bs[b ? 1 : 0]; ICPPFunctionTemplate fooAB= (ICPPFunctionTemplate) bs[b ? 1 : 0];
assertNameCount(pdom, fooX, IIndexFragment.FIND_REFERENCES, 3); List<ICPPTemplateInstance> instances= Arrays.asList(((ICPPInstanceCache) fooX).getAllInstances());
assertNameCount(pdom, fooAB, IIndexFragment.FIND_REFERENCES, 6); assertEquals(3, instances.size());
for (ICPPTemplateInstance inst : instances) {
assertEquals(1, pdom.findNames(inst, IIndexFragment.FIND_REFERENCES).length);
}
instances= Arrays.asList(((ICPPInstanceCache) fooAB).getAllInstances());
assertEquals(6, instances.size());
for (ICPPTemplateInstance inst : instances) {
assertEquals(1, pdom.findNames(inst, IIndexFragment.FIND_REFERENCES).length);
}
} }
} }

View file

@ -49,6 +49,7 @@ abstract class CElementHandle implements ICElementHandle, ISourceReference {
private IRegion fRegion; private IRegion fRegion;
private long fTimestamp; private long fTimestamp;
private int fIndex;
public CElementHandle(ICElement parent, int type, String name) { public CElementHandle(ICElement parent, int type, String name) {
fParent= parent; fParent= parent;
@ -57,8 +58,8 @@ abstract class CElementHandle implements ICElementHandle, ISourceReference {
// undo this here // undo this here
if (name.length() > 0 && name.charAt(0)=='{') { if (name.length() > 0 && name.charAt(0)=='{') {
fName= ""; //$NON-NLS-1$ fName= ""; //$NON-NLS-1$
} fIndex= name.hashCode();
else { } else {
fName= name; fName= name;
} }
fRegion= new Region(0,0); fRegion= new Region(0,0);
@ -313,6 +314,6 @@ abstract class CElementHandle implements ICElementHandle, ISourceReference {
} }
public int getIndex() { public int getIndex() {
return 0; return fIndex;
} }
} }

View file

@ -163,7 +163,7 @@ public class CPPTemplateParameterMap implements ICPPTemplateParameterMap {
} }
} }
public boolean mergeToExplicit(CPPTemplateParameterMap deducedMap) { public boolean addDeducedArgs(CPPTemplateParameterMap deducedMap) {
Integer[] keys= deducedMap.getAllParameterPositions(); Integer[] keys= deducedMap.getAllParameterPositions();
for (Integer key : keys) { for (Integer key : keys) {
Object explicit= fMap.get(key); Object explicit= fMap.get(key);

View file

@ -458,16 +458,12 @@ public class CPPSemantics {
} }
} }
// explicit function specializations are found via name resolution, need to // Some declarations are found via name resolution (e.g. when using a qualified name),
// add name as definition and check the declaration specifier. // add name as definition and check the declaration specifier.
final IASTDeclaration declaration = data.forDeclaration();
if (declaration != null) {
// Functions
if (binding instanceof IFunction) { if (binding instanceof IFunction) {
if (data.forFunctionDeclaration()) {
IASTNode declaration= data.astName;
while (declaration instanceof IASTName)
declaration= declaration.getParent();
while (declaration instanceof IASTDeclarator)
declaration= declaration.getParent();
binding= checkDeclSpecifier(binding, data.astName, declaration); binding= checkDeclSpecifier(binding, data.astName, declaration);
if (!(binding instanceof IProblemBinding)) { if (!(binding instanceof IProblemBinding)) {
if (declaration instanceof ICPPASTFunctionDefinition) { if (declaration instanceof ICPPASTFunctionDefinition) {
@ -475,24 +471,17 @@ public class CPPSemantics {
} }
} }
} }
} // Definitions of static fields.
// Definitions of static fields are found via name resolution, need to add name to
// the binding to get the right type of arrays that may be declared incomplete.
if (binding instanceof ICPPField && data.astName.isDefinition()) { if (binding instanceof ICPPField && data.astName.isDefinition()) {
IASTNode declaration= data.astName;
while (declaration instanceof IASTName)
declaration= declaration.getParent();
while (declaration instanceof IASTDeclarator)
declaration= declaration.getParent();
if (declaration.getPropertyInParent() != IASTCompositeTypeSpecifier.MEMBER_DECLARATION) { if (declaration.getPropertyInParent() != IASTCompositeTypeSpecifier.MEMBER_DECLARATION) {
ASTInternal.addDefinition(binding, data.astName); ASTInternal.addDefinition(binding, data.astName);
} }
} }
}
// If we're still null... // If we're still null...
if (binding == null) { if (binding == null) {
if (name instanceof ICPPASTQualifiedName && data.forFunctionDeclaration()) { if (name instanceof ICPPASTQualifiedName && declaration != null) {
binding = new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_MEMBER_DECLARATION_NOT_FOUND, binding = new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_MEMBER_DECLARATION_NOT_FOUND,
data.getFoundBindings()); data.getFoundBindings());
} else { } else {
@ -601,9 +590,7 @@ public class CPPSemantics {
data.forceQualified = true; data.forceQualified = true;
} }
if (parent instanceof ICPPASTFunctionDeclarator) { if (parent instanceof IASTIdExpression) {
data.setFunctionParameters(((ICPPASTFunctionDeclarator) parent).getParameters());
} else if (parent instanceof IASTIdExpression) {
IASTNode grand= parent.getParent(); IASTNode grand= parent.getParent();
while (grand instanceof IASTUnaryExpression while (grand instanceof IASTUnaryExpression
&& ((IASTUnaryExpression) grand).getOperator() == IASTUnaryExpression.op_bracketedPrimary) { && ((IASTUnaryExpression) grand).getOperator() == IASTUnaryExpression.op_bracketedPrimary) {
@ -2276,7 +2263,7 @@ public class CPPSemantics {
} }
private static ICPPFunction[] selectByArgumentCount(LookupData data, ICPPFunction[] functions) throws DOMException { private static ICPPFunction[] selectByArgumentCount(LookupData data, ICPPFunction[] functions) throws DOMException {
assert !data.forFunctionDeclaration(); assert data.forDeclaration() == null;
int argumentCount = data.getFunctionArgumentCount(); int argumentCount = data.getFunctionArgumentCount();
@ -2328,16 +2315,6 @@ public class CPPSemantics {
return result; return result;
} }
private static boolean isMatchingFunctionDeclaration(ICPPFunction candidate, LookupData data) {
IASTNode node = data.astName.getParent();
while (node instanceof IASTName)
node = node.getParent();
if (node instanceof IASTDeclarator) {
return isSameFunction(candidate, (IASTDeclarator) node);
}
return false;
}
static IBinding resolveFunction(LookupData data, ICPPFunction[] fns, boolean allowUDC) throws DOMException { static IBinding resolveFunction(LookupData data, ICPPFunction[] fns, boolean allowUDC) throws DOMException {
fns= (ICPPFunction[]) ArrayUtil.trim(ICPPFunction.class, fns); fns= (ICPPFunction[]) ArrayUtil.trim(ICPPFunction.class, fns);
if (fns == null || fns.length == 0) if (fns == null || fns.length == 0)
@ -2348,17 +2325,18 @@ public class CPPSemantics {
if (data.forUsingDeclaration()) if (data.forUsingDeclaration())
return new CPPUsingDeclaration(data.astName, fns); return new CPPUsingDeclaration(data.astName, fns);
// No arguments to resolve function
if (!data.hasFunctionArguments()) {
return createFunctionSet(data.astName, fns);
}
if (data.astName instanceof ICPPASTConversionName) { if (data.astName instanceof ICPPASTConversionName) {
return resolveUserDefinedConversion(data, fns); return resolveUserDefinedConversion(data, fns);
} }
if (data.forFunctionDeclaration()) if (data.forDeclaration() != null) {
return resolveFunctionDeclaration(data, fns); return resolveFunctionDeclaration(data, fns);
}
// No arguments to resolve function
if (!data.hasFunctionArguments()) {
return createFunctionSet(data.astName, fns);
}
// 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
final IType[] argTypes = data.getFunctionArgumentTypes(); final IType[] argTypes = data.getFunctionArgumentTypes();
@ -2519,39 +2497,78 @@ public class CPPSemantics {
} }
} }
/**
* Called for declarations with qualified name or template-id. Also for explicit function
* specializations or instantiations.
*/
private static IBinding resolveFunctionDeclaration(LookupData data, ICPPFunction[] fns) throws DOMException { private static IBinding resolveFunctionDeclaration(LookupData data, ICPPFunction[] fns) throws DOMException {
if (data.forExplicitFunctionSpecialization()) { final IASTDeclarator dtor= ASTQueries.findTypeRelevantDeclarator(data.getDeclarator());
fns = CPPTemplates.instantiateForFunctionCall(data.astName, final IType t = CPPVisitor.createType(dtor);
fns, if (!(t instanceof ICPPFunctionType))
Arrays.asList(data.getFunctionArgumentTypes()), Arrays.asList(data.getFunctionArgumentValueCategories()), return null;
data.argsContainImpliedObject);
} final ICPPFunctionType ft= (ICPPFunctionType) t;
int argCount = data.getFunctionArgumentCount(); IASTName templateID= data.astName;
if (argCount == 1) { if (templateID.getPropertyInParent() == ICPPASTTemplateId.TEMPLATE_NAME) {
// check for parameter of type void templateID= (ICPPASTTemplateId) templateID.getParent();
final IType[] argTypes = data.getFunctionArgumentTypes();
if (argTypes.length == 1 && SemanticUtil.isVoidType(argTypes[0])) {
argCount= 0;
}
} }
// 14.5.4 Friends with template ids require instantiation
boolean isFriend= CPPVisitor.isFriendDeclaration(data.forDeclaration());
if (!data.forExplicitFunctionSpecialization()
&& !(isFriend && templateID instanceof ICPPASTTemplateId)) {
// Search for a matching function
for (ICPPFunction fn : fns) { for (ICPPFunction fn : fns) {
if (fn != null && !(fn instanceof IProblemBinding) && !(fn instanceof ICPPUnknownBinding)) { if (fn != null && !(fn instanceof IProblemBinding) && !(fn instanceof ICPPUnknownBinding)) {
// The index is optimized to provide the function type, avoid using the parameters if (isSameFunction(fn, dtor)) {
// as long as possible.
final IType[] parameterTypes = fn.getType().getParameterTypes();
int parCount = parameterTypes.length;
if (parCount == 1 && SemanticUtil.isVoidType(parameterTypes[0]))
parCount= 0;
if (parCount == argCount && isMatchingFunctionDeclaration(fn, data)) {
return fn; return fn;
} }
} }
} }
// 14.5.4 Friends with qualified ids allow for instantiation
if (!data.forExplicitFunctionInstantiation()
&& !(isFriend && templateID.getParent() instanceof ICPPASTQualifiedName)) {
return null; return null;
} }
}
// Try to instantiate a template
IASTTranslationUnit tu= data.tu;
ICPPTemplateArgument[] tmplArgs= ICPPTemplateArgument.EMPTY_ARGUMENTS;
if (templateID instanceof ICPPASTTemplateId) {
tmplArgs = CPPTemplates.createTemplateArgumentArray((ICPPASTTemplateId) templateID);
}
ICPPFunctionTemplate bestTemplate= null;
ICPPFunction bestInst= null;
boolean isAmbiguous= false;
for (ICPPFunction fn : fns) {
if (fn instanceof ICPPFunctionTemplate
&& !(fn instanceof IProblemBinding) && !(fn instanceof ICPPUnknownBinding)) {
ICPPFunctionTemplate template= (ICPPFunctionTemplate) fn;
ICPPFunction inst= CPPTemplates.instantiateForFunctionDeclaration(template, tmplArgs, ft);
if (inst != null) {
int cmp= CPPTemplates.orderFunctionTemplates(bestTemplate, template, TypeSelection.PARAMETERS_AND_RETURN_TYPE);
if (cmp == 0)
cmp= compareByRelevance(tu, bestTemplate, template);
if (cmp == 0)
isAmbiguous= true;
if (cmp < 0) {
isAmbiguous= false;
bestTemplate= template;
bestInst= inst;
}
}
}
}
if (isAmbiguous)
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, fns);
return bestInst;
}
public static void sortAstBeforeIndex(IFunction[] fns) { public static void sortAstBeforeIndex(IFunction[] fns) {
int iast= 0; int iast= 0;
@ -2691,14 +2708,15 @@ public class CPPSemantics {
return new CPPReferenceType(implicitType, false); return new CPPReferenceType(implicitType, false);
} }
private static IBinding resolveUserDefinedConversion(LookupData data, IFunction[] fns) { private static IBinding resolveUserDefinedConversion(LookupData data, ICPPFunction[] fns) {
ICPPASTConversionName astName= (ICPPASTConversionName) data.astName; ICPPASTConversionName astName= (ICPPASTConversionName) data.astName;
IType t= CPPVisitor.createType(astName.getTypeId()); IType t= CPPVisitor.createType(astName.getTypeId());
if (t instanceof ISemanticProblem) { if (t instanceof ISemanticProblem) {
return new ProblemBinding(astName, IProblemBinding.SEMANTIC_INVALID_TYPE, data.getFoundBindings()); return new ProblemBinding(astName, IProblemBinding.SEMANTIC_INVALID_TYPE, data.getFoundBindings());
} }
if (!data.forFunctionDeclaration() || data.forExplicitFunctionSpecialization()) { if (data.forDeclaration() == null ||
CPPTemplates.instantiateConversionTemplates(fns, t); data.forExplicitFunctionSpecialization() || data.forExplicitFunctionInstantiation()) {
fns= CPPTemplates.instantiateConversionTemplates(fns, t);
} }
IFunction unknown= null; IFunction unknown= null;
@ -2896,12 +2914,10 @@ public class CPPSemantics {
final ICPPFunctionTemplate template = (ICPPFunctionTemplate) fn; final ICPPFunctionTemplate template = (ICPPFunctionTemplate) fn;
ICPPFunction inst= CPPTemplates.instantiateForAddressOfFunction(template, (ICPPFunctionType) targetType, name); ICPPFunction inst= CPPTemplates.instantiateForAddressOfFunction(template, (ICPPFunctionType) targetType, name);
if (inst != null) { if (inst != null) {
int cmp= -1; int cmp= CPPTemplates.orderFunctionTemplates(resultTemplate, template, TypeSelection.PARAMETERS_AND_RETURN_TYPE);
if (result != null) {
cmp= CPPTemplates.orderFunctionTemplates(resultTemplate, template, TypeSelection.PARAMETERS_AND_RETURN_TYPE);
if (cmp == 0) if (cmp == 0)
cmp= compareByRelevance(tu, resultTemplate, template); cmp= compareByRelevance(tu, resultTemplate, template);
}
if (cmp == 0) if (cmp == 0)
isAmbiguous= true; isAmbiguous= true;
@ -3627,7 +3643,9 @@ public class CPPSemantics {
if (templateDecl != null) { if (templateDecl != null) {
if (templateDecl instanceof ICPPASTTemplateSpecialization) { if (templateDecl instanceof ICPPASTTemplateSpecialization) {
if (!(function instanceof ICPPSpecialization)) if (!(function instanceof ICPPTemplateInstance))
return false;
if (!((ICPPTemplateInstance) function).isExplicitSpecialization())
return false; return false;
} else { } else {
if (function instanceof ICPPTemplateDefinition) { if (function instanceof ICPPTemplateDefinition) {

View file

@ -30,6 +30,7 @@ import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory; import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression; import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause; import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
@ -51,6 +52,7 @@ import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.IValue;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition;
@ -706,10 +708,17 @@ public class CPPTemplates {
parentOfName= parentOfName.getParent(); parentOfName= parentOfName.getParent();
} }
return parentOfName instanceof ICPPASTElaboratedTypeSpecifier || if (parentOfName instanceof ICPPASTElaboratedTypeSpecifier ||
parentOfName instanceof ICPPASTCompositeTypeSpecifier || parentOfName instanceof ICPPASTCompositeTypeSpecifier ||
parentOfName instanceof ICPPASTNamedTypeSpecifier || parentOfName instanceof ICPPASTNamedTypeSpecifier ||
parentOfName instanceof ICPPASTBaseSpecifier; parentOfName instanceof ICPPASTBaseSpecifier)
return true;
if (parentOfName instanceof IASTDeclarator) {
IASTDeclarator rel= ASTQueries.findTypeRelevantDeclarator((IASTDeclarator) parentOfName);
return !(rel instanceof IASTFunctionDeclarator);
}
return false;
} }
@ -1310,7 +1319,7 @@ public class CPPTemplates {
// determine nesting level of parent // determine nesting level of parent
int level= missingTemplateDecls; int level= missingTemplateDecls;
if (!CPPVisitor.isFriendFunctionDeclaration(innerMostTDecl.getDeclaration())) { if (!isFriendFunctionDeclaration(innerMostTDecl.getDeclaration())) {
node= outerMostTDecl.getParent(); node= outerMostTDecl.getParent();
while (node != null) { while (node != null) {
if (node instanceof ICPPASTInternalTemplateDeclaration) { if (node instanceof ICPPASTInternalTemplateDeclaration) {
@ -1335,6 +1344,23 @@ public class CPPTemplates {
innerMostTDecl.setAssociatedWithLastName(lastIsTemplate); innerMostTDecl.setAssociatedWithLastName(lastIsTemplate);
} }
private static boolean isFriendFunctionDeclaration(IASTDeclaration declaration) {
while (declaration instanceof ICPPASTTemplateDeclaration) {
declaration= ((ICPPASTTemplateDeclaration) declaration).getDeclaration();
}
if (declaration instanceof IASTSimpleDeclaration) {
IASTSimpleDeclaration sdecl = (IASTSimpleDeclaration) declaration;
ICPPASTDeclSpecifier declspec= (ICPPASTDeclSpecifier) sdecl.getDeclSpecifier();
if (declspec.isFriend()) {
IASTDeclarator[] dtors= sdecl.getDeclarators();
if (dtors.length == 1 && ASTQueries.findTypeRelevantDeclarator(dtors[0]) instanceof IASTFunctionDeclarator) {
return true;
}
}
}
return false;
}
private static CharArraySet collectTemplateParameterNames(ICPPASTTemplateDeclaration tdecl) { private static CharArraySet collectTemplateParameterNames(ICPPASTTemplateDeclaration tdecl) {
CharArraySet set= new CharArraySet(4); CharArraySet set= new CharArraySet(4);
while(true) { while(true) {
@ -1628,24 +1654,30 @@ public class CPPTemplates {
return null; return null;
} }
static void instantiateConversionTemplates(IFunction[] functions, IType conversionType) { /**
* 14.8.2.3 Deducing conversion function template arguments
*/
static ICPPFunction[] instantiateConversionTemplates(ICPPFunction[] functions, IType conversionType) {
boolean checkedForDependentType= false; boolean checkedForDependentType= false;
for (int i = 0; i < functions.length; i++) { ICPPFunction[] result= functions;
IFunction func = functions[i]; int i=0;
if (func instanceof ICPPFunctionTemplate) { boolean done= false;
ICPPFunctionTemplate template= (ICPPFunctionTemplate) func; for (ICPPFunction f : functions) {
functions[i]= null; ICPPFunction inst = f;
if (f instanceof ICPPFunctionTemplate) {
ICPPFunctionTemplate template= (ICPPFunctionTemplate) f;
inst= null;
// extract template arguments and parameter types. // Extract template arguments and parameter types.
if (!checkedForDependentType) { if (!checkedForDependentType) {
try { try {
if (isDependentType(conversionType)) { if (isDependentType(conversionType)) {
functions[i]= CPPUnknownFunction.createForSample(template); inst= CPPUnknownFunction.createForSample(template);
return; done= true;
} }
checkedForDependentType= true; checkedForDependentType= true;
} catch (DOMException e) { } catch (DOMException e) {
return; return functions;
} }
} }
CPPTemplateParameterMap map= new CPPTemplateParameterMap(1); CPPTemplateParameterMap map= new CPPTemplateParameterMap(1);
@ -1653,16 +1685,48 @@ public class CPPTemplates {
ICPPTemplateArgument[] args= TemplateArgumentDeduction.deduceForConversion(template, conversionType, map); ICPPTemplateArgument[] args= TemplateArgumentDeduction.deduceForConversion(template, conversionType, map);
if (args != null) { if (args != null) {
IBinding instance= instantiateFunctionTemplate(template, args, map); IBinding instance= instantiateFunctionTemplate(template, args, map);
if (instance instanceof IFunction) { if (instance instanceof ICPPFunction) {
functions[i]= (IFunction) instance; inst= (ICPPFunction) instance;
} }
} }
} catch (DOMException e) { } catch (DOMException e) {
// try next candidate // try next candidate
} }
} }
if (result != functions || f != inst) {
if (result == functions) {
result= new ICPPFunction[functions.length];
System.arraycopy(functions, 0, result, 0, i);
}
result[i++]= inst;
}
if (done)
break;
}
return result;
}
/**
* 14.8.2.6 Deducing template arguments from a function declaration
* @return
*/
static ICPPFunction instantiateForFunctionDeclaration(ICPPFunctionTemplate template,
ICPPTemplateArgument[] args, ICPPFunctionType functionType) {
CPPTemplateParameterMap map= new CPPTemplateParameterMap(1);
try {
args= TemplateArgumentDeduction.deduceForDeclaration(template, args, functionType, map);
if (args != null) {
IBinding instance= instantiateFunctionTemplate(template, args, map);
if (instance instanceof ICPPFunction) {
return (ICPPFunction) instance;
} }
} }
} catch (DOMException e) {
// try next candidate
}
return null;
}
/** /**
* 14.8.2.2 Deducing template arguments taking the address of a function template [temp.deduct.funcaddr] * 14.8.2.2 Deducing template arguments taking the address of a function template [temp.deduct.funcaddr]
@ -1702,6 +1766,13 @@ public class CPPTemplates {
// 14.5.6.2 Partial ordering of function templates // 14.5.6.2 Partial ordering of function templates
static int orderFunctionTemplates(ICPPFunctionTemplate f1, ICPPFunctionTemplate f2, TypeSelection mode) static int orderFunctionTemplates(ICPPFunctionTemplate f1, ICPPFunctionTemplate f2, TypeSelection mode)
throws DOMException { throws DOMException {
if (f1 == f2)
return 0;
if (f1 == null)
return -1;
if (f2 == null)
return 1;
int s1 = compareSpecialization(f1, f2, mode); int s1 = compareSpecialization(f1, f2, mode);
int s2 = compareSpecialization(f2, f1, mode); int s2 = compareSpecialization(f2, f1, mode);

View file

@ -633,13 +633,7 @@ public class CPPVisitor extends ASTQueries {
boolean isFriendDecl= false; boolean isFriendDecl= false;
ICPPScope scope = (ICPPScope) getContainingNonTemplateScope(name); ICPPScope scope = (ICPPScope) getContainingNonTemplateScope(name);
if (scope instanceof ICPPClassScope) { if (scope instanceof ICPPClassScope) {
if (parent instanceof IASTSimpleDeclaration) { isFriendDecl = isFriendDeclaration(parent);
ICPPASTDeclSpecifier declSpec = (ICPPASTDeclSpecifier) ((IASTSimpleDeclaration) parent).getDeclSpecifier();
isFriendDecl= declSpec.isFriend();
} else if (parent instanceof IASTFunctionDefinition) {
ICPPASTDeclSpecifier declSpec = (ICPPASTDeclSpecifier) ((IASTFunctionDefinition) parent).getDeclSpecifier();
isFriendDecl= declSpec.isFriend();
}
if (isFriendDecl) { if (isFriendDecl) {
try { try {
while (scope.getKind() == EScopeKind.eClassType) { while (scope.getKind() == EScopeKind.eClassType) {
@ -753,6 +747,18 @@ public class CPPVisitor extends ASTQueries {
return binding; return binding;
} }
public static boolean isFriendDeclaration(IASTNode decl) {
IASTDeclSpecifier declSpec;
if (decl instanceof IASTSimpleDeclaration) {
declSpec = ((IASTSimpleDeclaration) decl).getDeclSpecifier();
} else if (decl instanceof IASTFunctionDefinition) {
declSpec = ((IASTFunctionDefinition) decl).getDeclSpecifier();
} else {
return false;
}
return declSpec instanceof ICPPASTDeclSpecifier && ((ICPPASTDeclSpecifier) declSpec).isFriend();
}
public static boolean isConstructor(IScope containingScope, IASTDeclarator declarator) { public static boolean isConstructor(IScope containingScope, IASTDeclarator declarator) {
if (containingScope == null || !(containingScope instanceof ICPPClassScope)) if (containingScope == null || !(containingScope instanceof ICPPClassScope))
return false; return false;
@ -2340,7 +2346,6 @@ public class CPPVisitor extends ASTQueries {
*/ */
public static IBinding findDeclarationOwner(IASTNode node, boolean allowFunction) { public static IBinding findDeclarationOwner(IASTNode node, boolean allowFunction) {
// Search for declaration // Search for declaration
boolean isFriend= false;
boolean isNonSimpleElabDecl= false; boolean isNonSimpleElabDecl= false;
while (!(node instanceof IASTDeclaration)) { while (!(node instanceof IASTDeclaration)) {
if (node == null) if (node == null)
@ -2360,19 +2365,7 @@ public class CPPVisitor extends ASTQueries {
node= node.getParent(); node= node.getParent();
} }
if (node instanceof IASTSimpleDeclaration) { boolean isFriend= isFriendDeclaration(node);
final IASTSimpleDeclaration sdecl = (IASTSimpleDeclaration) node;
ICPPASTDeclSpecifier declSpec= (ICPPASTDeclSpecifier) sdecl.getDeclSpecifier();
if (declSpec.isFriend()) {
isFriend= true;
}
} else if (node instanceof IASTFunctionDefinition) {
IASTFunctionDefinition funcDefinition = (IASTFunctionDefinition) node;
ICPPASTDeclSpecifier declSpec = (ICPPASTDeclSpecifier) funcDefinition.getDeclSpecifier();
if (declSpec.isFriend()) {
isFriend= true;
}
}
// Search for enclosing binding // Search for enclosing binding
IASTName name= null; IASTName name= null;
@ -2409,26 +2402,6 @@ public class CPPVisitor extends ASTQueries {
return name.resolveBinding(); return name.resolveBinding();
} }
/**
* Check whether a given declaration is a friend function declaration.
*/
public static boolean isFriendFunctionDeclaration(IASTDeclaration declaration) {
while (declaration instanceof ICPPASTTemplateDeclaration) {
declaration= ((ICPPASTTemplateDeclaration) declaration).getDeclaration();
}
if (declaration instanceof IASTSimpleDeclaration) {
IASTSimpleDeclaration sdecl = (IASTSimpleDeclaration) declaration;
ICPPASTDeclSpecifier declspec= (ICPPASTDeclSpecifier) sdecl.getDeclSpecifier();
if (declspec.isFriend()) {
IASTDeclarator[] dtors= sdecl.getDeclarators();
if (dtors.length == 1 && findTypeRelevantDeclarator(dtors[0]) instanceof IASTFunctionDeclarator) {
return true;
}
}
}
return false;
}
public static boolean doesNotSpecifyType(IASTDeclSpecifier declspec) { public static boolean doesNotSpecifyType(IASTDeclSpecifier declspec) {
if (declspec instanceof ICPPASTSimpleDeclSpecifier) { if (declspec instanceof ICPPASTSimpleDeclSpecifier) {
ICPPASTSimpleDeclSpecifier ds= (ICPPASTSimpleDeclSpecifier) declspec; ICPPASTSimpleDeclSpecifier ds= (ICPPASTSimpleDeclSpecifier) declspec;

View file

@ -684,10 +684,11 @@ public class Conversions {
final IType uqSource= getNestedType(source, TDEF | REF | CVTYPE); final IType uqSource= getNestedType(source, TDEF | REF | CVTYPE);
if (uqSource instanceof ICPPClassType) { if (uqSource instanceof ICPPClassType) {
ICPPMethod[] ops = SemanticUtil.getConversionOperators((ICPPClassType) uqSource); ICPPFunction[] ops = SemanticUtil.getConversionOperators((ICPPClassType) uqSource);
CPPTemplates.instantiateConversionTemplates(ops, t); ops= CPPTemplates.instantiateConversionTemplates(ops, t);
for (final ICPPMethod op : ops) { for (final ICPPFunction f : ops) {
if (op != null && !(op instanceof IProblemBinding)) { if (f instanceof ICPPMethod && !(f instanceof IProblemBinding)) {
ICPPMethod op= (ICPPMethod) f;
if (op.isExplicit()) if (op.isExplicit())
continue; continue;
final IType returnType = op.getType().getReturnType(); final IType returnType = op.getType().getReturnType();
@ -733,12 +734,13 @@ public class Conversions {
c.setDeferredUDC(DeferredUDC.INIT_BY_CONVERSION); c.setDeferredUDC(DeferredUDC.INIT_BY_CONVERSION);
return c; return c;
} }
ICPPMethod[] ops = SemanticUtil.getConversionOperators(uqSource); ICPPFunction[] ops = SemanticUtil.getConversionOperators(uqSource);
CPPTemplates.instantiateConversionTemplates(ops, target); ops= CPPTemplates.instantiateConversionTemplates(ops, target);
FunctionCost cost1= null; FunctionCost cost1= null;
Cost cost2= null; Cost cost2= null;
for (final ICPPMethod op : ops) { for (final ICPPFunction f : ops) {
if (op != null && !(op instanceof IProblemBinding)) { if (f instanceof ICPPMethod && !(f instanceof IProblemBinding)) {
ICPPMethod op= (ICPPMethod) f;
final boolean isExplicitConversion= op.isExplicit(); final boolean isExplicitConversion= op.isExplicit();
if (isExplicitConversion /** && !direct **/) if (isExplicitConversion /** && !direct **/)
continue; continue;

View file

@ -14,7 +14,6 @@
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.valueCategoryFromReturnType;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getSimplifiedType; import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getSimplifiedType;
import java.util.Collections; import java.util.Collections;
@ -53,7 +52,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldReference; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldReference;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerList; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerList;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
@ -69,7 +67,6 @@ import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap; import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.core.parser.util.ObjectSet; import org.eclipse.cdt.core.parser.util.ObjectSet;
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding; import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTranslationUnit; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTranslationUnit;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPCompositeBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPCompositeBinding;
@ -103,7 +100,6 @@ public class LookupData {
/** In list-initialization **/ /** In list-initialization **/
public boolean fNoNarrowing= false; public boolean fNoNarrowing= false;
private ICPPASTParameterDeclaration[] functionParameters;
private IASTInitializerClause[] functionArgs; private IASTInitializerClause[] functionArgs;
private IType[] functionArgTypes; private IType[] functionArgTypes;
private ValueCategory[] functionArgValueCategories; private ValueCategory[] functionArgValueCategories;
@ -171,81 +167,58 @@ public class LookupData {
return false; return false;
} }
public boolean forFunctionDeclaration() { /**
if (astName == null) return false; * Returns whether the name belongs to a simple declaration or function definition.
if (astName.getPropertyInParent() == CPPSemantics.STRING_LOOKUP_PROPERTY) return false; */
public IASTDeclaration forDeclaration() {
IASTNode node = getDeclarator();
IASTName n = astName; while (node instanceof IASTDeclarator)
if (n.getParent() instanceof ICPPASTTemplateId) node= node.getParent();
n = (IASTName) n.getParent();
IASTNode p1 = n.getParent(); if (node instanceof IASTSimpleDeclaration || node instanceof IASTFunctionDefinition)
if (p1 instanceof ICPPASTQualifiedName) { return (IASTDeclaration) node;
if (((ICPPASTQualifiedName) p1).getLastName() != n)
return false; return null;
p1 = p1.getParent();
} }
if (p1 instanceof IASTDeclarator) { public IASTDeclarator getDeclarator() {
IASTNode p2= ASTQueries.findOutermostDeclarator((IASTDeclarator) p1).getParent(); IASTName name= astName;
if (p2 instanceof IASTSimpleDeclaration) { if (name == null || name.getPropertyInParent() == CPPSemantics.STRING_LOOKUP_PROPERTY)
if (p2.getParent() instanceof ICPPASTExplicitTemplateInstantiation) return null;
return false;
if (astName instanceof ICPPASTTemplateId &&
((ICPPASTDeclSpecifier)((IASTSimpleDeclaration) p2).getDeclSpecifier()).isFriend())
return false;
return true; if (name.getParent() instanceof ICPPASTTemplateId)
name= (IASTName) name.getParent();
IASTNode node= name.getParent();
if (node instanceof ICPPASTQualifiedName) {
if (((ICPPASTQualifiedName) node).getLastName() != name)
return null;
node = node.getParent();
} }
return p2 instanceof IASTFunctionDefinition;
} if (node instanceof IASTDeclarator)
return false; return (IASTDeclarator) node;
return null;
} }
public boolean forExplicitFunctionSpecialization() { public boolean forExplicitFunctionSpecialization() {
if (astName == null) return false; IASTDeclaration decl= forDeclaration();
if (astName.getPropertyInParent() == CPPSemantics.STRING_LOOKUP_PROPERTY) return false; if (decl != null) {
IASTName n = astName; IASTName n = astName;
if (n.getParent() instanceof ICPPASTTemplateId) if (n.getParent() instanceof ICPPASTTemplateId)
n = (IASTName) n.getParent(); n = (IASTName) n.getParent();
IASTNode p1 = n.getParent();
if (p1 instanceof ICPPASTQualifiedName) {
if (((ICPPASTQualifiedName) p1).getLastName() != n)
return false;
p1 = p1.getParent();
}
if (p1 instanceof IASTDeclarator) {
IASTNode p2= ASTQueries.findOutermostDeclarator((IASTDeclarator) p1).getParent();
if (p2 instanceof IASTSimpleDeclaration || p2 instanceof IASTFunctionDefinition) {
ICPPASTTemplateDeclaration tmplDecl = CPPTemplates.getTemplateDeclaration(n); ICPPASTTemplateDeclaration tmplDecl = CPPTemplates.getTemplateDeclaration(n);
return tmplDecl instanceof ICPPASTTemplateSpecialization; return tmplDecl instanceof ICPPASTTemplateSpecialization;
} }
}
return false; return false;
} }
public boolean forExplicitFunctionInstantiation() { public boolean forExplicitFunctionInstantiation() {
if (astName == null) return false; IASTDeclaration decl= forDeclaration();
if (astName.getPropertyInParent() == CPPSemantics.STRING_LOOKUP_PROPERTY) return false; return decl != null && decl.getParent() instanceof ICPPASTExplicitTemplateInstantiation;
IASTName n = astName;
if (n.getParent() instanceof ICPPASTTemplateId)
n = (IASTName) n.getParent();
IASTNode p1 = n.getParent();
if (p1 instanceof ICPPASTQualifiedName) {
if (((ICPPASTQualifiedName) p1).getLastName() != n)
return false;
p1 = p1.getParent();
}
if (p1 instanceof IASTDeclarator) {
IASTNode p2= ASTQueries.findOutermostDeclarator((IASTDeclarator) p1).getParent();
if (p2 instanceof IASTDeclaration) {
return p2.getParent() instanceof ICPPASTExplicitTemplateInstantiation;
}
}
return false;
} }
public boolean qualified() { public boolean qualified() {
@ -414,14 +387,6 @@ public class LookupData {
} }
return CPPVisitor.getImpliedObjectType(scope); return CPPVisitor.getImpliedObjectType(scope);
} }
if (prop == IASTDeclarator.DECLARATOR_NAME) {
if (forExplicitFunctionInstantiation()) {
IScope scope = CPPVisitor.getContainingScope(astName);
if (scope instanceof ICPPClassScope) {
return ((ICPPClassScope) scope).getClassType();
}
}
}
return null; return null;
} }
@ -491,13 +456,7 @@ public class LookupData {
return false; return false;
if (p instanceof IASTDeclaration) { if (p instanceof IASTDeclaration) {
if (prop == IASTCompositeTypeSpecifier.MEMBER_DECLARATION) { if (prop == IASTCompositeTypeSpecifier.MEMBER_DECLARATION) {
if (p instanceof IASTSimpleDeclaration) { return CPPVisitor.isFriendDeclaration(p);
ICPPASTDeclSpecifier declSpec = (ICPPASTDeclSpecifier) ((IASTSimpleDeclaration) p).getDeclSpecifier();
return declSpec.isFriend();
} else if (p instanceof IASTFunctionDefinition) {
ICPPASTDeclSpecifier declSpec = (ICPPASTDeclSpecifier) ((IASTFunctionDefinition) p).getDeclSpecifier();
return declSpec.isFriend();
}
} else { } else {
return false; return false;
} }
@ -547,13 +506,6 @@ public class LookupData {
functionArgTypes[i]= new InitializerListType((ICPPASTInitializerList) e); functionArgTypes[i]= new InitializerListType((ICPPASTInitializerList) e);
} }
} }
} else if (functionParameters != null) {
ICPPASTParameterDeclaration[] pdecls= functionParameters;
functionArgTypes= new IType[pdecls.length];
for (int i = 0; i < pdecls.length; i++) {
functionArgTypes[i] = SemanticUtil.getSimplifiedType(CPPVisitor.createType(
pdecls[i], true));
}
} }
} }
return functionArgTypes; return functionArgTypes;
@ -570,36 +522,19 @@ public class LookupData {
functionArgValueCategories[i] = ExpressionTypes.valueCat((IASTExpression) arg); functionArgValueCategories[i] = ExpressionTypes.valueCat((IASTExpression) arg);
} }
} }
} else {
IType[] argTypes= getFunctionArgumentTypes();
if (argTypes != null) {
functionArgValueCategories= new ValueCategory[argTypes.length];
for (int i = 0; i < argTypes.length; i++) {
IType t= argTypes[i];
functionArgValueCategories[i]= valueCategoryFromReturnType(t);
}
} else {
functionArgValueCategories= new ValueCategory[0];
}
} }
} }
return functionArgValueCategories; return functionArgValueCategories;
} }
public void setFunctionParameters(ICPPASTParameterDeclaration[] parameters) {
functionParameters= parameters;
}
public int getFunctionArgumentCount() { public int getFunctionArgumentCount() {
if (functionArgs != null) if (functionArgs != null)
return functionArgs.length; return functionArgs.length;
if (functionParameters != null)
return functionParameters.length;
return 0; return 0;
} }
public boolean hasFunctionArguments() { public boolean hasFunctionArguments() {
return functionArgs != null || functionParameters != null; return functionArgs != null;
} }
public IBinding[] getFoundBindings() { public IBinding[] getFoundBindings() {

View file

@ -38,6 +38,7 @@ 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;
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.ICPPFunctionTemplate; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameterPackType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameterPackType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType;
@ -67,181 +68,16 @@ public class TemplateArgumentDeduction {
static ICPPTemplateArgument[] deduceForFunctionCall(ICPPFunctionTemplate template, static ICPPTemplateArgument[] deduceForFunctionCall(ICPPFunctionTemplate template,
ICPPTemplateArgument[] tmplArgs, List<IType> fnArgs, List<ValueCategory> argIsLValue, CPPTemplateParameterMap map) ICPPTemplateArgument[] tmplArgs, List<IType> fnArgs, List<ValueCategory> argIsLValue, CPPTemplateParameterMap map)
throws DOMException { throws DOMException {
final ICPPTemplateParameter[] tmplParams = template.getTemplateParameters(); final ICPPTemplateParameter[] tmplParams = template.getTemplateParameters();
final int numTmplParams = tmplParams.length;
final int numTmplArgs = tmplArgs.length;
tmplArgs= SemanticUtil.getSimplifiedArguments(tmplArgs); if (!addExplicitArguments(tmplParams, tmplArgs, map))
ICPPTemplateParameter tmplParam= null;
int packOffset= -1;
for (int i = 0; i < numTmplArgs; i++) {
if (packOffset < 0 || tmplParam == null) {
if (i >= numTmplParams)
return null; return null;
tmplParam= tmplParams[i];
if (tmplParam.isParameterPack()) {
packOffset= i;
}
}
ICPPTemplateArgument tmplArg= tmplArgs[i];
tmplArg= CPPTemplates.matchTemplateParameterAndArgument(tmplParam, tmplArg, map);
if (tmplArg == null)
return null;
if (packOffset < 0) {
map.put(tmplParam, tmplArg);
}
}
if (packOffset >= 0) {
final int packSize= tmplArgs.length- packOffset;
ICPPTemplateArgument[] pack= new ICPPTemplateArgument[packSize];
System.arraycopy(tmplArgs, packOffset, pack, 0, packSize);
map.put(tmplParam, pack);
}
if (!deduceFromFunctionArgs(template, fnArgs, argIsLValue, map)) if (!deduceFromFunctionArgs(template, fnArgs, argIsLValue, map))
return null; return null;
List<ICPPTemplateArgument> result= new ArrayList<ICPPTemplateArgument>(numTmplParams); return createArguments(map, tmplParams);
for (ICPPTemplateParameter tpar : tmplParams) {
if (tpar.isParameterPack()) {
ICPPTemplateArgument[] deducedArgs= map.getPackExpansion(tpar);
if (deducedArgs == null)
return null;
result.addAll(Arrays.asList(deducedArgs));
} else {
ICPPTemplateArgument deducedArg= map.getArgument(tpar);
if (deducedArg == null) {
deducedArg= tpar.getDefaultValue();
if (deducedArg == null)
return null;
}
result.add(deducedArg);
}
}
return result.toArray(new ICPPTemplateArgument[result.size()]);
}
/**
* 14.8.2.2 [temp.deduct.funcaddr]
* Deducing template arguments taking the address of a function template
* @throws DOMException
*/
static ICPPTemplateArgument[] deduceForAddressOf(ICPPFunctionTemplate template,
ICPPTemplateArgument[] tmplArgs, IFunctionType arg, CPPTemplateParameterMap map) throws DOMException {
final ICPPTemplateParameter[] tmplParams = template.getTemplateParameters();
final int numTmplParams = tmplParams.length;
final int numTmplArgs = tmplArgs.length;
tmplArgs= SemanticUtil.getSimplifiedArguments(tmplArgs);
ICPPTemplateParameter tmplParam= null;
int packOffset= -1;
for (int i = 0; i < numTmplArgs; i++) {
if (packOffset < 0 || tmplParam == null) {
if (i >= numTmplParams)
return null;
tmplParam= tmplParams[i];
if (tmplParam.isParameterPack()) {
packOffset= i;
}
}
ICPPTemplateArgument tmplArg= tmplArgs[i];
tmplArg= CPPTemplates.matchTemplateParameterAndArgument(tmplParam, tmplArg, map);
if (tmplArg == null)
return null;
if (packOffset < 0) {
map.put(tmplParam, tmplArg);
}
}
if (packOffset >= 0) {
final int packSize= tmplArgs.length- packOffset;
ICPPTemplateArgument[] pack= new ICPPTemplateArgument[packSize];
System.arraycopy(tmplArgs, packOffset, pack, 0, packSize);
map.put(tmplParam, pack);
}
IType par= template.getType();
par= CPPTemplates.instantiateType(par, map, -1, null);
if (!CPPTemplates.isValidType(par))
return null;
boolean isDependentPar= CPPTemplates.isDependentType(par);
if (isDependentPar) {
TemplateArgumentDeduction deduct= new TemplateArgumentDeduction(tmplParams, map, new CPPTemplateParameterMap(tmplParams.length), 0);
par= SemanticUtil.getNestedType(par, SemanticUtil.TDEF);
if (arg != null && !deduct.fromType(par, arg, false))
return null;
if (!map.mergeToExplicit(deduct.fDeducedArgs))
return null;
}
if (!verifyDeduction(tmplParams, map, true))
return null;
if (isDependentPar)
par= CPPTemplates.instantiateType(par, map, -1, null);
if (arg == null || arg.isSameType(par)) {
List<ICPPTemplateArgument> result= new ArrayList<ICPPTemplateArgument>(numTmplParams);
for (ICPPTemplateParameter tpar : tmplParams) {
if (tpar.isParameterPack()) {
ICPPTemplateArgument[] deducedArgs= map.getPackExpansion(tpar);
if (deducedArgs == null)
return null;
result.addAll(Arrays.asList(deducedArgs));
} else {
ICPPTemplateArgument deducedArg= map.getArgument(tpar);
if (deducedArg == null) {
deducedArg= tpar.getDefaultValue();
if (deducedArg == null)
return null;
}
result.add(deducedArg);
}
}
return result.toArray(new ICPPTemplateArgument[result.size()]);
}
return null;
}
/**
* Deduce arguments for a user defined conversion template
* 14.8.2.3
*/
static ICPPTemplateArgument[] deduceForConversion(ICPPFunctionTemplate template,
IType conversionType, CPPTemplateParameterMap map) throws DOMException {
final ICPPTemplateParameter[] tmplParams = template.getTemplateParameters();
final int length = tmplParams.length;
ICPPTemplateArgument[] result = new ICPPTemplateArgument[length];
IType a= SemanticUtil.getSimplifiedType(conversionType);
IType p= template.getType().getReturnType();
p= getArgumentTypeForDeduction(p, a instanceof ICPPReferenceType);
a= SemanticUtil.getNestedType(a, SemanticUtil.REF | SemanticUtil.TDEF);
TemplateArgumentDeduction deduct= new TemplateArgumentDeduction(tmplParams, null, map, 0);
if (!deduct.fromType(p, a, false)) {
return null;
}
for (int i = 0; i < length; i++) {
if (result[i] == null) {
final ICPPTemplateParameter tpar = tmplParams[i];
ICPPTemplateArgument deducedArg= map.getArgument(tpar);
if (deducedArg == null) {
deducedArg= tpar.getDefaultValue();
if (deducedArg == null)
return null;
}
result[i]= deducedArg;
}
}
return result;
} }
/** /**
@ -253,9 +89,6 @@ public class TemplateArgumentDeduction {
try { try {
IType[] fnPars = template.getType().getParameterTypes(); IType[] fnPars = template.getType().getParameterTypes();
final int fnParCount = fnPars.length; final int fnParCount = fnPars.length;
if (fnParCount == 0)
return true;
final ICPPTemplateParameter[] tmplPars = template.getTemplateParameters(); final ICPPTemplateParameter[] tmplPars = template.getTemplateParameters();
TemplateArgumentDeduction deduct= new TemplateArgumentDeduction(tmplPars, map, new CPPTemplateParameterMap(fnParCount), 0); TemplateArgumentDeduction deduct= new TemplateArgumentDeduction(tmplPars, map, new CPPTemplateParameterMap(fnParCount), 0);
IType fnParPack= null; IType fnParPack= null;
@ -338,7 +171,7 @@ public class TemplateArgumentDeduction {
} }
} }
if (!deduct.fExplicitArgs.mergeToExplicit(deduct.fDeducedArgs)) if (!map.addDeducedArgs(deduct.fDeducedArgs))
return false; return false;
return verifyDeduction(tmplPars, map, true); return verifyDeduction(tmplPars, map, true);
@ -407,6 +240,112 @@ public class TemplateArgumentDeduction {
return deduct.fromType(par, arg, true); return deduct.fromType(par, arg, true);
} }
/**
* 14.8.2.2 [temp.deduct.funcaddr]
* Deducing template arguments taking the address of a function template
* @throws DOMException
*/
static ICPPTemplateArgument[] deduceForAddressOf(ICPPFunctionTemplate template,
ICPPTemplateArgument[] tmplArgs, IFunctionType arg, CPPTemplateParameterMap map) throws DOMException {
final ICPPTemplateParameter[] tmplParams = template.getTemplateParameters();
if (!addExplicitArguments(tmplParams, tmplArgs, map))
return null;
IType par= template.getType();
par= CPPTemplates.instantiateType(par, map, -1, null);
if (!CPPTemplates.isValidType(par))
return null;
boolean isDependentPar= CPPTemplates.isDependentType(par);
if (isDependentPar) {
TemplateArgumentDeduction deduct= new TemplateArgumentDeduction(tmplParams, map, new CPPTemplateParameterMap(tmplParams.length), 0);
par= SemanticUtil.getNestedType(par, SemanticUtil.TDEF);
if (arg != null && !deduct.fromType(par, arg, false))
return null;
if (!map.addDeducedArgs(deduct.fDeducedArgs))
return null;
}
if (!verifyDeduction(tmplParams, map, true))
return null;
if (isDependentPar)
par= CPPTemplates.instantiateType(par, map, -1, null);
if (arg == null || arg.isSameType(par)) {
return createArguments(map, tmplParams);
}
return null;
}
/**
* Deduce arguments for a user defined conversion template
* 14.8.2.3
*/
static ICPPTemplateArgument[] deduceForConversion(ICPPFunctionTemplate template,
IType conversionType, CPPTemplateParameterMap map) throws DOMException {
final ICPPTemplateParameter[] tmplParams = template.getTemplateParameters();
final int length = tmplParams.length;
ICPPTemplateArgument[] result = new ICPPTemplateArgument[length];
IType a= SemanticUtil.getSimplifiedType(conversionType);
IType p= template.getType().getReturnType();
p= getArgumentTypeForDeduction(p, a instanceof ICPPReferenceType);
a= SemanticUtil.getNestedType(a, SemanticUtil.REF | SemanticUtil.TDEF);
TemplateArgumentDeduction deduct= new TemplateArgumentDeduction(tmplParams, null, map, 0);
if (!deduct.fromType(p, a, false)) {
return null;
}
for (int i = 0; i < length; i++) {
if (result[i] == null) {
final ICPPTemplateParameter tpar = tmplParams[i];
ICPPTemplateArgument deducedArg= map.getArgument(tpar);
if (deducedArg == null) {
deducedArg= tpar.getDefaultValue();
if (deducedArg == null)
return null;
}
result[i]= deducedArg;
}
}
return result;
}
/**
* Deduce arguments for a function declaration
* 14.8.2.6
*/
static ICPPTemplateArgument[] deduceForDeclaration(ICPPFunctionTemplate template,
ICPPTemplateArgument[] args, ICPPFunctionType ftype, CPPTemplateParameterMap map) throws DOMException {
final ICPPTemplateParameter[] tmplParams = template.getTemplateParameters();
if (!addExplicitArguments(tmplParams, args, map))
return null;
IType a= SemanticUtil.getSimplifiedType(ftype);
IType p= CPPTemplates.instantiateType(template.getType(), map, -1, null);
if (!CPPTemplates.isValidType(p))
return null;
TemplateArgumentDeduction deduct= new TemplateArgumentDeduction(tmplParams, map, new CPPTemplateParameterMap(tmplParams.length), 0);
if (!deduct.fromType(p, a, false)) {
return null;
}
if (!map.addDeducedArgs(deduct.fDeducedArgs))
return null;
if (!verifyDeduction(tmplParams, map, true))
return null;
IType type= CPPTemplates.instantiateType(p, map, -1, null);
if (!ftype.isSameType(type))
return null;
return createArguments(map, tmplParams);
}
/** /**
* 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.
@ -470,6 +409,64 @@ public class TemplateArgumentDeduction {
return isMoreCVQualified ? 1 : 0; return isMoreCVQualified ? 1 : 0;
} }
/**
* Adds the explicit arguments to the map.
*/
private static boolean addExplicitArguments(final ICPPTemplateParameter[] tmplParams,
ICPPTemplateArgument[] tmplArgs, CPPTemplateParameterMap map) {
tmplArgs= SemanticUtil.getSimplifiedArguments(tmplArgs);
ICPPTemplateParameter tmplParam= null;
int packOffset= -1;
for (int i = 0; i < tmplArgs.length; i++) {
if (packOffset < 0 || tmplParam == null) {
if (i >= tmplParams.length)
return false;
tmplParam= tmplParams[i];
if (tmplParam.isParameterPack()) {
packOffset= i;
}
}
ICPPTemplateArgument tmplArg= tmplArgs[i];
tmplArg= CPPTemplates.matchTemplateParameterAndArgument(tmplParam, tmplArg, map);
if (tmplArg == null)
return false;
if (packOffset < 0) {
map.put(tmplParam, tmplArg);
}
}
if (packOffset >= 0) {
final int packSize= tmplArgs.length- packOffset;
ICPPTemplateArgument[] pack= new ICPPTemplateArgument[packSize];
System.arraycopy(tmplArgs, packOffset, pack, 0, packSize);
map.put(tmplParam, pack);
}
return true;
}
private static ICPPTemplateArgument[] createArguments(CPPTemplateParameterMap map,
final ICPPTemplateParameter[] tmplParams) {
List<ICPPTemplateArgument> result= new ArrayList<ICPPTemplateArgument>(tmplParams.length);
for (ICPPTemplateParameter tpar : tmplParams) {
if (tpar.isParameterPack()) {
ICPPTemplateArgument[] deducedArgs= map.getPackExpansion(tpar);
if (deducedArgs == null)
return null;
result.addAll(Arrays.asList(deducedArgs));
} else {
ICPPTemplateArgument deducedArg= map.getArgument(tpar);
if (deducedArg == null) {
return null;
}
result.add(deducedArg);
}
}
return result.toArray(new ICPPTemplateArgument[result.size()]);
}
/** /**
* 14.8.2.1.3 If P is a class and has the form template-id, then A can be a derived class of the deduced A. * 14.8.2.1.3 If P is a class and has the form template-id, then A can be a derived class of the deduced A.
*/ */

View file

@ -43,6 +43,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDirective; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDirective;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceAlias; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceAlias;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
@ -254,7 +255,8 @@ abstract public class PDOMWriter {
try { try {
final IBinding binding = name.resolveBinding(); final IBinding binding = name.resolveBinding();
if (name.getPropertyInParent() == ICPPASTTemplateId.TEMPLATE_NAME && if (name.getPropertyInParent() == ICPPASTTemplateId.TEMPLATE_NAME &&
((IASTName) name.getParent()).getBinding() == binding) { (((IASTName) name.getParent()).getBinding() == binding ||
binding instanceof ICPPFunctionTemplate)) {
na[0]= null; na[0]= null;
} else if (binding instanceof IProblemBinding) { } else if (binding instanceof IProblemBinding) {
fStatistics.fProblemBindingCount++; fStatistics.fProblemBindingCount++;