From b2452fb45d0f19299ca931828f1d7f9b9de629e6 Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Wed, 29 Jun 2011 11:47:17 +0200 Subject: [PATCH] Bug 347298: Array type in field access. --- .../META-INF/MANIFEST.MF | 2 +- .../core/parser/tests/ast2/AST2CPPTests.java | 11 +++ .../org.eclipse.cdt.core/META-INF/MANIFEST.MF | 2 +- .../dom/ast/cpp/ICPPASTFieldReference.java | 7 ++ .../dom/parser/cpp/CPPASTFieldReference.java | 72 ++++++++++++++++--- .../dom/parser/cpp/CPPASTUnaryExpression.java | 18 ++--- .../parser/cpp/semantics/CPPSemantics.java | 72 +++---------------- .../dom/parser/cpp/semantics/CPPVisitor.java | 15 ++-- .../dom/parser/cpp/semantics/LookupData.java | 61 +++++++--------- 9 files changed, 128 insertions(+), 132 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/META-INF/MANIFEST.MF b/core/org.eclipse.cdt.core.tests/META-INF/MANIFEST.MF index 5ee390fd79e..fa08a99b27f 100644 --- a/core/org.eclipse.cdt.core.tests/META-INF/MANIFEST.MF +++ b/core/org.eclipse.cdt.core.tests/META-INF/MANIFEST.MF @@ -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, diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java index c64ca6ddbb2..93a0582d0ca 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java @@ -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(); + } } diff --git a/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF b/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF index 238adb9b4f9..e328381ed98 100644 --- a/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF +++ b/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF @@ -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 diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTFieldReference.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTFieldReference.java index 4282cda9e2a..03a06174cbe 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTFieldReference.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTFieldReference.java @@ -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(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFieldReference.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFieldReference.java index ebd4f0a2461..7ca5e3f97f6 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFieldReference.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFieldReference.java @@ -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 functionBindings = new ArrayList(); - 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 operator->() calls. + */ + public IType getFieldOwnerType() { + return getFieldOwnerType(null); + } + + /* + * Also collects the function bindings if requested. + */ + private IType getFieldOwnerType(Collection 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); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTUnaryExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTUnaryExpression.java index 9236b6be6b3..1905933da34 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTUnaryExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTUnaryExpression.java @@ -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(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java index c3661edffcd..c7b538a33eb 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java @@ -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 operator->() calls. - * @param fieldReference - * @return the type the field owner expression ultimately evaluates to when chaining overloaded - * class member access operators operator->() 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 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) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java index 0715609e8ba..476f3a42bff 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java @@ -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)) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java index 8ea3c5caff8..41095ccab2a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java @@ -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() {