diff options
author | Nathan Ridge | 2012-12-13 00:29:09 +0000 |
---|---|---|
committer | Sergey Prigogin | 2013-01-07 23:44:01 +0000 |
commit | f0e663e7cffc90d6828be98ae5e397b59d14bd12 (patch) | |
tree | 21d18011901938f78f6268fdae742cc444f2fbdb | |
parent | 67ac1524014e012dc2bc6745fcac955d73c75a81 (diff) | |
download | org.eclipse.cdt-f0e663e7cffc90d6828be98ae5e397b59d14bd12.tar.gz org.eclipse.cdt-f0e663e7cffc90d6828be98ae5e397b59d14bd12.tar.xz org.eclipse.cdt-f0e663e7cffc90d6828be98ae5e397b59d14bd12.zip |
Bug 395243 - Error involving dependent expressions
Change-Id: Iabd115b40d0b7b633c416171a19a981f1e51dee8
Reviewed-on: https://git.eclipse.org/r/9211
Reviewed-by: Sergey Prigogin <eclipse.sprigogin@gmail.com>
IP-Clean: Sergey Prigogin <eclipse.sprigogin@gmail.com>
Tested-by: Sergey Prigogin <eclipse.sprigogin@gmail.com>
10 files changed, 150 insertions, 49 deletions
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 1b3079dfc0f..19350ee7d27 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 @@ -6938,7 +6938,70 @@ public class AST2TemplateTests extends AST2BaseTest { // static const int value = sizeof(waldo(f)); // }; // typedef identity<Int<S<>::value>>::type reference; - public void _testDependentExpressions_395243() throws Exception { + public void testDependentExpressions_395243a() throws Exception { + parseAndCheckBindings(); + } + + // typedef char one; + // typedef struct { + // char arr[2]; + // } two; + // template <typename T> + // struct has_foo_type { + // template <typename _Up> + // struct wrap_type { }; + // template <typename U> + // static one test(wrap_type<typename U::foo_type>*); + // template <typename U> + // static two test(...); + // static const bool value = sizeof(test<T>(0)) == 1; + // }; + // template <bool> + // struct traits; + // template <> + // struct traits<true> { + // typedef int bar_type; + // }; + // struct S { + // typedef int foo_type; + // }; + // traits<has_foo_type<S>::value>::bar_type a; + public void testDependentExpressions_395243b() throws Exception { + parseAndCheckBindings(); + } + + // template <typename U> U bar(U); + // template <typename T> auto waldo(T t) -> decltype(bar(t)); + // struct S { + // void foo() const; + // }; + // struct V { + // S arr[5]; + // }; + // int main() { + // V e; + // auto v = waldo(e); + // for (auto s : v.arr) + // s.foo(); + // } + public void testDependentExpressions_395243c() throws Exception { + parseAndCheckBindings(); + } + + // template <typename> class C {}; + // template <typename T> int begin(C<T>); + // template <typename> + // struct A { + // class B { + // void m(); + // }; + // void test() { + // B* v[5]; + // for (auto x : v) + // x->m(); + // } + // }; + public void testDependentExpressions_395243d() 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..88f0d3b79d8 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,32 @@ 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()); + /** + * 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 = sample.getOwner(); - return new CPPDeferredFunction(owner, sample.getNameCharArray()); + 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..8b8ec43a81c 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 @@ -92,7 +92,7 @@ public class CPPFunctionSet implements ICPPTwoPhaseBinding { 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 247603215af..a447998e76e 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<FunctionCost> 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 4d3afd83849..61f55dfe0fe 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 } /** @@ -1750,18 +1750,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 && hasDependentArgument(tmplArgs)) + return new ICPPFunction[] {CPPDeferredFunction.createForCandidates(fns)}; - if (requireTemplate) { - if (hasDependentArgument(tmplArgs)) - return new ICPPFunction[] {CPPDeferredFunction.createForSample(template)}; - } - } catch (DOMException e) { - return NO_FUNCTIONS; - } haveTemplate= true; break; } @@ -1827,15 +1821,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 { @@ -1893,7 +1883,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/CPPVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java index 4e47369eeae..8afc1bf3d89 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 @@ -11,6 +11,7 @@ * Andrew Ferguson (Symbian) * Sergey Prigogin (Google) * Thomas Corbat (IFS) + * Nathan Ridge *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; @@ -2017,11 +2018,13 @@ public class CPPVisitor extends ASTQueries { IBinding b= implicits[0].getBinding(); CPPASTName name= new CPPASTName(); name.setBinding(b); + IASTInitializerClause[] beginCallArguments = new IASTInitializerClause[] { forInit.copy() }; if (b instanceof ICPPMethod && forInit instanceof IASTExpression) { beginExpr= new CPPASTFunctionCallExpression( - new CPPASTFieldReference(name, (IASTExpression) forInit.copy()), NO_ARGS); + new CPPASTFieldReference(name, (IASTExpression) forInit.copy()), + beginCallArguments); } else { - beginExpr= new CPPASTFunctionCallExpression(new CPPASTIdExpression(name), NO_ARGS); + beginExpr= new CPPASTFunctionCallExpression(new CPPASTIdExpression(name), beginCallArguments); } } else { return new ProblemType(ISemanticProblem.TYPE_CANNOT_DEDUCE_AUTO_TYPE); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinding.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinding.java index ea60a5169fc..a4419e5c668 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinding.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinding.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; @@ -362,6 +363,13 @@ public class EvalBinding extends CPPEvaluation { binding = CPPTemplates.createSpecialization((ICPPClassSpecialization) owner, binding, point); } + } else if (binding instanceof ICPPParameter) { + ICPPParameter parameter = (ICPPParameter) binding; + IType originalType = parameter.getType(); + IType type = CPPTemplates.instantiateType(originalType, tpMap, packOffset, within, point); + if (originalType != type) { + return new EvalFixed(type, ValueCategory.LVALUE, Value.create(this)); + } } if (binding == fBinding) return this; 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 f202f82778f..60771fd3cfe 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 @@ -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; @@ -23,6 +24,7 @@ import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; @@ -145,12 +147,16 @@ 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; - if (originalOwner instanceof ICPPUnknownBinding) { + if (owner instanceof ICPPUnknownBinding) { owner = resolveUnknown((ICPPUnknownBinding) owner, tpMap, packOffset, within, point); + } else if (owner instanceof ICPPClassTemplate) { + owner = resolveUnknown(CPPTemplates.createDeferredInstance((ICPPClassTemplate) owner), + tpMap, packOffset, within, point); } else if (owner instanceof IType) { IType type = CPPTemplates.instantiateType((IType) owner, tpMap, packOffset, within, point); if (type instanceof IBinding) 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 2f78b975479..74760703536 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,6 +195,25 @@ 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); } |