From 794aaa995e48f472010b6f011ddea3e529a8dff0 Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Wed, 28 Sep 2011 14:51:27 +0200 Subject: [PATCH] Bug 350345: Resolving explicit type conversions --- .../core/parser/tests/ast2/AST2CPPTests.java | 10 ++- .../parser/tests/ast2/AST2TemplateTests.java | 28 ++++-- .../internal/core/dom/parser/ProblemType.java | 2 + .../cpp/CPPASTFunctionCallExpression.java | 89 ++++++++++++------- .../parser/cpp/semantics/CPPSemantics.java | 44 +++++---- .../parser/cpp/semantics/CPPTemplates.java | 13 ++- .../resources/refactoring/ExtractMethod.rts | 4 +- .../ui/callhierarchy/CallHierarchyUI.java | 32 ++++++- .../search/actions/OpenDeclarationsJob.java | 25 ++++-- 9 files changed, 167 insertions(+), 80 deletions(-) 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 67758d824e9..7ee28813f70 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 @@ -87,6 +87,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCastExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConversionName; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionCallExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification; @@ -2551,9 +2552,12 @@ public class AST2CPPTests extends AST2BaseTest { ICPPConstructor T1_ctor = (ICPPConstructor) col.getName(6) .resolveBinding(); ICPPClassType T1 = (ICPPClassType) col.getName(0).resolveBinding(); - - assertInstances(col, T1_ctor, 2); - assertInstances(col, T1, 2); + assertInstances(col, T1_ctor, 1); + assertInstances(col, T1, 3); + + ICPPASTFunctionCallExpression fc= (ICPPASTFunctionCallExpression) col.getName(4).getParent().getParent(); + IBinding ctor2 = fc.getImplicitNames()[0].resolveBinding(); + assertSame(T1_ctor, ctor2); } // struct S { int i; }; 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 e26814e4cb9..9f018116ef0 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 @@ -49,6 +49,7 @@ import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.ITypedef; import org.eclipse.cdt.core.dom.ast.IVariable; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionCallExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId; @@ -1725,8 +1726,13 @@ public class AST2TemplateTests extends AST2BaseTest { ICPPConstructor ctor = (ICPPConstructor) col.getName(2).resolveBinding(); ICPPFunction f = (ICPPFunction) col.getName(5).resolveBinding(); - ICPPSpecialization spec = (ICPPSpecialization) col.getName(11).resolveBinding(); - assertSame(spec.getSpecializedBinding(), ctor); + final IASTName typeConversion = col.getName(11); + ICPPSpecialization spec = (ICPPSpecialization) typeConversion.resolveBinding(); + assertSame(ctor.getOwner(), spec.getSpecializedBinding()); + + final ICPPASTFunctionCallExpression fcall = (ICPPASTFunctionCallExpression) typeConversion.getParent().getParent(); + final IBinding ctorSpec = fcall.getImplicitNames()[0].resolveBinding(); + assertSame(ctor, (((ICPPSpecialization) ctorSpec).getSpecializedBinding())); assertSame(f, col.getName(10).resolveBinding()); } @@ -1750,9 +1756,14 @@ public class AST2TemplateTests extends AST2BaseTest { ICPPConstructor ctor = (ICPPConstructor) col.getName(3).resolveBinding(); ICPPMethod add = (ICPPMethod) col.getName(9).resolveBinding(); - ICPPSpecialization spec = (ICPPSpecialization) col.getName(20).resolveBinding(); - assertSame(spec.getSpecializedBinding(), ctor); + final IASTName typeConversion = col.getName(20); + ICPPSpecialization spec = (ICPPSpecialization) typeConversion.resolveBinding(); + assertSame(ctor.getOwner(), spec.getSpecializedBinding()); + final ICPPASTFunctionCallExpression fcall = (ICPPASTFunctionCallExpression) typeConversion.getParent().getParent(); + final IBinding ctorSpec = fcall.getImplicitNames()[0].resolveBinding(); + assertSame(ctor, (((ICPPSpecialization) ctorSpec).getSpecializedBinding())); + assertSame(add, col.getName(19).resolveBinding()); } @@ -1772,9 +1783,14 @@ public class AST2TemplateTests extends AST2BaseTest { ICPPConstructor ctor = (ICPPConstructor) col.getName(2).resolveBinding(); ICPPMethod add = (ICPPMethod) col.getName(7).resolveBinding(); - ICPPSpecialization spec = (ICPPSpecialization) col.getName(17).resolveBinding(); - assertSame(spec.getSpecializedBinding(), ctor); + final IASTName typeConversion = col.getName(17); + ICPPSpecialization spec = (ICPPSpecialization) typeConversion.resolveBinding(); + assertSame(ctor.getOwner(), spec.getSpecializedBinding()); + final ICPPASTFunctionCallExpression fcall = (ICPPASTFunctionCallExpression) typeConversion.getParent().getParent(); + final IBinding ctorSpec = fcall.getImplicitNames()[0].resolveBinding(); + assertSame(ctor, (((ICPPSpecialization) ctorSpec).getSpecializedBinding())); + assertSame(add, col.getName(16).resolveBinding()); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemType.java index a936ef92c0b..4172ddaf9a0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemType.java @@ -20,6 +20,8 @@ import org.eclipse.core.runtime.CoreException; * Implementation of problem types. */ public class ProblemType implements IProblemType, ISerializableType { + public static final IType UNRESOLVED_NAME = new ProblemType(TYPE_UNRESOLVED_NAME); + private final int fID; public ProblemType(int id) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionCallExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionCallExpression.java index 5f484e3700a..89a49353461 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionCallExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionCallExpression.java @@ -13,21 +13,18 @@ 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.internal.core.dom.parser.cpp.semantics.ExpressionTypes.prvalueType; -import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.typeFromFunctionCall; -import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.typeFromReturnType; -import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.valueCategoryFromFunctionCall; -import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.valueCategoryFromReturnType; -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.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.*; import org.eclipse.cdt.core.dom.ast.ASTVisitor; +import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.ExpansionOverlapsBoundaryException; import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTIdExpression; import org.eclipse.cdt.core.dom.ast.IASTImplicitName; import org.eclipse.cdt.core.dom.ast.IASTInitializerClause; +import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IFunctionType; @@ -38,7 +35,6 @@ import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExpressionList; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionCallExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.parser.IToken; @@ -47,6 +43,7 @@ import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent; 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.CPPTemplates; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.LookupData; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; @@ -124,7 +121,17 @@ public class CPPASTFunctionCallExpression extends ASTNode implements public IASTImplicitName[] getImplicitNames() { if (implicitNames == null) { ICPPFunction overload = getOperator(); - if (overload == null || overload instanceof CPPImplicitFunction) { + if (overload == null) + return implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY; + + if (isExplicitTypeConversion() != null) { + CPPASTImplicitName n1 = new CPPASTImplicitName(overload.getNameCharArray(), this); + n1.setOffsetAndLength((ASTNode) functionName); + n1.setBinding(overload); + return implicitNames= new IASTImplicitName[] {n1}; + } + + if (overload instanceof CPPImplicitFunction) { if (!(overload instanceof ICPPMethod) || ((ICPPMethod) overload).isImplicit()) { return implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY; } @@ -190,7 +197,7 @@ public class CPPASTFunctionCallExpression extends ASTNode implements return false; } - if (implicits != null && implicits.length > 0 && !implicits[1].accept(action)) + if (implicits != null && implicits.length > 1 && !implicits[1].accept(action)) return false; if (action.shouldVisitExpressions && action.leave(this) == ASTVisitor.PROCESS_ABORT) @@ -217,35 +224,40 @@ public class CPPASTFunctionCallExpression extends ASTNode implements public ICPPFunction getOperator() { if (overload == UNINITIALIZED_FUNCTION) { overload= null; - IType t= functionName.getExpressionType(); - t= SemanticUtil.getNestedType(t, TDEF | REF | CVTYPE); - if (t instanceof ICPPClassType) { - overload = CPPSemantics.findOverloadedOperator(this, (ICPPClassType)t); + IType t= isExplicitTypeConversion(); + if (t != null) { + t = getNestedType(t, TDEF|CVTYPE|REF); + if (t instanceof ICPPClassType && !(t instanceof ICPPUnknownBinding)) { + ICPPClassType cls= (ICPPClassType) t; + LookupData data= CPPSemantics.createLookupData(((IASTIdExpression) functionName).getName()); + try { + IBinding b= CPPSemantics.resolveFunction(data, cls.getConstructors(), true); + if (b instanceof ICPPFunction) + overload= (ICPPFunction) b; + } catch (DOMException e) { + } + } + } else { + t= SemanticUtil.getNestedType(functionName.getExpressionType(), TDEF|REF|CVTYPE); + if (t instanceof ICPPClassType) { + overload = CPPSemantics.findOverloadedOperator(this, (ICPPClassType)t); + } } } return overload; } public IType getExpressionType() { - if (functionName instanceof IASTIdExpression) { - // Handle misused id-expression in functional type conversions or simple type initializers. - final IBinding binding= ((IASTIdExpression) functionName).getName().resolvePreBinding(); - if (binding instanceof ICPPConstructor) { - IBinding owner= binding.getOwner(); - if (owner instanceof ICPPClassType) { - return (ICPPClassType) owner; - } - return new ProblemType(ISemanticProblem.TYPE_UNKNOWN_FOR_EXPRESSION); - } - if (binding instanceof IProblemBinding) { - return new ProblemType(ISemanticProblem.TYPE_UNRESOLVED_NAME); + // Handle explicit type conversion in functional notation. + IType t= isExplicitTypeConversion(); + if (t != null) { + if (t instanceof IProblemBinding) { + return ProblemType.UNRESOLVED_NAME; } - if (binding instanceof IType) { - return prvalueType((IType) binding); - } + return prvalueType(t); } - IType t= SemanticUtil.getNestedType(functionName.getExpressionType(), TDEF|REF|CVTYPE); + t= SemanticUtil.getNestedType(functionName.getExpressionType(), TDEF|REF|CVTYPE); if (t instanceof ICPPClassType) { if (overload == UNINITIALIZED_FUNCTION) { overload = CPPSemantics.findOverloadedOperator(this, (ICPPClassType)t); @@ -268,11 +280,24 @@ public class CPPASTFunctionCallExpression extends ASTNode implements return new ProblemType(ISemanticProblem.TYPE_UNKNOWN_FOR_EXPRESSION); } - public boolean isLValue() { + private IType isExplicitTypeConversion() { + if (functionName instanceof IASTIdExpression) { + final IASTName name = ((IASTIdExpression) functionName).getName(); + IBinding b= name.resolvePreBinding(); + if (b instanceof IType) + return (IType) b; + } + return null; + } + + public boolean isLValue() { return getValueCategory() == LVALUE; } public ValueCategory getValueCategory() { + if (isExplicitTypeConversion() != null) + return PRVALUE; + IType t= functionName.getExpressionType(); if (t instanceof ICPPClassType) { if (overload == UNINITIALIZED_FUNCTION) { 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 c413f46c01d..03a655b8892 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 @@ -308,6 +308,15 @@ public class CPPSemantics { } } + // Explicit type conversion in functional notation + if (binding instanceof ICPPClassTemplate && data.astName instanceof ICPPASTTemplateId) { + final IASTNode parent = data.astName.getParent(); + if (parent instanceof IASTIdExpression && + parent.getPropertyInParent() == IASTFunctionCallExpression.FUNCTION_NAME) { + return binding; + } + } + /* 14.6.1-1: * Within the scope of a class template, when the name of the template is neither qualified nor * followed by <, it is equivalent to the name followed by the template parameters enclosed in <>. @@ -441,15 +450,15 @@ public class CPPSemantics { } } else if (namePropertyInParent == IASTIdExpression.ID_NAME) { if (binding instanceof IType) { - IASTNode parent= name.getParent().getParent(); - if (parent instanceof ICPPASTTemplatedTypeTemplateParameter) { - // default for template template parameter is an id-expression, which is a type. - } else if (parent instanceof ICPPASTUnaryExpression - && ((ICPPASTUnaryExpression) parent).getOperator() == IASTUnaryExpression.op_sizeofParameterPack) { - // argument of sizeof... can be a type - } else if ((binding instanceof ICPPUnknownType || binding instanceof ITypedef || binding instanceof IEnumeration) - && convertClassToConstructor(data.astName)) { - // constructor or simple-type constructor + final IASTNode idExpr = name.getParent(); + ASTNodeProperty pip = idExpr.getPropertyInParent(); + if (pip == ICPPASTTemplatedTypeTemplateParameter.DEFAULT_VALUE) { + // Default for template template parameter is a type. + } else if (pip == IASTFunctionCallExpression.FUNCTION_NAME) { + // Explicit type conversion in functional notation. + } else if (pip == IASTUnaryExpression.OPERAND + && ((ICPPASTUnaryExpression) idExpr.getParent()).getOperator() == IASTUnaryExpression.op_sizeofParameterPack) { + // Argument of sizeof... can be a type } else { binding= new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_INVALID_TYPE, data.getFoundBindings()); @@ -511,20 +520,7 @@ public class CPPSemantics { if (parent instanceof ICPPASTConstructorChainInitializer) { return true; } - if (parent instanceof IASTExpression) { - ASTNodeProperty propInParent= parent.getPropertyInParent(); - if (parent instanceof IASTIdExpression) { - parent= parent.getParent(); - } - while (parent instanceof IASTUnaryExpression - && ((IASTUnaryExpression) parent).getOperator() == IASTUnaryExpression.op_bracketedPrimary) { - propInParent = parent.getPropertyInParent(); - parent= parent.getParent(); - } - if (parent instanceof IASTFunctionCallExpression && propInParent == IASTFunctionCallExpression.FUNCTION_NAME) { - return true; - } - } else if (parent instanceof ICPPASTNamedTypeSpecifier) { + if (parent instanceof ICPPASTNamedTypeSpecifier) { parent= parent.getParent(); if (parent instanceof IASTTypeId && parent.getParent() instanceof ICPPASTNewExpression) { IASTDeclarator dtor = ((IASTTypeId) parent).getAbstractDeclarator(); @@ -2324,7 +2320,7 @@ public class CPPSemantics { return result; } - static IBinding resolveFunction(LookupData data, ICPPFunction[] fns, boolean allowUDC) throws DOMException { + public static IBinding resolveFunction(LookupData data, ICPPFunction[] fns, boolean allowUDC) throws DOMException { fns= (ICPPFunction[]) ArrayUtil.trim(ICPPFunction.class, fns); if (fns == null || fns.length == 0) return null; 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 fd0d47050de..4d4935bc154 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 @@ -605,12 +605,17 @@ public class CPPTemplates { //functions are instantiated as part of the resolution process IBinding result= CPPVisitor.createBinding(id); IASTName templateName = id.getTemplateName(); - if (result instanceof ICPPTemplateInstance) { - templateName.setBinding(((ICPPTemplateInstance) result).getTemplateDefinition()); - } else { + if (result instanceof ICPPClassTemplate) { templateName.setBinding(result); + id.setBinding(null); + } else { + if (result instanceof ICPPTemplateInstance) { + templateName.setBinding(((ICPPTemplateInstance) result).getTemplateDefinition()); + } else { + templateName.setBinding(result); + } + return result; } - return result; } IASTNode parentOfName = id.getParent(); diff --git a/core/org.eclipse.cdt.ui.tests/resources/refactoring/ExtractMethod.rts b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ExtractMethod.rts index 4ecde97741d..8f91ea478c7 100644 --- a/core/org.eclipse.cdt.ui.tests/resources/refactoring/ExtractMethod.rts +++ b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ExtractMethod.rts @@ -2189,7 +2189,7 @@ public: virtual ~Test(); private: void test(); - RetValueType exp(); + RetType exp(); }; #endif /* TEST_H_ */ @@ -2218,7 +2218,7 @@ Test::Test() { Test::~Test() { } -RetValueType Test::exp() +RetType Test::exp() { return RetType(); } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/callhierarchy/CallHierarchyUI.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/callhierarchy/CallHierarchyUI.java index 43298556bea..d520b11a21f 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/callhierarchy/CallHierarchyUI.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/callhierarchy/CallHierarchyUI.java @@ -23,12 +23,18 @@ import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.texteditor.ITextEditor; import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.dom.ast.DOMException; +import org.eclipse.cdt.core.dom.ast.EScopeKind; +import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression; +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.IBinding; import org.eclipse.cdt.core.dom.ast.IEnumerator; import org.eclipse.cdt.core.dom.ast.IFunction; import org.eclipse.cdt.core.dom.ast.IVariable; import org.eclipse.cdt.core.dom.ast.c.ICExternalBinding; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionCallExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization; import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.index.IIndexManager; @@ -36,7 +42,6 @@ import org.eclipse.cdt.core.index.IIndexName; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.core.model.ITranslationUnit; -import org.eclipse.cdt.internal.ui.viewsupport.CElementLabels; import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.cdt.internal.core.model.ext.ICElementHandle; @@ -45,6 +50,7 @@ import org.eclipse.cdt.internal.corext.util.CModelUtil; import org.eclipse.cdt.internal.ui.actions.OpenActionUtil; import org.eclipse.cdt.internal.ui.util.ExceptionHandler; import org.eclipse.cdt.internal.ui.util.StatusLineHandler; +import org.eclipse.cdt.internal.ui.viewsupport.CElementLabels; import org.eclipse.cdt.internal.ui.viewsupport.IndexUI; public class CallHierarchyUI { @@ -158,6 +164,19 @@ public class CallHierarchyUI { IASTName name= IndexUI.getSelectedName(editorInput, sel); if (name != null) { IBinding binding= name.resolveBinding(); + if (!CallHierarchyUI.isRelevantForCallHierarchy(binding)) { + for (IASTNode parent= name; parent != null; parent= parent.getParent()) { + if (parent.getPropertyInParent() == IASTFunctionCallExpression.FUNCTION_NAME) { + ICPPASTFunctionCallExpression fcall= (ICPPASTFunctionCallExpression) parent.getParent(); + if (fcall != null) { + IASTImplicitName[] implicit = fcall.getImplicitNames(); + if (implicit.length > 0) + binding= implicit[0].resolveBinding(); + } + break; + } + } + } if (CallHierarchyUI.isRelevantForCallHierarchy(binding)) { if (name.isDefinition()) { ICElement elem= IndexUI.getCElementForName(project, index, name); @@ -270,8 +289,15 @@ public class CallHierarchyUI { public static boolean isRelevantForCallHierarchy(IBinding binding) { if (binding instanceof ICExternalBinding || binding instanceof IEnumerator || - binding instanceof IFunction || - binding instanceof IVariable) { + binding instanceof IFunction) + return true; + + if (binding instanceof IVariable) { + try { + if (binding.getScope().getKind() == EScopeKind.eLocal) + return false; + } catch (DOMException e) { + } return true; } return false; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/actions/OpenDeclarationsJob.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/actions/OpenDeclarationsJob.java index f1ee815d040..4e149bbbd68 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/actions/OpenDeclarationsJob.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/actions/OpenDeclarationsJob.java @@ -71,8 +71,10 @@ import org.eclipse.cdt.core.index.IndexFilter; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.core.model.ILanguage; +import org.eclipse.cdt.core.model.IMethodDeclaration; import org.eclipse.cdt.core.model.ISourceRange; import org.eclipse.cdt.core.model.ISourceReference; +import org.eclipse.cdt.core.model.IStructureDeclaration; import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.core.parser.util.CharArrayUtils; @@ -487,13 +489,24 @@ class OpenDeclarationsJob extends Job implements ASTRunnable { if (uniqueElements.size() == 1) { target= (ISourceReference) uniqueElements.get(0); } else { - if (OpenDeclarationsAction.sIsJUnitTest) { - throw new RuntimeException("ambiguous input: " + uniqueElements.size()); //$NON-NLS-1$ + if (uniqueElements.size() == 2) { + final ICElement e0 = uniqueElements.get(0); + final ICElement e1 = uniqueElements.get(1); + if (e0 instanceof IStructureDeclaration && e1 instanceof IMethodDeclaration) { + target= (ISourceReference) e1; + } else if (e1 instanceof IStructureDeclaration && e0 instanceof IMethodDeclaration) { + target= (ISourceReference) e0; + } + } + if (target == null) { + if (OpenDeclarationsAction.sIsJUnitTest) { + throw new RuntimeException("ambiguous input: " + uniqueElements.size()); //$NON-NLS-1$ + } + ICElement[] elemArray= uniqueElements.toArray(new ICElement[uniqueElements.size()]); + target = (ISourceReference) OpenActionUtil.selectCElement(elemArray, fAction.getSite().getShell(), + CEditorMessages.OpenDeclarationsAction_dialog_title, CEditorMessages.OpenDeclarationsAction_selectMessage, + CElementLabels.ALL_DEFAULT | CElementLabels.ALL_FULLY_QUALIFIED | CElementLabels.MF_POST_FILE_QUALIFIED, 0); } - ICElement[] elemArray= uniqueElements.toArray(new ICElement[uniqueElements.size()]); - target = (ISourceReference) OpenActionUtil.selectCElement(elemArray, fAction.getSite().getShell(), - CEditorMessages.OpenDeclarationsAction_dialog_title, CEditorMessages.OpenDeclarationsAction_selectMessage, - CElementLabels.ALL_DEFAULT | CElementLabels.ALL_FULLY_QUALIFIED | CElementLabels.MF_POST_FILE_QUALIFIED, 0); } if (target != null) { ITranslationUnit tu= target.getTranslationUnit();