diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CPPSelectionTestsNoIndexer.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CPPSelectionTestsNoIndexer.java index 2915e2f3e4f..857168d1778 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CPPSelectionTestsNoIndexer.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CPPSelectionTestsNoIndexer.java @@ -35,6 +35,7 @@ import org.eclipse.ui.texteditor.ITextEditor; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.IPDOMManager; +import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IBinding; @@ -1279,4 +1280,21 @@ public class CPPSelectionTestsNoIndexer extends BaseSelectionTests { IBinding targetBinding = ((IASTName) target).resolveBinding(); assertInstance(targetBinding, ICPPConstructor.class); } + + // template + // struct waldo; + // + // template + // struct waldo {}; + public void testNavigationToTemplateForwardDecl_483048() throws Exception { + String code = getAboveComment(); + IFile file = importFile("testBug483048.cpp", code); + + int offset = code.indexOf("waldo {}"); + IASTNode target = testF3(file, offset); + + // Check that the result of the navigation is the forward declaration, + // not the definition. + assertInstance(target.getParent(), IASTElaboratedTypeSpecifier.class); + } } 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 e0de116e01c..e809b368d83 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 @@ -64,6 +64,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPAliasTemplateInstance; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization; @@ -267,9 +268,12 @@ class OpenDeclarationsJob extends Job implements ASTRunnable { if (candidateBindings.length != 0) { bindings = candidateBindings; } - } else if (kind == NameKind.DEFINITION && b instanceof IType) { + } else if (kind == NameKind.DEFINITION && b instanceof IType && !(b instanceof ICPPClassTemplate)) { // Don't navigate away from a type definition. // Select the name at the current location instead. + // However, for a class template, it's useful to navigate to + // a forward declaration, as it may contain definitions of + // default arguments, while the definition may not. navigateToName(sourceName); return Status.OK_STATUS; }