1
0
Fork 0
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:
Markus Schorn 2011-06-29 11:47:17 +02:00
parent 7cfdf1b5e2
commit b2452fb45d
9 changed files with 128 additions and 132 deletions

View file

@ -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,

View file

@ -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();
}
}

View file

@ -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

View file

@ -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();
}

View file

@ -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);
}
}

View file

@ -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();

View file

@ -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) {

View file

@ -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)) {

View file

@ -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() {