diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java index 6b0d18b3fc3..013c8924b4a 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java @@ -9480,4 +9480,16 @@ public class AST2CPPTests extends AST2BaseTest { public void testAmbiguityResolution_Bug354599() throws Exception { 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); + } } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java index bf1f8b09d8f..a5ea4b878a2 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java @@ -5454,4 +5454,16 @@ public class AST2TemplateTests extends AST2BaseTest { public void testTemplateTemplateParameterMatching_352859() throws Exception { parseAndCheckBindings(); } + + // template 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()); + } } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/CPPFunctionTemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/CPPFunctionTemplateTests.java index cdb7fdd4eb8..82e8550af9d 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/CPPFunctionTemplateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/CPPFunctionTemplateTests.java @@ -11,18 +11,23 @@ *******************************************************************************/ package org.eclipse.cdt.internal.pdom.tests; +import java.util.Arrays; +import java.util.List; + import junit.framework.Test; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.IPDOMManager; 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.ICPPTemplateInstance; import org.eclipse.cdt.core.index.IndexFilter; import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.core.testplugin.CProjectHelper; import org.eclipse.cdt.core.testplugin.CTestPlugin; import org.eclipse.cdt.core.testplugin.util.TestSourceReader; 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.pdom.PDOM; 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 fooAB= (ICPPFunctionTemplate) bs[b ? 1 : 0]; - assertNameCount(pdom, fooX, IIndexFragment.FIND_REFERENCES, 3); - assertNameCount(pdom, fooAB, IIndexFragment.FIND_REFERENCES, 6); + List instances= Arrays.asList(((ICPPInstanceCache) fooX).getAllInstances()); + 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); + } } } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ext/CElementHandle.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ext/CElementHandle.java index e7f81ee9fe9..36932ec7aa2 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ext/CElementHandle.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ext/CElementHandle.java @@ -49,6 +49,7 @@ abstract class CElementHandle implements ICElementHandle, ISourceReference { private IRegion fRegion; private long fTimestamp; + private int fIndex; public CElementHandle(ICElement parent, int type, String name) { fParent= parent; @@ -57,8 +58,8 @@ abstract class CElementHandle implements ICElementHandle, ISourceReference { // undo this here if (name.length() > 0 && name.charAt(0)=='{') { fName= ""; //$NON-NLS-1$ - } - else { + fIndex= name.hashCode(); + } else { fName= name; } fRegion= new Region(0,0); @@ -313,6 +314,6 @@ abstract class CElementHandle implements ICElementHandle, ISourceReference { } public int getIndex() { - return 0; + return fIndex; } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateParameterMap.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateParameterMap.java index d1ce349769a..3d5bc411e5b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateParameterMap.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateParameterMap.java @@ -163,7 +163,7 @@ public class CPPTemplateParameterMap implements ICPPTemplateParameterMap { } } - public boolean mergeToExplicit(CPPTemplateParameterMap deducedMap) { + public boolean addDeducedArgs(CPPTemplateParameterMap deducedMap) { Integer[] keys= deducedMap.getAllParameterPositions(); for (Integer key : keys) { Object explicit= fMap.get(key); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java index eb7ec223333..2a087805332 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java @@ -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. - 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(); - + final IASTDeclaration declaration = data.forDeclaration(); + if (declaration != null) { + // Functions + if (binding instanceof IFunction) { binding= checkDeclSpecifier(binding, data.astName, declaration); if (!(binding instanceof IProblemBinding)) { if (declaration instanceof ICPPASTFunctionDefinition) { @@ -475,24 +471,17 @@ public class CPPSemantics { } } } - } - - // 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()) { - IASTNode declaration= data.astName; - while (declaration instanceof IASTName) - declaration= declaration.getParent(); - while (declaration instanceof IASTDeclarator) - declaration= declaration.getParent(); - if (declaration.getPropertyInParent() != IASTCompositeTypeSpecifier.MEMBER_DECLARATION) { - ASTInternal.addDefinition(binding, data.astName); + // Definitions of static fields. + if (binding instanceof ICPPField && data.astName.isDefinition()) { + if (declaration.getPropertyInParent() != IASTCompositeTypeSpecifier.MEMBER_DECLARATION) { + ASTInternal.addDefinition(binding, data.astName); + } } } - + // If we're still 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, data.getFoundBindings()); } else { @@ -601,9 +590,7 @@ public class CPPSemantics { data.forceQualified = true; } - if (parent instanceof ICPPASTFunctionDeclarator) { - data.setFunctionParameters(((ICPPASTFunctionDeclarator) parent).getParameters()); - } else if (parent instanceof IASTIdExpression) { + if (parent instanceof IASTIdExpression) { IASTNode grand= parent.getParent(); while (grand instanceof IASTUnaryExpression && ((IASTUnaryExpression) grand).getOperator() == IASTUnaryExpression.op_bracketedPrimary) { @@ -2276,7 +2263,7 @@ public class CPPSemantics { } private static ICPPFunction[] selectByArgumentCount(LookupData data, ICPPFunction[] functions) throws DOMException { - assert !data.forFunctionDeclaration(); + assert data.forDeclaration() == null; int argumentCount = data.getFunctionArgumentCount(); @@ -2328,16 +2315,6 @@ public class CPPSemantics { 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 { fns= (ICPPFunction[]) ArrayUtil.trim(ICPPFunction.class, fns); if (fns == null || fns.length == 0) @@ -2348,17 +2325,18 @@ public class CPPSemantics { if (data.forUsingDeclaration()) return new CPPUsingDeclaration(data.astName, fns); - // No arguments to resolve function - if (!data.hasFunctionArguments()) { - return createFunctionSet(data.astName, fns); - } - if (data.astName instanceof ICPPASTConversionName) { return resolveUserDefinedConversion(data, fns); } - if (data.forFunctionDeclaration()) + if (data.forDeclaration() != null) { 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 final IType[] argTypes = data.getFunctionArgumentTypes(); @@ -2519,38 +2497,77 @@ 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 { - if (data.forExplicitFunctionSpecialization()) { - fns = CPPTemplates.instantiateForFunctionCall(data.astName, - fns, - Arrays.asList(data.getFunctionArgumentTypes()), Arrays.asList(data.getFunctionArgumentValueCategories()), - data.argsContainImpliedObject); + final IASTDeclarator dtor= ASTQueries.findTypeRelevantDeclarator(data.getDeclarator()); + final IType t = CPPVisitor.createType(dtor); + if (!(t instanceof ICPPFunctionType)) + return null; + + final ICPPFunctionType ft= (ICPPFunctionType) t; + + IASTName templateID= data.astName; + if (templateID.getPropertyInParent() == ICPPASTTemplateId.TEMPLATE_NAME) { + templateID= (ICPPASTTemplateId) templateID.getParent(); + } + + // 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) { + if (fn != null && !(fn instanceof IProblemBinding) && !(fn instanceof ICPPUnknownBinding)) { + if (isSameFunction(fn, dtor)) { + return fn; + } + } + } + // 14.5.4 Friends with qualified ids allow for instantiation + if (!data.forExplicitFunctionInstantiation() + && !(isFriend && templateID.getParent() instanceof ICPPASTQualifiedName)) { + 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); } - int argCount = data.getFunctionArgumentCount(); - if (argCount == 1) { - // check for parameter of type void - final IType[] argTypes = data.getFunctionArgumentTypes(); - if (argTypes.length == 1 && SemanticUtil.isVoidType(argTypes[0])) { - argCount= 0; - } - } - - for (ICPPFunction fn : fns) { - if (fn != null && !(fn instanceof IProblemBinding) && !(fn instanceof ICPPUnknownBinding)) { - // The index is optimized to provide the function type, avoid using the parameters - // 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 null; + 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) { @@ -2691,14 +2708,15 @@ public class CPPSemantics { 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; IType t= CPPVisitor.createType(astName.getTypeId()); if (t instanceof ISemanticProblem) { return new ProblemBinding(astName, IProblemBinding.SEMANTIC_INVALID_TYPE, data.getFoundBindings()); } - if (!data.forFunctionDeclaration() || data.forExplicitFunctionSpecialization()) { - CPPTemplates.instantiateConversionTemplates(fns, t); + if (data.forDeclaration() == null || + data.forExplicitFunctionSpecialization() || data.forExplicitFunctionInstantiation()) { + fns= CPPTemplates.instantiateConversionTemplates(fns, t); } IFunction unknown= null; @@ -2896,12 +2914,10 @@ public class CPPSemantics { final ICPPFunctionTemplate template = (ICPPFunctionTemplate) fn; ICPPFunction inst= CPPTemplates.instantiateForAddressOfFunction(template, (ICPPFunctionType) targetType, name); if (inst != null) { - int cmp= -1; - if (result != null) { - cmp= CPPTemplates.orderFunctionTemplates(resultTemplate, template, TypeSelection.PARAMETERS_AND_RETURN_TYPE); - if (cmp == 0) - cmp= compareByRelevance(tu, resultTemplate, template); - } + int cmp= CPPTemplates.orderFunctionTemplates(resultTemplate, template, TypeSelection.PARAMETERS_AND_RETURN_TYPE); + if (cmp == 0) + cmp= compareByRelevance(tu, resultTemplate, template); + if (cmp == 0) isAmbiguous= true; @@ -3627,7 +3643,9 @@ public class CPPSemantics { if (templateDecl != null) { if (templateDecl instanceof ICPPASTTemplateSpecialization) { - if (!(function instanceof ICPPSpecialization)) + if (!(function instanceof ICPPTemplateInstance)) + return false; + if (!((ICPPTemplateInstance) function).isExplicitSpecialization()) return false; } else { if (function instanceof ICPPTemplateDefinition) { @@ -3641,7 +3659,7 @@ public class CPPSemantics { } } else if (function instanceof ICPPTemplateDefinition) { return false; - } + } declarator= ASTQueries.findTypeRelevantDeclarator(declarator); if (declarator instanceof ICPPASTFunctionDeclarator) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java index aef3e512a70..a3cb25d933c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java @@ -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.IASTExpression; 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.IASTIdExpression; 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.cpp.ICPPASTCompositeTypeSpecifier; 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.ICPPASTExplicitTemplateInstantiation; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition; @@ -706,10 +708,17 @@ public class CPPTemplates { parentOfName= parentOfName.getParent(); } - return parentOfName instanceof ICPPASTElaboratedTypeSpecifier || + if (parentOfName instanceof ICPPASTElaboratedTypeSpecifier || parentOfName instanceof ICPPASTCompositeTypeSpecifier || 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 int level= missingTemplateDecls; - if (!CPPVisitor.isFriendFunctionDeclaration(innerMostTDecl.getDeclaration())) { + if (!isFriendFunctionDeclaration(innerMostTDecl.getDeclaration())) { node= outerMostTDecl.getParent(); while (node != null) { if (node instanceof ICPPASTInternalTemplateDeclaration) { @@ -1335,6 +1344,23 @@ public class CPPTemplates { 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) { CharArraySet set= new CharArraySet(4); while(true) { @@ -1628,24 +1654,30 @@ public class CPPTemplates { 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; - for (int i = 0; i < functions.length; i++) { - IFunction func = functions[i]; - if (func instanceof ICPPFunctionTemplate) { - ICPPFunctionTemplate template= (ICPPFunctionTemplate) func; - functions[i]= null; + ICPPFunction[] result= functions; + int i=0; + boolean done= false; + for (ICPPFunction f : functions) { + 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) { try { if (isDependentType(conversionType)) { - functions[i]= CPPUnknownFunction.createForSample(template); - return; + inst= CPPUnknownFunction.createForSample(template); + done= true; } checkedForDependentType= true; } catch (DOMException e) { - return; + return functions; } } CPPTemplateParameterMap map= new CPPTemplateParameterMap(1); @@ -1653,16 +1685,48 @@ public class CPPTemplates { ICPPTemplateArgument[] args= TemplateArgumentDeduction.deduceForConversion(template, conversionType, map); if (args != null) { IBinding instance= instantiateFunctionTemplate(template, args, map); - if (instance instanceof IFunction) { - functions[i]= (IFunction) instance; + if (instance instanceof ICPPFunction) { + inst= (ICPPFunction) instance; } } } catch (DOMException e) { // 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] @@ -1702,6 +1766,13 @@ public class CPPTemplates { // 14.5.6.2 Partial ordering of function templates static int orderFunctionTemplates(ICPPFunctionTemplate f1, ICPPFunctionTemplate f2, TypeSelection mode) throws DOMException { + if (f1 == f2) + return 0; + if (f1 == null) + return -1; + if (f2 == null) + return 1; + int s1 = compareSpecialization(f1, f2, mode); int s2 = compareSpecialization(f2, f1, mode); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java index 049f19d97f4..ebf43313861 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java @@ -633,13 +633,7 @@ public class CPPVisitor extends ASTQueries { boolean isFriendDecl= false; ICPPScope scope = (ICPPScope) getContainingNonTemplateScope(name); if (scope instanceof ICPPClassScope) { - if (parent instanceof IASTSimpleDeclaration) { - ICPPASTDeclSpecifier declSpec = (ICPPASTDeclSpecifier) ((IASTSimpleDeclaration) parent).getDeclSpecifier(); - isFriendDecl= declSpec.isFriend(); - } else if (parent instanceof IASTFunctionDefinition) { - ICPPASTDeclSpecifier declSpec = (ICPPASTDeclSpecifier) ((IASTFunctionDefinition) parent).getDeclSpecifier(); - isFriendDecl= declSpec.isFriend(); - } + isFriendDecl = isFriendDeclaration(parent); if (isFriendDecl) { try { while (scope.getKind() == EScopeKind.eClassType) { @@ -753,6 +747,18 @@ public class CPPVisitor extends ASTQueries { 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) { if (containingScope == null || !(containingScope instanceof ICPPClassScope)) return false; @@ -2340,7 +2346,6 @@ public class CPPVisitor extends ASTQueries { */ public static IBinding findDeclarationOwner(IASTNode node, boolean allowFunction) { // Search for declaration - boolean isFriend= false; boolean isNonSimpleElabDecl= false; while (!(node instanceof IASTDeclaration)) { if (node == null) @@ -2360,19 +2365,7 @@ public class CPPVisitor extends ASTQueries { node= node.getParent(); } - if (node instanceof IASTSimpleDeclaration) { - 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; - } - } + boolean isFriend= isFriendDeclaration(node); // Search for enclosing binding IASTName name= null; @@ -2409,26 +2402,6 @@ public class CPPVisitor extends ASTQueries { 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) { if (declspec instanceof ICPPASTSimpleDeclSpecifier) { ICPPASTSimpleDeclSpecifier ds= (ICPPASTSimpleDeclSpecifier) declspec; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java index 25b732fb3e3..e6e19133d69 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java @@ -684,10 +684,11 @@ public class Conversions { final IType uqSource= getNestedType(source, TDEF | REF | CVTYPE); if (uqSource instanceof ICPPClassType) { - ICPPMethod[] ops = SemanticUtil.getConversionOperators((ICPPClassType) uqSource); - CPPTemplates.instantiateConversionTemplates(ops, t); - for (final ICPPMethod op : ops) { - if (op != null && !(op instanceof IProblemBinding)) { + ICPPFunction[] ops = SemanticUtil.getConversionOperators((ICPPClassType) uqSource); + ops= CPPTemplates.instantiateConversionTemplates(ops, t); + for (final ICPPFunction f : ops) { + if (f instanceof ICPPMethod && !(f instanceof IProblemBinding)) { + ICPPMethod op= (ICPPMethod) f; if (op.isExplicit()) continue; final IType returnType = op.getType().getReturnType(); @@ -733,12 +734,13 @@ public class Conversions { c.setDeferredUDC(DeferredUDC.INIT_BY_CONVERSION); return c; } - ICPPMethod[] ops = SemanticUtil.getConversionOperators(uqSource); - CPPTemplates.instantiateConversionTemplates(ops, target); + ICPPFunction[] ops = SemanticUtil.getConversionOperators(uqSource); + ops= CPPTemplates.instantiateConversionTemplates(ops, target); FunctionCost cost1= null; Cost cost2= null; - for (final ICPPMethod op : ops) { - if (op != null && !(op instanceof IProblemBinding)) { + for (final ICPPFunction f : ops) { + if (f instanceof ICPPMethod && !(f instanceof IProblemBinding)) { + ICPPMethod op= (ICPPMethod) f; final boolean isExplicitConversion= op.isExplicit(); if (isExplicitConversion /** && !direct **/) continue; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java index 41095ccab2a..201d5c4a69d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java @@ -14,7 +14,6 @@ *******************************************************************************/ 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 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.ICPPASTInitializerList; 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.ICPPASTTemplateDeclaration; 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.CharArrayUtils; 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.cpp.CPPASTTranslationUnit; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPCompositeBinding; @@ -103,7 +100,6 @@ public class LookupData { /** In list-initialization **/ public boolean fNoNarrowing= false; - private ICPPASTParameterDeclaration[] functionParameters; private IASTInitializerClause[] functionArgs; private IType[] functionArgTypes; private ValueCategory[] functionArgValueCategories; @@ -171,81 +167,58 @@ public class LookupData { return false; } - public boolean forFunctionDeclaration() { - if (astName == null) return false; - if (astName.getPropertyInParent() == CPPSemantics.STRING_LOOKUP_PROPERTY) return false; + /** + * Returns whether the name belongs to a simple declaration or function definition. + */ + public IASTDeclaration forDeclaration() { + IASTNode node = getDeclarator(); + + while (node instanceof IASTDeclarator) + node= node.getParent(); + + if (node instanceof IASTSimpleDeclaration || node instanceof IASTFunctionDefinition) + return (IASTDeclaration) node; - 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(); - } + return null; + } + + public IASTDeclarator getDeclarator() { + IASTName name= astName; + if (name == null || name.getPropertyInParent() == CPPSemantics.STRING_LOOKUP_PROPERTY) + return null; - if (p1 instanceof IASTDeclarator) { - IASTNode p2= ASTQueries.findOutermostDeclarator((IASTDeclarator) p1).getParent(); - if (p2 instanceof IASTSimpleDeclaration) { - if (p2.getParent() instanceof ICPPASTExplicitTemplateInstantiation) - return false; - if (astName instanceof ICPPASTTemplateId && - ((ICPPASTDeclSpecifier)((IASTSimpleDeclaration) p2).getDeclSpecifier()).isFriend()) - return false; - - return true; - } - return p2 instanceof IASTFunctionDefinition; + 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 false; + + if (node instanceof IASTDeclarator) + return (IASTDeclarator) node; + + return null; } public boolean forExplicitFunctionSpecialization() { - if (astName == null) return false; - if (astName.getPropertyInParent() == CPPSemantics.STRING_LOOKUP_PROPERTY) return false; - - 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 IASTSimpleDeclaration || p2 instanceof IASTFunctionDefinition) { - ICPPASTTemplateDeclaration tmplDecl = CPPTemplates.getTemplateDeclaration(n); - return tmplDecl instanceof ICPPASTTemplateSpecialization; - } + IASTDeclaration decl= forDeclaration(); + if (decl != null) { + IASTName n = astName; + if (n.getParent() instanceof ICPPASTTemplateId) + n = (IASTName) n.getParent(); + + ICPPASTTemplateDeclaration tmplDecl = CPPTemplates.getTemplateDeclaration(n); + return tmplDecl instanceof ICPPASTTemplateSpecialization; } return false; } public boolean forExplicitFunctionInstantiation() { - if (astName == null) return false; - if (astName.getPropertyInParent() == CPPSemantics.STRING_LOOKUP_PROPERTY) return false; - - 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; + IASTDeclaration decl= forDeclaration(); + return decl != null && decl.getParent() instanceof ICPPASTExplicitTemplateInstantiation; } public boolean qualified() { @@ -414,14 +387,6 @@ public class LookupData { } 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; } @@ -491,13 +456,7 @@ public class LookupData { return false; if (p instanceof IASTDeclaration) { if (prop == IASTCompositeTypeSpecifier.MEMBER_DECLARATION) { - if (p instanceof IASTSimpleDeclaration) { - ICPPASTDeclSpecifier declSpec = (ICPPASTDeclSpecifier) ((IASTSimpleDeclaration) p).getDeclSpecifier(); - return declSpec.isFriend(); - } else if (p instanceof IASTFunctionDefinition) { - ICPPASTDeclSpecifier declSpec = (ICPPASTDeclSpecifier) ((IASTFunctionDefinition) p).getDeclSpecifier(); - return declSpec.isFriend(); - } + return CPPVisitor.isFriendDeclaration(p); } else { return false; } @@ -547,14 +506,7 @@ public class LookupData { 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; } @@ -570,36 +522,19 @@ public class LookupData { 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; } - public void setFunctionParameters(ICPPASTParameterDeclaration[] parameters) { - functionParameters= parameters; - } - public int getFunctionArgumentCount() { if (functionArgs != null) return functionArgs.length; - if (functionParameters != null) - return functionParameters.length; return 0; } public boolean hasFunctionArguments() { - return functionArgs != null || functionParameters != null; + return functionArgs != null; } public IBinding[] getFoundBindings() { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java index be23516639f..03346097b98 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java @@ -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.ICPPFunction; 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.ICPPParameterPackType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType; @@ -67,181 +68,16 @@ public class TemplateArgumentDeduction { static ICPPTemplateArgument[] deduceForFunctionCall(ICPPFunctionTemplate template, ICPPTemplateArgument[] tmplArgs, List fnArgs, List argIsLValue, 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); - } + if (!addExplicitArguments(tmplParams, tmplArgs, map)) + return null; if (!deduceFromFunctionArgs(template, fnArgs, argIsLValue, map)) return null; - List result= new ArrayList(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()]); - } - - /** - * 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 result= new ArrayList(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; + return createArguments(map, tmplParams); } /** @@ -253,9 +89,6 @@ public class TemplateArgumentDeduction { try { IType[] fnPars = template.getType().getParameterTypes(); final int fnParCount = fnPars.length; - if (fnParCount == 0) - return true; - final ICPPTemplateParameter[] tmplPars = template.getTemplateParameters(); TemplateArgumentDeduction deduct= new TemplateArgumentDeduction(tmplPars, map, new CPPTemplateParameterMap(fnParCount), 0); IType fnParPack= null; @@ -288,7 +121,7 @@ public class TemplateArgumentDeduction { // C++0x: 14.9.2.1-1 if (arg instanceof InitializerListType) { par= SemanticUtil.getNestedType(par, TDEF | REF | CVTYPE); - + // Check if this is a deduced context IType inner= Conversions.getInitListType(par); if (inner != null) { @@ -338,7 +171,7 @@ public class TemplateArgumentDeduction { } } - if (!deduct.fExplicitArgs.mergeToExplicit(deduct.fDeducedArgs)) + if (!map.addDeducedArgs(deduct.fDeducedArgs)) return false; return verifyDeduction(tmplPars, map, true); @@ -346,7 +179,7 @@ public class TemplateArgumentDeduction { } return false; } - + private static boolean deduceFromFunctionArg(IType par, IType arg, ValueCategory valueCat, TemplateArgumentDeduction deduct) throws DOMException { boolean isReferenceTypeParameter= false; if (par instanceof ICPPReferenceType) { @@ -407,6 +240,112 @@ public class TemplateArgumentDeduction { 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, * returns false if there is no mapping. @@ -470,6 +409,64 @@ public class TemplateArgumentDeduction { 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 result= new ArrayList(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. */ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java index 39498fcadf4..b435461ca37 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java @@ -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.ICPPASTUsingDirective; 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.ICPPNamespaceAlias; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter; @@ -254,7 +255,8 @@ abstract public class PDOMWriter { try { final IBinding binding = name.resolveBinding(); if (name.getPropertyInParent() == ICPPASTTemplateId.TEMPLATE_NAME && - ((IASTName) name.getParent()).getBinding() == binding) { + (((IASTName) name.getParent()).getBinding() == binding || + binding instanceof ICPPFunctionTemplate)) { na[0]= null; } else if (binding instanceof IProblemBinding) { fStatistics.fProblemBindingCount++;