mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 14:42:11 +02:00
Bug 447728 - Support for types of unkown fields
Change-Id: Id8ccc110930b86a762a847ff50a8659c87318a4b Signed-off-by: Nathan Ridge <zeratul976@hotmail.com> Reviewed-on: https://git.eclipse.org/r/35302 Reviewed-by: Sergey Prigogin <eclipse.sprigogin@gmail.com> Tested-by: Sergey Prigogin <eclipse.sprigogin@gmail.com>
This commit is contained in:
parent
8e5a31e714
commit
f9f0d4c3da
10 changed files with 154 additions and 10 deletions
|
@ -8594,4 +8594,28 @@ public class AST2TemplateTests extends AST2TestBase {
|
|||
public void testLocalTypeAsTemplateArgument_442832() throws Exception {
|
||||
parseAndCheckBindings();
|
||||
}
|
||||
|
||||
// template <typename T>
|
||||
// struct Bar {};
|
||||
//
|
||||
// template <typename T>
|
||||
// auto foo(T t) -> Bar<decltype(t.foo)> {
|
||||
// Bar<decltype(t.foo)> bar; // bogus `invalid template arguments` error here
|
||||
// return bar;
|
||||
// }
|
||||
//
|
||||
// struct S {
|
||||
// int foo;
|
||||
// };
|
||||
//
|
||||
// int main() {
|
||||
// Bar<int> 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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <typename T>
|
||||
// struct Bar {};
|
||||
//
|
||||
// template <typename T>
|
||||
// auto foo(T t) -> Bar<decltype(t.foo)> {
|
||||
// Bar<decltype(t.foo)> bar; // bogus `invalid template arguments` error here
|
||||
// return bar;
|
||||
// }
|
||||
//
|
||||
// struct S {
|
||||
// int foo;
|
||||
// };
|
||||
|
||||
// int main() {
|
||||
// Bar<int> 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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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$
|
||||
|
|
Loading…
Add table
Reference in a new issue