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 868304db03e..915a4c94767 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 @@ -12,6 +12,7 @@ * Andrew Ferguson (Symbian) * Sergey Prigogin (Google) * Thomas Corbat (IFS) + * Nathan Ridge *******************************************************************************/ package org.eclipse.cdt.core.parser.tests.ast2; @@ -6912,15 +6913,32 @@ public class AST2TemplateTests extends AST2BaseTest { parseAndCheckBindings(); } - // template - // struct M { - // template - // M(Args...); - // }; - // void foo() { - // new M((int*)0, 0); - // } + // template + // struct M { + // template + // M(Args...); + // }; + // void foo() { + // new M((int*)0, 0); + // } public void testVariadicConstructor_395247() throws Exception { parseAndCheckBindings(); } + + // template struct Int {}; + // template + // struct identity { + // typedef T type; + // }; + // template + // char waldo(T); + // template + // struct S { + // F f; + // static const int value = sizeof(waldo(f)); + // }; + // typedef identity::value>>::type reference; + public void testDependentExpressions_395243() throws Exception { + parseAndCheckBindings(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeferredFunction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeferredFunction.java index daf282b6106..108f60c3d83 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeferredFunction.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeferredFunction.java @@ -8,12 +8,11 @@ * Contributors: * Markus Schorn - initial API and implementation * Sergey Prigogin (Google) + * Nathan Ridge *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; -import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IBinding; -import org.eclipse.cdt.core.dom.ast.IFunction; import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; @@ -30,19 +29,33 @@ public class CPPDeferredFunction extends CPPUnknownBinding implements ICPPFuncti private static final ICPPFunctionType FUNCTION_TYPE= new CPPFunctionType(ProblemType.UNKNOWN_FOR_EXPRESSION, IType.EMPTY_TYPE_ARRAY); - public static ICPPFunction createForSample(IFunction sample) throws DOMException { - if (sample instanceof ICPPConstructor) - return new CPPUnknownConstructor(((ICPPConstructor) sample).getClassOwner()); - - final IBinding owner = sample.getOwner(); - return new CPPDeferredFunction(owner, sample.getNameCharArray()); + /** + * Creates a CPPDeferredFunction given a set of overloaded functions + * (some of which may be templates) that the function might resolve to. + * At least one candidate must be provided. + * + * @param candidates a set of overloaded functions, some of which may be templates + * @return the constructed CPPDeferredFunction + */ + public static ICPPFunction createForCandidates(ICPPFunction... candidates) { + if (candidates[0] instanceof ICPPConstructor) + return new CPPUnknownConstructor(((ICPPConstructor) candidates[0]).getClassOwner(), candidates); + + final IBinding owner = candidates[0].getOwner(); + return new CPPDeferredFunction(owner, candidates[0].getNameCharArray(), candidates); } private final IBinding fOwner; + private final ICPPFunction[] fCandidates; - public CPPDeferredFunction(IBinding owner, char[] name) { + public CPPDeferredFunction(IBinding owner, char[] name, ICPPFunction[] candidates) { super(name); fOwner= owner; + fCandidates = candidates; + } + + public ICPPFunction[] getCandidates() { + return fCandidates; } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownConstructor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownConstructor.java index 0dd63fc488a..94b59961cfa 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownConstructor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownConstructor.java @@ -8,11 +8,13 @@ * Contributors: * Markus Schorn - initial API and implementation * Thomas Corbat (IFS) + * Nathan Ridge *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; /** * Represents a reference to a constructor (instance), which cannot be resolved because @@ -21,7 +23,11 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; public class CPPUnknownConstructor extends CPPDeferredFunction implements ICPPConstructor { public CPPUnknownConstructor(ICPPClassType owner) { - super(owner, owner.getNameCharArray()); + super(owner, owner.getNameCharArray(), null); + } + + public CPPUnknownConstructor(ICPPClassType owner, ICPPFunction[] candidates) { + super(owner, owner.getNameCharArray(), candidates); } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPFunctionSet.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPFunctionSet.java index 8d1842259e7..0eef3cfa56e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPFunctionSet.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPFunctionSet.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 Wind River Systems, Inc. and others. + * Copyright (c) 2010, 2012 Wind River Systems, Inc. and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,6 +7,7 @@ * * Contributors: * Markus Schorn - initial API and implementation + * Nathan Ridge *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; @@ -31,7 +32,7 @@ public class CPPFunctionSet implements ICPPTwoPhaseBinding { private final ICPPFunction[] fBindings; private final IASTName fName; private final ICPPTemplateArgument[] fTemplateArguments; - + public CPPFunctionSet(ICPPFunction[] bindingList, ICPPTemplateArgument[] args, IASTName name) { fBindings = ArrayUtil.removeNulls(bindingList); fTemplateArguments= args; @@ -89,10 +90,10 @@ public class CPPFunctionSet implements ICPPTwoPhaseBinding { fName.setBinding(selectedFunction); } } - + public void setToUnknown() { if (fName != null) { - fName.setBinding(new CPPDeferredFunction(null, fName.toCharArray())); + fName.setBinding(new CPPDeferredFunction(null, fName.toCharArray(), fBindings)); } } } 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 eeb245d2399..58e8713a21f 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 @@ -13,6 +13,7 @@ * Sergey Prigogin (Google) * Mike Kucera (IBM) * Thomas Corbat (IFS) + * Nathan Ridge *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; @@ -451,7 +452,7 @@ public class CPPSemantics { final ASTNodeProperty namePropertyInParent = name.getPropertyInParent(); if (binding == null && data.skippedScope != null) { if (data.hasFunctionArguments()) { - binding= new CPPDeferredFunction(data.skippedScope, name.getSimpleID()); + binding= new CPPDeferredFunction(data.skippedScope, name.getSimpleID(), null); } else { if (namePropertyInParent == IASTNamedTypeSpecifier.NAME) { binding= new CPPUnknownMemberClass(data.skippedScope, name.getSimpleID()); @@ -2395,7 +2396,7 @@ public class CPPSemantics { if (viableCount == 1) return fns[0]; setTargetedFunctionsToUnknown(argTypes); - return CPPDeferredFunction.createForSample(fns[0]); + return CPPDeferredFunction.createForCandidates(fns); } IFunction[] ambiguousFunctions= null; // ambiguity, 2 functions are equally good @@ -2403,7 +2404,7 @@ public class CPPSemantics { // Loop over all functions List potentialCosts= null; - IFunction unknownFunction= null; + ICPPFunction unknownFunction= null; final CPPASTTranslationUnit tu = data.getTranslationUnit(); for (ICPPFunction fn : fns) { if (fn == null) @@ -2455,7 +2456,7 @@ public class CPPSemantics { return null; setTargetedFunctionsToUnknown(argTypes); - return CPPDeferredFunction.createForSample(unknownFunction); + return CPPDeferredFunction.createForCandidates(fns); } if (ambiguousFunctions != null) { 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 877e605ba48..39e5db03281 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 @@ -11,6 +11,7 @@ * Markus Schorn (Wind River Systems) * Sergey Prigogin (Google) * Thomas Corbat (IFS) + * Nathan Ridge *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; @@ -163,7 +164,6 @@ public class CPPTemplates { static final int PACK_SIZE_DEFER = -1; static final int PACK_SIZE_FAIL = -2; static final int PACK_SIZE_NOT_FOUND = Integer.MAX_VALUE; - private static final ICPPFunction[] NO_FUNCTIONS = {}; static enum TypeSelection { PARAMETERS, RETURN_TYPE, PARAMETERS_AND_RETURN_TYPE } /** @@ -1726,18 +1726,12 @@ public class CPPTemplates { requireTemplate= false; if (func instanceof ICPPFunctionTemplate) { - ICPPFunctionTemplate template= (ICPPFunctionTemplate) func; - try { - if (containsDependentType(fnArgs)) - return new ICPPFunction[] {CPPDeferredFunction.createForSample(template)}; + if (containsDependentType(fnArgs)) + return new ICPPFunction[] {CPPDeferredFunction.createForCandidates(fns)}; - if (requireTemplate) { - if (hasDependentArgument(tmplArgs)) - return new ICPPFunction[] {CPPDeferredFunction.createForSample(template)}; - } - } catch (DOMException e) { - return NO_FUNCTIONS; - } + if (requireTemplate && hasDependentArgument(tmplArgs)) + return new ICPPFunction[] {CPPDeferredFunction.createForCandidates(fns)}; + haveTemplate= true; break; } @@ -1803,15 +1797,11 @@ public class CPPTemplates { // Extract template arguments and parameter types. if (!checkedForDependentType) { - try { - if (isDependentType(conversionType)) { - inst= CPPDeferredFunction.createForSample(template); - done= true; - } - checkedForDependentType= true; - } catch (DOMException e) { - return functions; + if (isDependentType(conversionType)) { + inst= CPPDeferredFunction.createForCandidates(functions); + done= true; } + checkedForDependentType= true; } CPPTemplateParameterMap map= new CPPTemplateParameterMap(1); try { @@ -1869,7 +1859,7 @@ public class CPPTemplates { ICPPTemplateArgument[] args, IASTNode point) { try { if (target != null && isDependentType(target)) { - return CPPDeferredFunction.createForSample(template); + return CPPDeferredFunction.createForCandidates(template); } if (template instanceof ICPPConstructor || args == null) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionSet.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionSet.java index 4e16f5a0751..a31627bcb5d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionSet.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionSet.java @@ -145,7 +145,8 @@ public class EvalFunctionSet extends CPPEvaluation { ICPPClassSpecialization within, int maxdepth, IASTNode point) { ICPPTemplateArgument[] originalArguments = fFunctionSet.getTemplateArguments(); ICPPTemplateArgument[] arguments = originalArguments; - arguments = instantiateArguments(originalArguments, tpMap, packOffset, within, point); + if (originalArguments != null) + arguments = instantiateArguments(originalArguments, tpMap, packOffset, within, point); IBinding originalOwner = fFunctionSet.getOwner(); IBinding owner = originalOwner; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalID.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalID.java index 501189404f1..9a055e968d2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalID.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalID.java @@ -8,6 +8,7 @@ * Contributors: * Markus Schorn - initial API and implementation * Sergey Prigogin (Google) + * Nathan Ridge *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; @@ -48,6 +49,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPDeferredFunction; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding; import org.eclipse.core.runtime.CoreException; @@ -184,15 +186,6 @@ public class EvalID extends CPPEvaluation { return new EvalFunctionSet((CPPFunctionSet) binding, isAddressOf(expr)); } if (binding instanceof ICPPUnknownBinding) { - IBinding owner = binding.getOwner(); - if (owner instanceof IProblemBinding) - return EvalFixed.INCOMPLETE; - - ICPPEvaluation fieldOwner= null; - IType fieldOwnerType= withinNonStaticMethod(expr); - if (fieldOwnerType != null) { - fieldOwner= new EvalFixed(fieldOwnerType, ValueCategory.LVALUE, Value.UNKNOWN); - } ICPPTemplateArgument[] templateArgs = null; final IASTName lastName = name.getLastName(); if (lastName instanceof ICPPASTTemplateId) { @@ -202,12 +195,30 @@ public class EvalID extends CPPEvaluation { return EvalFixed.INCOMPLETE; } } + + if (binding instanceof CPPDeferredFunction) { + CPPDeferredFunction deferredFunction = (CPPDeferredFunction) binding; + if (deferredFunction.getCandidates() != null) { + CPPFunctionSet functionSet = new CPPFunctionSet(deferredFunction.getCandidates(), templateArgs, null); + return new EvalFunctionSet(functionSet, isAddressOf(expr)); + } + } + + IBinding owner = binding.getOwner(); + if (owner instanceof IProblemBinding) + return EvalFixed.INCOMPLETE; + + ICPPEvaluation fieldOwner= null; + IType fieldOwnerType= withinNonStaticMethod(expr); + if (fieldOwnerType != null) { + fieldOwner= new EvalFixed(fieldOwnerType, ValueCategory.LVALUE, Value.UNKNOWN); + } + return new EvalID(fieldOwner, owner, name.getSimpleID(), isAddressOf(expr), name instanceof ICPPASTQualifiedName, templateArgs); } - /** - * 9.3.1-3 Transformation to class member access within a non-static member function. - */ + + // 9.3.1-3 Transformation to class member access within a non-static member function. if (binding instanceof ICPPMember && !(binding instanceof IType) && !(binding instanceof ICPPConstructor) &&!((ICPPMember) binding).isStatic()) { IType fieldOwnerType= withinNonStaticMethod(expr); @@ -305,7 +316,7 @@ public class EvalID extends CPPEvaluation { if (eval != null) return eval; } - + return new EvalID(fieldOwner, nameOwner, fName, fAddressOf, fQualified, templateArgs); }