1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-28 11:25:35 +02:00

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>
This commit is contained in:
Nathan Ridge 2012-12-12 19:29:09 -05:00 committed by Sergey Prigogin
parent 67ac152401
commit f0e663e7cf
10 changed files with 150 additions and 49 deletions

View file

@ -6938,7 +6938,70 @@ public class AST2TemplateTests extends AST2BaseTest {
// static const int value = sizeof(waldo(f)); // static const int value = sizeof(waldo(f));
// }; // };
// typedef identity<Int<S<>::value>>::type reference; // 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(); parseAndCheckBindings();
} }
} }

View file

@ -8,12 +8,11 @@
* Contributors: * Contributors:
* Markus Schorn - initial API and implementation * Markus Schorn - initial API and implementation
* Sergey Prigogin (Google) * Sergey Prigogin (Google)
* Nathan Ridge
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp; 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.IBinding;
import org.eclipse.cdt.core.dom.ast.IFunction;
import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; 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= private static final ICPPFunctionType FUNCTION_TYPE=
new CPPFunctionType(ProblemType.UNKNOWN_FOR_EXPRESSION, IType.EMPTY_TYPE_ARRAY); new CPPFunctionType(ProblemType.UNKNOWN_FOR_EXPRESSION, IType.EMPTY_TYPE_ARRAY);
public static ICPPFunction createForSample(IFunction sample) throws DOMException { /**
if (sample instanceof ICPPConstructor) * Creates a CPPDeferredFunction given a set of overloaded functions
return new CPPUnknownConstructor(((ICPPConstructor) sample).getClassOwner()); * (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(); final IBinding owner = candidates[0].getOwner();
return new CPPDeferredFunction(owner, sample.getNameCharArray()); return new CPPDeferredFunction(owner, candidates[0].getNameCharArray(), candidates);
} }
private final IBinding fOwner; private final IBinding fOwner;
private final ICPPFunction[] fCandidates;
public CPPDeferredFunction(IBinding owner, char[] name) { public CPPDeferredFunction(IBinding owner, char[] name, ICPPFunction[] candidates) {
super(name); super(name);
fOwner= owner; fOwner= owner;
fCandidates = candidates;
}
public ICPPFunction[] getCandidates() {
return fCandidates;
} }
@Override @Override

View file

@ -8,11 +8,13 @@
* Contributors: * Contributors:
* Markus Schorn - initial API and implementation * Markus Schorn - initial API and implementation
* Thomas Corbat (IFS) * Thomas Corbat (IFS)
* Nathan Ridge
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp; 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.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; 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 * 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 class CPPUnknownConstructor extends CPPDeferredFunction implements ICPPConstructor {
public CPPUnknownConstructor(ICPPClassType owner) { 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 @Override

View file

@ -92,7 +92,7 @@ public class CPPFunctionSet implements ICPPTwoPhaseBinding {
public void setToUnknown() { public void setToUnknown() {
if (fName != null) { if (fName != null) {
fName.setBinding(new CPPDeferredFunction(null, fName.toCharArray())); fName.setBinding(new CPPDeferredFunction(null, fName.toCharArray(), fBindings));
} }
} }
} }

View file

@ -13,6 +13,7 @@
* Sergey Prigogin (Google) * Sergey Prigogin (Google)
* Mike Kucera (IBM) * Mike Kucera (IBM)
* Thomas Corbat (IFS) * Thomas Corbat (IFS)
* Nathan Ridge
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
@ -451,7 +452,7 @@ public class CPPSemantics {
final ASTNodeProperty namePropertyInParent = name.getPropertyInParent(); final ASTNodeProperty namePropertyInParent = name.getPropertyInParent();
if (binding == null && data.skippedScope != null) { if (binding == null && data.skippedScope != null) {
if (data.hasFunctionArguments()) { if (data.hasFunctionArguments()) {
binding= new CPPDeferredFunction(data.skippedScope, name.getSimpleID()); binding= new CPPDeferredFunction(data.skippedScope, name.getSimpleID(), null);
} else { } else {
if (namePropertyInParent == IASTNamedTypeSpecifier.NAME) { if (namePropertyInParent == IASTNamedTypeSpecifier.NAME) {
binding= new CPPUnknownMemberClass(data.skippedScope, name.getSimpleID()); binding= new CPPUnknownMemberClass(data.skippedScope, name.getSimpleID());
@ -2395,7 +2396,7 @@ public class CPPSemantics {
if (viableCount == 1) if (viableCount == 1)
return fns[0]; return fns[0];
setTargetedFunctionsToUnknown(argTypes); setTargetedFunctionsToUnknown(argTypes);
return CPPDeferredFunction.createForSample(fns[0]); return CPPDeferredFunction.createForCandidates(fns);
} }
IFunction[] ambiguousFunctions= null; // ambiguity, 2 functions are equally good IFunction[] ambiguousFunctions= null; // ambiguity, 2 functions are equally good
@ -2403,7 +2404,7 @@ public class CPPSemantics {
// Loop over all functions // Loop over all functions
List<FunctionCost> potentialCosts= null; List<FunctionCost> potentialCosts= null;
IFunction unknownFunction= null; ICPPFunction unknownFunction= null;
final CPPASTTranslationUnit tu = data.getTranslationUnit(); final CPPASTTranslationUnit tu = data.getTranslationUnit();
for (ICPPFunction fn : fns) { for (ICPPFunction fn : fns) {
if (fn == null) if (fn == null)
@ -2455,7 +2456,7 @@ public class CPPSemantics {
return null; return null;
setTargetedFunctionsToUnknown(argTypes); setTargetedFunctionsToUnknown(argTypes);
return CPPDeferredFunction.createForSample(unknownFunction); return CPPDeferredFunction.createForCandidates(fns);
} }
if (ambiguousFunctions != null) { if (ambiguousFunctions != null) {

View file

@ -11,6 +11,7 @@
* Markus Schorn (Wind River Systems) * Markus Schorn (Wind River Systems)
* Sergey Prigogin (Google) * Sergey Prigogin (Google)
* Thomas Corbat (IFS) * Thomas Corbat (IFS)
* Nathan Ridge
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; 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_DEFER = -1;
static final int PACK_SIZE_FAIL = -2; static final int PACK_SIZE_FAIL = -2;
static final int PACK_SIZE_NOT_FOUND = Integer.MAX_VALUE; 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 } static enum TypeSelection { PARAMETERS, RETURN_TYPE, PARAMETERS_AND_RETURN_TYPE }
/** /**
@ -1750,18 +1750,12 @@ public class CPPTemplates {
requireTemplate= false; requireTemplate= false;
if (func instanceof ICPPFunctionTemplate) { if (func instanceof ICPPFunctionTemplate) {
ICPPFunctionTemplate template= (ICPPFunctionTemplate) func; if (containsDependentType(fnArgs))
try { return new ICPPFunction[] {CPPDeferredFunction.createForCandidates(fns)};
if (containsDependentType(fnArgs))
return new ICPPFunction[] {CPPDeferredFunction.createForSample(template)}; 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; haveTemplate= true;
break; break;
} }
@ -1827,15 +1821,11 @@ public class CPPTemplates {
// Extract template arguments and parameter types. // Extract template arguments and parameter types.
if (!checkedForDependentType) { if (!checkedForDependentType) {
try { if (isDependentType(conversionType)) {
if (isDependentType(conversionType)) { inst= CPPDeferredFunction.createForCandidates(functions);
inst= CPPDeferredFunction.createForSample(template); done= true;
done= true;
}
checkedForDependentType= true;
} catch (DOMException e) {
return functions;
} }
checkedForDependentType= true;
} }
CPPTemplateParameterMap map= new CPPTemplateParameterMap(1); CPPTemplateParameterMap map= new CPPTemplateParameterMap(1);
try { try {
@ -1893,7 +1883,7 @@ public class CPPTemplates {
ICPPTemplateArgument[] args, IASTNode point) { ICPPTemplateArgument[] args, IASTNode point) {
try { try {
if (target != null && isDependentType(target)) { if (target != null && isDependentType(target)) {
return CPPDeferredFunction.createForSample(template); return CPPDeferredFunction.createForCandidates(template);
} }
if (template instanceof ICPPConstructor || args == null) if (template instanceof ICPPConstructor || args == null)

View file

@ -11,6 +11,7 @@
* Andrew Ferguson (Symbian) * Andrew Ferguson (Symbian)
* Sergey Prigogin (Google) * Sergey Prigogin (Google)
* Thomas Corbat (IFS) * Thomas Corbat (IFS)
* Nathan Ridge
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
@ -2017,11 +2018,13 @@ public class CPPVisitor extends ASTQueries {
IBinding b= implicits[0].getBinding(); IBinding b= implicits[0].getBinding();
CPPASTName name= new CPPASTName(); CPPASTName name= new CPPASTName();
name.setBinding(b); name.setBinding(b);
IASTInitializerClause[] beginCallArguments = new IASTInitializerClause[] { forInit.copy() };
if (b instanceof ICPPMethod && forInit instanceof IASTExpression) { if (b instanceof ICPPMethod && forInit instanceof IASTExpression) {
beginExpr= new CPPASTFunctionCallExpression( beginExpr= new CPPASTFunctionCallExpression(
new CPPASTFieldReference(name, (IASTExpression) forInit.copy()), NO_ARGS); new CPPASTFieldReference(name, (IASTExpression) forInit.copy()),
beginCallArguments);
} else { } else {
beginExpr= new CPPASTFunctionCallExpression(new CPPASTIdExpression(name), NO_ARGS); beginExpr= new CPPASTFunctionCallExpression(new CPPASTIdExpression(name), beginCallArguments);
} }
} else { } else {
return new ProblemType(ISemanticProblem.TYPE_CANNOT_DEDUCE_AUTO_TYPE); return new ProblemType(ISemanticProblem.TYPE_CANNOT_DEDUCE_AUTO_TYPE);

View file

@ -8,6 +8,7 @@
* Contributors: * Contributors:
* Markus Schorn - initial API and implementation * Markus Schorn - initial API and implementation
* Sergey Prigogin (Google) * Sergey Prigogin (Google)
* Nathan Ridge
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; 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 = CPPTemplates.createSpecialization((ICPPClassSpecialization) owner,
binding, point); 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) if (binding == fBinding)
return this; return this;

View file

@ -8,6 +8,7 @@
* Contributors: * Contributors:
* Markus Schorn - initial API and implementation * Markus Schorn - initial API and implementation
* Sergey Prigogin (Google) * Sergey Prigogin (Google)
* Nathan Ridge
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; 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.IType;
import org.eclipse.cdt.core.dom.ast.IValue; 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.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.ICPPFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
@ -145,12 +147,16 @@ public class EvalFunctionSet extends CPPEvaluation {
ICPPClassSpecialization within, int maxdepth, IASTNode point) { ICPPClassSpecialization within, int maxdepth, IASTNode point) {
ICPPTemplateArgument[] originalArguments = fFunctionSet.getTemplateArguments(); ICPPTemplateArgument[] originalArguments = fFunctionSet.getTemplateArguments();
ICPPTemplateArgument[] arguments = originalArguments; 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 originalOwner = fFunctionSet.getOwner();
IBinding owner = originalOwner; IBinding owner = originalOwner;
if (originalOwner instanceof ICPPUnknownBinding) { if (owner instanceof ICPPUnknownBinding) {
owner = resolveUnknown((ICPPUnknownBinding) owner, tpMap, packOffset, within, point); 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) { } else if (owner instanceof IType) {
IType type = CPPTemplates.instantiateType((IType) owner, tpMap, packOffset, within, point); IType type = CPPTemplates.instantiateType((IType) owner, tpMap, packOffset, within, point);
if (type instanceof IBinding) if (type instanceof IBinding)

View file

@ -8,6 +8,7 @@
* Contributors: * Contributors:
* Markus Schorn - initial API and implementation * Markus Schorn - initial API and implementation
* Sergey Prigogin (Google) * Sergey Prigogin (Google)
* Nathan Ridge
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; 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.ISerializableEvaluation;
import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; 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.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.ICPPEvaluation;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.CoreException;
@ -184,15 +186,6 @@ public class EvalID extends CPPEvaluation {
return new EvalFunctionSet((CPPFunctionSet) binding, isAddressOf(expr)); return new EvalFunctionSet((CPPFunctionSet) binding, isAddressOf(expr));
} }
if (binding instanceof ICPPUnknownBinding) { 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; ICPPTemplateArgument[] templateArgs = null;
final IASTName lastName = name.getLastName(); final IASTName lastName = name.getLastName();
if (lastName instanceof ICPPASTTemplateId) { if (lastName instanceof ICPPASTTemplateId) {
@ -202,6 +195,25 @@ public class EvalID extends CPPEvaluation {
return EvalFixed.INCOMPLETE; 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), return new EvalID(fieldOwner, owner, name.getSimpleID(), isAddressOf(expr),
name instanceof ICPPASTQualifiedName, templateArgs); name instanceof ICPPASTQualifiedName, templateArgs);
} }