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:
parent
49342dc9bf
commit
64c383952a
12 changed files with 475 additions and 439 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5454,4 +5454,16 @@ public class AST2TemplateTests extends AST2BaseTest {
|
|||
public void testTemplateTemplateParameterMatching_352859() throws Exception {
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<ICPPTemplateInstance> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
final IASTDeclaration declaration = data.forDeclaration();
|
||||
if (declaration != null) {
|
||||
// Functions
|
||||
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);
|
||||
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.
|
||||
// Definitions of static fields.
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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,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 {
|
||||
if (data.forExplicitFunctionSpecialization()) {
|
||||
fns = CPPTemplates.instantiateForFunctionCall(data.astName,
|
||||
fns,
|
||||
Arrays.asList(data.getFunctionArgumentTypes()), Arrays.asList(data.getFunctionArgumentValueCategories()),
|
||||
data.argsContainImpliedObject);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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)) {
|
||||
// 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)) {
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
int iast= 0;
|
||||
|
@ -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);
|
||||
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) {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
||||
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();
|
||||
while (node instanceof IASTDeclarator)
|
||||
node= node.getParent();
|
||||
|
||||
if (node instanceof IASTSimpleDeclaration || node instanceof IASTFunctionDefinition)
|
||||
return (IASTDeclaration) node;
|
||||
|
||||
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;
|
||||
public IASTDeclarator getDeclarator() {
|
||||
IASTName name= astName;
|
||||
if (name == null || name.getPropertyInParent() == CPPSemantics.STRING_LOOKUP_PROPERTY)
|
||||
return null;
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
|
||||
IASTDeclaration decl= forDeclaration();
|
||||
if (decl != null) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
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,13 +506,6 @@ 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() {
|
||||
|
|
|
@ -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<IType> fnArgs, List<ValueCategory> 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)
|
||||
if (!addExplicitArguments(tmplParams, tmplArgs, map))
|
||||
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))
|
||||
return null;
|
||||
|
||||
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()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
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;
|
||||
|
@ -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);
|
||||
|
@ -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 <code>false</code> 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<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.
|
||||
*/
|
||||
|
|
|
@ -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++;
|
||||
|
|
Loading…
Add table
Reference in a new issue