mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-24 17:35:35 +02:00
Bug 347298: Array type in field access.
This commit is contained in:
parent
7cfdf1b5e2
commit
b2452fb45d
9 changed files with 128 additions and 132 deletions
|
@ -2,7 +2,7 @@ Manifest-Version: 1.0
|
|||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: org.eclipse.cdt.core.tests
|
||||
Bundle-SymbolicName: org.eclipse.cdt.core.tests; singleton:=true
|
||||
Bundle-Version: 5.3.0.qualifier
|
||||
Bundle-Version: 5.4.0.qualifier
|
||||
Bundle-Activator: org.eclipse.cdt.core.testplugin.CTestPlugin
|
||||
Export-Package: org.eclipse.cdt.core.cdescriptor.tests,
|
||||
org.eclipse.cdt.core.envvar,
|
||||
|
|
|
@ -9391,4 +9391,15 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
assertTrue(qn.isDeclaration());
|
||||
assertTrue(qn.getLastName().isDeclaration());
|
||||
}
|
||||
|
||||
// struct S{
|
||||
// void foo(){}
|
||||
// };
|
||||
// void test(){
|
||||
// S s[1];
|
||||
// s->foo();
|
||||
// }
|
||||
public void testMemberAccessForArray_347298() throws Exception {
|
||||
parseAndCheckBindings();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ Manifest-Version: 1.0
|
|||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: %pluginName
|
||||
Bundle-SymbolicName: org.eclipse.cdt.core; singleton:=true
|
||||
Bundle-Version: 5.3.0.qualifier
|
||||
Bundle-Version: 5.4.0.qualifier
|
||||
Bundle-Activator: org.eclipse.cdt.core.CCorePlugin
|
||||
Bundle-Vendor: %providerName
|
||||
Bundle-Localization: plugin
|
||||
|
|
|
@ -13,6 +13,7 @@ package org.eclipse.cdt.core.dom.ast.cpp;
|
|||
|
||||
import org.eclipse.cdt.core.dom.ast.IASTFieldReference;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
|
||||
/**
|
||||
* Certain field references in C++ require the use the keyword template to
|
||||
|
@ -45,4 +46,10 @@ public interface ICPPASTFieldReference extends IASTFieldReference, IASTImplicitN
|
|||
* @since 5.3
|
||||
*/
|
||||
public ICPPASTFieldReference copy(CopyStyle style);
|
||||
|
||||
/**
|
||||
* Returns the type of the field owner.
|
||||
* @since 5.4
|
||||
*/
|
||||
public IType getFieldOwnerType();
|
||||
}
|
||||
|
|
|
@ -17,12 +17,11 @@ import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.LVALUE;
|
|||
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.PRVALUE;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.glvalueType;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.prvalueType;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.ALLCVQ;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.CVTYPE;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.REF;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.typeFromFunctionCall;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
||||
|
@ -41,6 +40,7 @@ import org.eclipse.cdt.core.dom.ast.ISemanticProblem;
|
|||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.IVariable;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldReference;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||
|
@ -139,11 +139,7 @@ public class CPPASTFieldReference extends ASTNode implements ICPPASTFieldReferen
|
|||
|
||||
// collect the function bindings
|
||||
List<ICPPFunction> functionBindings = new ArrayList<ICPPFunction>();
|
||||
try {
|
||||
CPPSemantics.getFieldOwnerType(this, functionBindings);
|
||||
} catch (DOMException e) {
|
||||
return implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
|
||||
}
|
||||
getFieldOwnerType(functionBindings);
|
||||
if (functionBindings.isEmpty())
|
||||
return implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
|
||||
|
||||
|
@ -319,4 +315,62 @@ public class CPPASTFieldReference extends ASTNode implements ICPPASTFieldReferen
|
|||
public IBinding[] findBindings(IASTName n, boolean isPrefix) {
|
||||
return findBindings(n, isPrefix, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* For a pointer dereference expression e1->e2, return the type that e1 ultimately evaluates to
|
||||
* after chaining overloaded class member access operators <code>operator->()</code> calls.
|
||||
*/
|
||||
public IType getFieldOwnerType() {
|
||||
return getFieldOwnerType(null);
|
||||
}
|
||||
|
||||
/*
|
||||
* Also collects the function bindings if requested.
|
||||
*/
|
||||
private IType getFieldOwnerType(Collection<ICPPFunction> functionBindings) {
|
||||
final IASTExpression owner = getFieldOwner();
|
||||
if (owner == null)
|
||||
return null;
|
||||
|
||||
IType type= owner.getExpressionType();
|
||||
if (!isPointerDereference())
|
||||
return type;
|
||||
|
||||
// bug 205964: as long as the type is a class type, recurse.
|
||||
// Be defensive and allow a max of 20 levels.
|
||||
for (int j = 0; j < 20; j++) {
|
||||
// for unknown types we cannot determine the overloaded -> operator
|
||||
IType classType= getUltimateTypeUptoPointers(type);
|
||||
if (classType instanceof ICPPUnknownType)
|
||||
return CPPUnknownClass.createUnnamedInstance();
|
||||
|
||||
if (!(classType instanceof ICPPClassType))
|
||||
break;
|
||||
|
||||
/*
|
||||
* 13.5.6-1: An expression x->m is interpreted as (x.operator->())->m for a
|
||||
* class object x of type T
|
||||
*
|
||||
* Construct an AST fragment for x.operator-> which the lookup routines can
|
||||
* examine for type information.
|
||||
*/
|
||||
|
||||
ICPPFunction op = CPPSemantics.findOverloadedOperator(this, type, (ICPPClassType) classType);
|
||||
if (op == null)
|
||||
break;
|
||||
|
||||
if (functionBindings != null)
|
||||
functionBindings.add(op);
|
||||
|
||||
type= typeFromFunctionCall(op);
|
||||
type= SemanticUtil.mapToAST(type, owner);
|
||||
}
|
||||
|
||||
IType prValue= prvalueType(type);
|
||||
if (prValue instanceof IPointerType) {
|
||||
return glvalueType(((IPointerType) prValue).getType());
|
||||
}
|
||||
|
||||
return new ProblemType(ISemanticProblem.TYPE_UNKNOWN_FOR_EXPRESSION);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,9 +16,7 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
|||
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.LVALUE;
|
||||
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.PRVALUE;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.*;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.CVTYPE;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.REF;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getUltimateTypeUptoPointers;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||
|
@ -28,7 +26,6 @@ import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
|
|||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IArrayType;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IFunction;
|
||||
import org.eclipse.cdt.core.dom.ast.IPointerType;
|
||||
|
@ -46,7 +43,6 @@ import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
|
|||
import org.eclipse.cdt.internal.core.dom.parser.ProblemType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
|
||||
|
||||
/**
|
||||
* Unary expression in c++
|
||||
|
@ -249,15 +245,15 @@ public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpres
|
|||
|
||||
if (op == op_star) {
|
||||
IType type= operand.getExpressionType();
|
||||
type = SemanticUtil.getNestedType(type, TDEF | REF | CVTYPE);
|
||||
if (type instanceof ISemanticProblem) {
|
||||
return type;
|
||||
}
|
||||
|
||||
if (type instanceof IPointerType || type instanceof IArrayType) {
|
||||
type = prvalueType(type);
|
||||
if (type instanceof IPointerType) {
|
||||
type= ((ITypeContainer) type).getType();
|
||||
return glvalueType(type);
|
||||
}
|
||||
if (type instanceof ISemanticProblem) {
|
||||
return type;
|
||||
}
|
||||
type= getUltimateTypeUptoPointers(type);
|
||||
if (type instanceof ICPPUnknownType) {
|
||||
// mstodo Type of unknown
|
||||
return CPPUnknownClass.createUnnamedInstance();
|
||||
|
|
|
@ -23,7 +23,6 @@ import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUti
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
@ -2922,69 +2921,6 @@ public class CPPSemantics {
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* For a pointer dereference expression e1->e2, return the type that e1 ultimately evaluates to
|
||||
* when chaining overloaded class member access operators <code>operator->()</code> calls.
|
||||
* @param fieldReference
|
||||
* @return the type the field owner expression ultimately evaluates to when chaining overloaded
|
||||
* class member access operators <code>operator->()</code> calls.
|
||||
* @throws DOMException
|
||||
*/
|
||||
public static IType getFieldOwnerType(ICPPASTFieldReference fieldReference) throws DOMException {
|
||||
return getFieldOwnerType(fieldReference, null);
|
||||
}
|
||||
|
||||
/*
|
||||
* Also collects the function bindings if requested.
|
||||
*/
|
||||
public static IType getFieldOwnerType(ICPPASTFieldReference fieldReference, Collection<ICPPFunction> functionBindings) throws DOMException {
|
||||
final IASTExpression owner = fieldReference.getFieldOwner();
|
||||
if (owner == null)
|
||||
return null;
|
||||
|
||||
IType type= SemanticUtil.getNestedType(owner.getExpressionType(), TDEF|REF);
|
||||
if (!fieldReference.isPointerDereference())
|
||||
return type;
|
||||
|
||||
// bug 205964: as long as the type is a class type, recurse.
|
||||
// Be defensive and allow a max of 10 levels.
|
||||
boolean foundOperator= false;
|
||||
for (int j = 0; j < 10; j++) {
|
||||
IType uTemp= getUltimateTypeUptoPointers(type);
|
||||
if (uTemp instanceof IPointerType)
|
||||
return type;
|
||||
|
||||
// for unknown types we cannot determine the overloaded -> operator
|
||||
if (uTemp instanceof ICPPUnknownType)
|
||||
return CPPUnknownClass.createUnnamedInstance();
|
||||
|
||||
if (!(uTemp instanceof ICPPClassType))
|
||||
break;
|
||||
|
||||
/*
|
||||
* 13.5.6-1: An expression x->m is interpreted as (x.operator->())->m for a
|
||||
* class object x of type T
|
||||
*
|
||||
* Construct an AST fragment for x.operator-> which the lookup routines can
|
||||
* examine for type information.
|
||||
*/
|
||||
|
||||
IASTExpression arg = createArgForType(fieldReference, type);
|
||||
ICPPFunction op = findOverloadedOperator(fieldReference, new IASTExpression[] {arg}, uTemp, OverloadableOperator.ARROW, LookupMode.NO_GLOBALS);
|
||||
if (op == null)
|
||||
break;
|
||||
|
||||
if (functionBindings != null)
|
||||
functionBindings.add(op);
|
||||
|
||||
type= SemanticUtil.getNestedType(op.getType().getReturnType(), TDEF|REF);
|
||||
type= SemanticUtil.mapToAST(type, owner);
|
||||
foundOperator= true;
|
||||
}
|
||||
|
||||
return foundOperator ? type : null;
|
||||
}
|
||||
|
||||
public static ICPPFunction findOverloadedOperator(IASTArraySubscriptExpression exp) {
|
||||
final IASTExpression arrayExpression = exp.getArrayExpression();
|
||||
IASTInitializerClause[] args = {arrayExpression, exp.getArgument()};
|
||||
|
@ -3279,6 +3215,14 @@ public class CPPSemantics {
|
|||
return findOverloadedOperator(dummy, args, op1type, OverloadableOperator.COMMA, LookupMode.LIMITED_GLOBALS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the operator->() function
|
||||
*/
|
||||
public static ICPPFunction findOverloadedOperator(ICPPASTFieldReference fieldRef, IType cvQualifiedType, ICPPClassType classType) {
|
||||
IASTExpression arg = CPPSemantics.createArgForType(fieldRef, cvQualifiedType);
|
||||
return findOverloadedOperator(fieldRef, new IASTExpression[] {arg}, classType, OverloadableOperator.ARROW, LookupMode.NO_GLOBALS);
|
||||
}
|
||||
|
||||
private static enum LookupMode {NO_GLOBALS, LIMITED_GLOBALS, ALL_GLOBALS}
|
||||
private static ICPPFunction findOverloadedOperator(IASTExpression parent, IASTInitializerClause[] args, IType methodLookupType,
|
||||
OverloadableOperator operator, LookupMode mode) {
|
||||
|
|
|
@ -1121,19 +1121,16 @@ public class CPPVisitor extends ASTQueries {
|
|||
data.usesEnclosingScope= false;
|
||||
}
|
||||
final ICPPASTFieldReference fieldReference = (ICPPASTFieldReference) parent;
|
||||
IType type = CPPSemantics.getFieldOwnerType(fieldReference);
|
||||
if (fieldReference.isPointerDereference()) {
|
||||
type= getUltimateType(type, false);
|
||||
} else {
|
||||
type= getUltimateTypeUptoPointers(type);
|
||||
}
|
||||
IType type = fieldReference.getFieldOwnerType();
|
||||
type= getUltimateTypeUptoPointers(type);
|
||||
if (type instanceof ICPPClassType) {
|
||||
if (type instanceof IIndexBinding) {
|
||||
type= (((CPPASTTranslationUnit) fieldReference.getTranslationUnit())).mapToAST((ICPPClassType) type);
|
||||
}
|
||||
type= SemanticUtil.mapToAST(type, fieldReference);
|
||||
return ((ICPPClassType) type).getCompositeScope();
|
||||
} else if (type instanceof ICPPUnknownBinding) {
|
||||
return ((ICPPUnknownBinding) type).asScope();
|
||||
} else {
|
||||
// mstodo introduce problem category
|
||||
return new CPPScope.CPPScopeProblem(name, ISemanticProblem.TYPE_UNKNOWN_FOR_EXPRESSION);
|
||||
}
|
||||
} else if (parent instanceof IASTGotoStatement || parent instanceof IASTLabelStatement) {
|
||||
while (!(parent instanceof IASTFunctionDefinition)) {
|
||||
|
|
|
@ -22,7 +22,6 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
|
||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
||||
|
@ -42,7 +41,6 @@ import org.eclipse.cdt.core.dom.ast.IASTNode;
|
|||
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IPointerType;
|
||||
import org.eclipse.cdt.core.dom.ast.IScope;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.c.ICASTFieldDesignator;
|
||||
|
@ -401,41 +399,30 @@ public class LookupData {
|
|||
nameParent= name.getParent();
|
||||
}
|
||||
|
||||
try {
|
||||
final ASTNodeProperty prop = name.getPropertyInParent();
|
||||
if (prop == CPPSemantics.STRING_LOOKUP_PROPERTY) {
|
||||
return null;
|
||||
}
|
||||
if (prop == IASTFieldReference.FIELD_NAME) {
|
||||
ICPPASTFieldReference fieldRef = (ICPPASTFieldReference) nameParent;
|
||||
IType implied= CPPSemantics.getFieldOwnerType(fieldRef);
|
||||
if (fieldRef.isPointerDereference()) {
|
||||
implied= SemanticUtil.getUltimateTypeUptoPointers(implied);
|
||||
if (implied instanceof IPointerType)
|
||||
return ((IPointerType) implied).getType();
|
||||
}
|
||||
return implied;
|
||||
}
|
||||
if (prop == IASTIdExpression.ID_NAME) {
|
||||
IScope scope = CPPVisitor.getContainingScope(name);
|
||||
if (scope instanceof ICPPClassScope) {
|
||||
return ((ICPPClassScope) scope).getClassType();
|
||||
}
|
||||
|
||||
return CPPVisitor.getImpliedObjectType(scope);
|
||||
}
|
||||
if (prop == IASTDeclarator.DECLARATOR_NAME) {
|
||||
if (forExplicitFunctionInstantiation()) {
|
||||
IScope scope = CPPVisitor.getContainingScope(astName);
|
||||
if (scope instanceof ICPPClassScope) {
|
||||
return ((ICPPClassScope) scope).getClassType();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
} catch (DOMException e) {
|
||||
return e.getProblem();
|
||||
}
|
||||
final ASTNodeProperty prop = name.getPropertyInParent();
|
||||
if (prop == CPPSemantics.STRING_LOOKUP_PROPERTY) {
|
||||
return null;
|
||||
}
|
||||
if (prop == IASTFieldReference.FIELD_NAME) {
|
||||
ICPPASTFieldReference fieldRef = (ICPPASTFieldReference) nameParent;
|
||||
return fieldRef.getFieldOwnerType();
|
||||
}
|
||||
if (prop == IASTIdExpression.ID_NAME) {
|
||||
IScope scope = CPPVisitor.getContainingScope(name);
|
||||
if (scope instanceof ICPPClassScope) {
|
||||
return ((ICPPClassScope) scope).getClassType();
|
||||
}
|
||||
return CPPVisitor.getImpliedObjectType(scope);
|
||||
}
|
||||
if (prop == IASTDeclarator.DECLARATOR_NAME) {
|
||||
if (forExplicitFunctionInstantiation()) {
|
||||
IScope scope = CPPVisitor.getContainingScope(astName);
|
||||
if (scope instanceof ICPPClassScope) {
|
||||
return ((ICPPClassScope) scope).getClassType();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean forFriendship() {
|
||||
|
|
Loading…
Add table
Reference in a new issue