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 ae43ce1fd74..1b9dbcd3b9b 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 @@ -8594,4 +8594,28 @@ public class AST2TemplateTests extends AST2TestBase { public void testLocalTypeAsTemplateArgument_442832() throws Exception { parseAndCheckBindings(); } + + // template + // struct Bar {}; + // + // template + // auto foo(T t) -> Bar { + // Bar bar; // bogus `invalid template arguments` error here + // return bar; + // } + // + // struct S { + // int foo; + // }; + // + // int main() { + // Bar var1; + // auto var2 = foo(S()); + // } + public void testTypeOfUnknownMember_447728() throws Exception { + BindingAssertionHelper helper = getAssertionHelper(); + IVariable var1 = helper.assertNonProblem("var1"); + IVariable var2 = helper.assertNonProblem("var2"); + assertSameType(var1.getType(), var2.getType()); + } } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java index b00711fe5ec..2b743335d6d 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java @@ -31,6 +31,7 @@ import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.ITypedef; import org.eclipse.cdt.core.dom.ast.IValue; +import org.eclipse.cdt.core.dom.ast.IVariable; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; @@ -2606,4 +2607,28 @@ public class IndexCPPTemplateResolutionTest extends IndexBindingResolutionTestBa public void testInfiniteRecursionMarshallingTemplateDefinition_439923() throws Exception { checkBindings(); } + + + // template + // struct Bar {}; + // + // template + // auto foo(T t) -> Bar { + // Bar bar; // bogus `invalid template arguments` error here + // return bar; + // } + // + // struct S { + // int foo; + // }; + + // int main() { + // Bar var1; + // auto var2 = foo(S()); + // } + public void testTypeOfUnknownMember_447728() throws Exception { + IVariable var1 = getBindingFromASTName("var1", 4); + IVariable var2 = getBindingFromASTName("var2", 4); + assertSameType(var1.getType(), var2.getType()); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ITypeMarshalBuffer.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ITypeMarshalBuffer.java index d6f37f32af1..62b74fd409d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ITypeMarshalBuffer.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ITypeMarshalBuffer.java @@ -39,6 +39,7 @@ public interface ITypeMarshalBuffer { final static byte DEFERRED_CLASS_INSTANCE = 0x0E; final static byte ALIAS_TEMPLATE = 0x0F; final static byte TYPE_TRANSFORMATION = 0x10; + final static byte UNKNOWN_MEMBER_TYPE = 0x11; // Can add more types up to 0x1C, after that it will collide with TypeMarshalBuffer.UNSTORABLE_TYPE. final static byte diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownField.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownField.java index 7d6fde70206..4bdae24ed21 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownField.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownField.java @@ -15,7 +15,7 @@ import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; -import org.eclipse.cdt.internal.core.dom.parser.ProblemType; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.TypeOfUnknownMember; /** * Represents a reference to a field, which cannot be resolved because the owner is @@ -78,7 +78,7 @@ public class CPPUnknownField extends CPPUnknownMember implements ICPPField { @Override public IType getType() { - return ProblemType.UNKNOWN_FOR_EXPRESSION; + return new TypeOfUnknownMember(this); } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownMethod.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownMethod.java index 0219cb9c5b0..aad4047ed4d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownMethod.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownMethod.java @@ -67,6 +67,10 @@ public class CPPUnknownMethod extends CPPUnknownMember implements ICPPMethod { @Override public ICPPFunctionType getType() { + // TODO(nathanridge): We'd like to return a TypeOfUnknownMember here, + // but that doesn't implement ICPPFuncionType. We'll probably have + // to write an implementation of ICPPFunctionType that stores the + // CPPUnknownMethod and resolves it upon instantiation. return FUNCTION_TYPE; } 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 8ba60494cb3..25d840b2119 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 @@ -44,6 +44,7 @@ import org.eclipse.cdt.core.dom.ast.IASTTypeId; import org.eclipse.cdt.core.dom.ast.IArrayType; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IEnumerator; +import org.eclipse.cdt.core.dom.ast.IFunction; import org.eclipse.cdt.core.dom.ast.IFunctionType; import org.eclipse.cdt.core.dom.ast.IPointerType; import org.eclipse.cdt.core.dom.ast.IProblemBinding; @@ -52,6 +53,7 @@ import org.eclipse.cdt.core.dom.ast.ISemanticProblem; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.ITypedef; import org.eclipse.cdt.core.dom.ast.IValue; +import org.eclipse.cdt.core.dom.ast.IVariable; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTAliasDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTAmbiguousTemplateArgument; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; @@ -1343,6 +1345,18 @@ public class CPPTemplates { return type; } } + + if (type instanceof TypeOfUnknownMember) { + IBinding binding = resolveUnknown(((TypeOfUnknownMember) type).getUnknownMember(), tpMap, packOffset, within, point); + if (binding instanceof IType) { + return (IType) binding; + } else if (binding instanceof IVariable) { + return ((IVariable) binding).getType(); + } else if (binding instanceof IFunction) { + return ((IFunction) binding).getType(); + } + return type; + } if (within != null && type instanceof IBinding) { IType unwound= getNestedType(type, TDEF); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TypeOfUnknownMember.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TypeOfUnknownMember.java new file mode 100644 index 00000000000..5f9fcbbe07b --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TypeOfUnknownMember.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 2014 Nathan Ridge. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Nathan Ridge - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.internal.core.dom.parser.ISerializableType; +import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownMember; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownType; +import org.eclipse.cdt.internal.core.index.IIndexFragment; +import org.eclipse.core.runtime.CoreException; + +/** + * Represents the type of an unknown member. + */ +public class TypeOfUnknownMember implements ICPPUnknownType, ISerializableType { + private final CPPUnknownMember fMember; + + public TypeOfUnknownMember(CPPUnknownMember member) { + fMember = member; + } + + public CPPUnknownMember getUnknownMember() { + return fMember; + } + + @Override + public boolean isSameType(IType type) { + return type instanceof TypeOfUnknownMember + && fMember == ((TypeOfUnknownMember) type).fMember; + } + + @Override + public void marshal(ITypeMarshalBuffer buffer) throws CoreException { + buffer.putShort(ITypeMarshalBuffer.UNKNOWN_MEMBER_TYPE); + fMember.marshal(buffer); + } + + public static IType unmarshal(IIndexFragment fragment, short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { + short firstBytesForMember = buffer.getShort(); + if ((firstBytesForMember & ITypeMarshalBuffer.KIND_MASK) != ITypeMarshalBuffer.UNKNOWN_MEMBER) + throw new CoreException(CCorePlugin.createStatus("Expected an unknown memebr, first bytes=" + firstBytesForMember)); //$NON-NLS-1$; + return new TypeOfUnknownMember((CPPUnknownMember) CPPUnknownMember.unmarshal(fragment, firstBytesForMember, buffer)); + } + + @Override + public Object clone() { + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + return null; + } + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CPPCompositesFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CPPCompositesFactory.java index 20c9c4e816d..09e8ed830f4 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CPPCompositesFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CPPCompositesFactory.java @@ -70,6 +70,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPQualifierType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPReferenceType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnaryTypeTransformation; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownMember; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPClassSpecializationScope; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; @@ -96,6 +97,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalTypeId; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalUnary; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalUnaryTypeID; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.TypeOfDependentExpression; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.TypeOfUnknownMember; import org.eclipse.cdt.internal.core.index.CIndex; import org.eclipse.cdt.internal.core.index.IIndexFragmentBinding; import org.eclipse.cdt.internal.core.index.IIndexScope; @@ -236,6 +238,13 @@ public class CPPCompositesFactory extends AbstractCompositeFactory { return new TypeOfDependentExpression(e2); return type; } + if (rtype instanceof TypeOfUnknownMember) { + CPPUnknownMember member = ((TypeOfUnknownMember) rtype).getUnknownMember(); + if (member instanceof IIndexFragmentBinding) + member = (CPPUnknownMember) getCompositeBinding((IIndexFragmentBinding) member); + return new TypeOfUnknownMember(member); + + } if (rtype instanceof ICPPUnaryTypeTransformation) { ICPPUnaryTypeTransformation typeTransformation= (ICPPUnaryTypeTransformation) rtype; IType operand = getCompositeType(typeTransformation.getOperand()); @@ -611,12 +620,6 @@ public class CPPCompositesFactory extends AbstractCompositeFactory { } else { throw new CompositingNotImplementedError("Composite binding unavailable for " + binding + " " + binding.getClass()); //$NON-NLS-1$ //$NON-NLS-2$ } - } else if (binding instanceof ICPPParameter) { - result = new CompositeCPPParameter(this, (ICPPParameter) binding); - } else if (binding instanceof ICPPField) { - result = new CompositeCPPField(this, (ICPPField) binding); - } else if (binding instanceof ICPPVariable) { - result = new CompositeCPPVariable(this, (ICPPVariable) binding); } else if (binding instanceof ICPPUnknownBinding) { if (binding instanceof ICPPUnknownMember) { ICPPUnknownMember def= (ICPPUnknownMember) binding; @@ -636,6 +639,12 @@ public class CPPCompositesFactory extends AbstractCompositeFactory { } } throw new CompositingNotImplementedError("Composite binding unavailable for " + binding + " " + binding.getClass()); //$NON-NLS-1$ //$NON-NLS-2$ + } else if (binding instanceof ICPPParameter) { + result = new CompositeCPPParameter(this, (ICPPParameter) binding); + } else if (binding instanceof ICPPField) { + result = new CompositeCPPField(this, (ICPPField) binding); + } else if (binding instanceof ICPPVariable) { + result = new CompositeCPPVariable(this, (ICPPVariable) binding); } else if (binding instanceof ICPPClassType) { ICPPClassType def = (ICPPClassType) findOneBinding(binding); result = def == null ? null : new CompositeCPPClassType(this, def); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java index a5edefd302b..5c0e2fe5814 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java @@ -255,10 +255,11 @@ public class PDOM extends PlatformObject implements IPDOM { * * CDT 8.6 development (versions not supported on the 8.5.x branch) * 180.0 - Internal types of enumerators, bug 446711. + * 180.1 - Storing types of unknown members, bug 447728. */ - private static final int MIN_SUPPORTED_VERSION= version(180, 0); + private static final int MIN_SUPPORTED_VERSION= version(180, 1); private static final int MAX_SUPPORTED_VERSION= version(180, Short.MAX_VALUE); - private static final int DEFAULT_VERSION = version(180, 0); + private static final int DEFAULT_VERSION = version(180, 1); private static int version(int major, int minor) { return (major << 16) + minor; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java index 3a4af863c8b..ca8e4f6e4e7 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java @@ -121,6 +121,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalTypeId; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalUnary; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalUnaryTypeID; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.TypeOfDependentExpression; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.TypeOfUnknownMember; import org.eclipse.cdt.internal.core.index.IIndexBindingConstants; import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants; import org.eclipse.cdt.internal.core.index.composite.CompositeIndexBinding; @@ -1267,6 +1268,8 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { return CPPAliasTemplateInstance.unmarshal(firstBytes, buffer); case ITypeMarshalBuffer.TYPE_TRANSFORMATION: return CPPUnaryTypeTransformation.unmarshal(firstBytes, buffer); + case ITypeMarshalBuffer.UNKNOWN_MEMBER_TYPE: + return TypeOfUnknownMember.unmarshal(getPDOM(), firstBytes, buffer); } throw new CoreException(CCorePlugin.createStatus("Cannot unmarshal a type, first bytes=" + firstBytes)); //$NON-NLS-1$