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 69fa6f16fe9..207acf84227 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 @@ -9062,6 +9062,29 @@ public class AST2TemplateTests extends AST2TestBase { assertFalse(x.getType().isSameType(CommonCPPTypes.int_)); } + // struct Cat { void meow(); }; + // struct Dog { void woof(); }; + // + // template + // Dog bar(T); + // + // template + // auto foo(T t) -> decltype(bar(t)); + // + // namespace N { + // class A {}; + // } + // + // Cat bar(N::A); + // + // int main() { + // auto x = foo(N::A()); + // x.woof(); + // } + public void testUnqualifiedFunctionCallInTemplate_402498d() throws Exception { + parseAndCheckBindings(); + } + // void bar(); // // template diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java index 8602fa3d843..e15574d2c24 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java @@ -3035,4 +3035,37 @@ public class IndexCPPTemplateResolutionTest extends IndexBindingResolutionTestBa public void testBracedInitList_490475() throws Exception { checkBindings(); } + + // struct Cat { void meow(); }; + // struct Dog { void woof(); }; + + // template + // Dog bar(T); + // + // template + // auto foo(T t) -> decltype(bar(t)); + // + // Cat bar(int); + // + // int main() { + // auto x = foo(0); + // x.woof(); + // } + public void testUnqualifiedFunctionCallInTemplate_402498() throws Exception { + checkBindings(); + } + + // template struct traits; + + // template struct M; + // + // template + // struct traits> { + // typedef T type; + // }; + // + // typedef traits>::type waldo; // ERROR + public void testRegression_402498() throws Exception { + checkBindings(); + } } 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 169e1ad4366..cb49e16ea86 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 @@ -280,6 +280,17 @@ public class CPPSemantics { // "a" => { null, "a", null } // ":: i" => { "::", "i", null } private static final Pattern QUALNAME_REGEX = Pattern.compile("^\\s*(::)?\\s*([^\\s:]+)\\s*(?:::(.*))?$"); //$NON-NLS-1$ + + // This flag controls whether name lookup is allowed to find bindings in headers + // that are not reachable via includes from the file containing the name. + // Generally this is not allowed, but certain consumers, such as IncludeOrganizer, + // need it (since the whole point of IncludeOrganizer is to find missing headers). + private static final ThreadLocal fAllowPromiscuousBindingResolution = new ThreadLocal() { + @Override + protected Boolean initialValue() { + return false; + } + }; static protected IBinding resolveBinding(IASTName name) { if (traceBindingResolution) { @@ -1931,14 +1942,15 @@ public class CPPSemantics { if (node == null) return true; - final int pointOfRef= ((ASTNode) node).getOffset(); + // The pointOfRef and pointOfDecl variables contain node offsets scaled by a factor of two. + // This is done to distinguish between left and right points for the same offset. + final int pointOfRef= ((ASTNode) node).getOffset() * 2; ASTNode nd = null; if (obj instanceof ICPPSpecialization) { obj = ((ICPPSpecialization) obj).getSpecializedBinding(); } int pointOfDecl= -1; - boolean pointOfDeclIsEndOffset = false; if (obj instanceof ICPPInternalBinding) { ICPPInternalBinding cpp = (ICPPInternalBinding) obj; IASTNode[] n = cpp.getDeclarations(); @@ -1962,72 +1974,84 @@ public class CPPSemantics { if (obj instanceof ASTNode) { nd = (ASTNode) obj; } else if (obj instanceof ICPPUsingDirective) { - pointOfDecl= ((ICPPUsingDirective) obj).getPointOfDeclaration(); + pointOfDecl= ((ICPPUsingDirective) obj).getPointOfDeclaration() * 2; } } - if (pointOfDecl < 0 && nd != null) { - ASTNodeProperty prop = nd.getPropertyInParent(); - if (prop == IASTDeclarator.DECLARATOR_NAME || nd instanceof IASTDeclarator) { - // Point of declaration for a name is immediately after its complete declarator - // and before its initializer. - IASTDeclarator dtor = (IASTDeclarator)((nd instanceof IASTDeclarator) ? nd : nd.getParent()); - while (dtor.getParent() instanceof IASTDeclarator) { - dtor = (IASTDeclarator) dtor.getParent(); + if (pointOfDecl < 0) { + if (nd != null) { + pointOfDecl = getPointOfDeclaration(nd); + } else if (obj instanceof IIndexBinding && !isUsingPromiscuousBindingResolution()) { + IIndexBinding indexBinding = (IIndexBinding) obj; + if (indexBinding instanceof ICPPMethod && ((ICPPMethod) indexBinding).isImplicit()) { + return true; } - IASTInitializer init = dtor.getInitializer(); - // [basic.scope.pdecl]/p9: The point of declaration for a template parameter - // is immediately after its complete template-parameter. - // Note: can't just check "dtor.getParent() instanceof ICPPASTTemplateParameter" - // because function parameter declarations implement ICPPASTTemplateParameter too. - boolean isTemplateParameter = dtor.getParent() instanceof ICPPASTTemplateParameter - && dtor.getParent().getPropertyInParent() == ICPPASTTemplateDeclaration.PARAMETER; - if (init != null && !isTemplateParameter) { - pointOfDecl = ((ASTNode) init).getOffset() - 1; - } else { - pointOfDecl = ((ASTNode) dtor).getOffset() + ((ASTNode) dtor).getLength(); - pointOfDeclIsEndOffset = true; - } - } else if (prop == IASTEnumerator.ENUMERATOR_NAME) { - // Point of declaration for an enumerator is immediately after it - // enumerator-definition - IASTEnumerator enumtor = (IASTEnumerator) nd.getParent(); - if (enumtor.getValue() != null) { - ASTNode exp = (ASTNode) enumtor.getValue(); - pointOfDecl = exp.getOffset() + exp.getLength(); - } else { - pointOfDecl = nd.getOffset() + nd.getLength(); - } - pointOfDeclIsEndOffset = true; - } else if (prop == ICPPASTUsingDeclaration.NAME) { - nd = (ASTNode) nd.getParent(); - pointOfDecl = nd.getOffset(); - } else if (prop == ICPPASTNamespaceAlias.ALIAS_NAME) { - nd = (ASTNode) nd.getParent(); - pointOfDecl = nd.getOffset() + nd.getLength(); - pointOfDeclIsEndOffset = true; - } else if (prop == ICPPASTAliasDeclaration.ALIAS_NAME) { - // [basic.scope.pdecl]/p3: The point of declaration of an alias or alias template - // immediately follows the type-id to which the alias refers. - ASTNode targetType = (ASTNode) ((ICPPASTAliasDeclaration) nd.getParent()).getMappingTypeId(); - pointOfDecl = targetType.getOffset() + targetType.getLength(); - pointOfDeclIsEndOffset = true; - } else if (prop == ICPPASTSimpleTypeTemplateParameter.PARAMETER_NAME - || prop == ICPPASTTemplatedTypeTemplateParameter.PARAMETER_NAME) { - // [basic.scope.pdecl]/p9: The point of declaration for a template parameter - // is immediately after its complete template-parameter. - // Type and template template parameters are handled here; - // non-type template parameters are handled in the DECLARATOR_NAME - // case above. - nd = (ASTNode) nd.getParent(); - pointOfDecl = nd.getOffset() + nd.getLength(); - pointOfDeclIsEndOffset = true; - } else { - pointOfDecl = nd.getOffset() + nd.getLength(); - pointOfDeclIsEndOffset = true; + IASTTranslationUnit tu = node.getTranslationUnit(); + IIndexFileSet indexFileSet = tu.getIndexFileSet(); + return (indexFileSet != null && indexFileSet.containsDeclaration(indexBinding)); } } - return pointOfDecl < pointOfRef || (pointOfDecl == pointOfRef && pointOfDeclIsEndOffset); + return pointOfDecl < pointOfRef; + } + + /** + * Returns the point of declaration for the given AST node. The point of declaration is a node offset + * scaled by a factor of two. This is done to distinguish between left and right points for the offset. + */ + private static int getPointOfDeclaration(ASTNode nd) { + ASTNodeProperty prop = nd.getPropertyInParent(); + if (prop == IASTDeclarator.DECLARATOR_NAME || nd instanceof IASTDeclarator) { + // Point of declaration for a name is immediately after its complete declarator + // and before its initializer. + IASTDeclarator dtor = (IASTDeclarator)((nd instanceof IASTDeclarator) ? nd : nd.getParent()); + while (dtor.getParent() instanceof IASTDeclarator) { + dtor = (IASTDeclarator) dtor.getParent(); + } + IASTInitializer init = dtor.getInitializer(); + // [basic.scope.pdecl]/p9: The point of declaration for a template parameter + // is immediately after its complete template-parameter. + // Note: can't just check "dtor.getParent() instanceof ICPPASTTemplateParameter" + // because function parameter declarations implement ICPPASTTemplateParameter too. + boolean isTemplateParameter = dtor.getParent() instanceof ICPPASTTemplateParameter + && dtor.getParent().getPropertyInParent() == ICPPASTTemplateDeclaration.PARAMETER; + if (init != null && !isTemplateParameter) { + return ((ASTNode) init).getOffset() * 2 - 1; + } else { + return (((ASTNode) dtor).getOffset() + ((ASTNode) dtor).getLength()) * 2 - 1; + } + } else if (prop == IASTEnumerator.ENUMERATOR_NAME) { + // Point of declaration for an enumerator is immediately after it + // enumerator-definition + IASTEnumerator enumtor = (IASTEnumerator) nd.getParent(); + if (enumtor.getValue() != null) { + ASTNode exp = (ASTNode) enumtor.getValue(); + return (exp.getOffset() + exp.getLength()) * 2 - 1; + } else { + return (nd.getOffset() + nd.getLength()) * 2 - 1; + } + } else if (prop == ICPPASTUsingDeclaration.NAME) { + nd = (ASTNode) nd.getParent(); + return nd.getOffset() * 2; + } else if (prop == ICPPASTNamespaceAlias.ALIAS_NAME) { + nd = (ASTNode) nd.getParent(); + return (nd.getOffset() + nd.getLength()) * 2 - 1; + } else if (prop == ICPPASTAliasDeclaration.ALIAS_NAME) { + // [basic.scope.pdecl]/p3: The point of declaration of an alias or alias template + // immediately follows the type-id to which the alias refers. + ASTNode targetType = (ASTNode) ((ICPPASTAliasDeclaration) nd.getParent()).getMappingTypeId(); + return (targetType.getOffset() + targetType.getLength()) * 2 - 1; + } else if (prop == ICPPASTSimpleTypeTemplateParameter.PARAMETER_NAME + || prop == ICPPASTTemplatedTypeTemplateParameter.PARAMETER_NAME) { + // [basic.scope.pdecl]/p9: The point of declaration for a template parameter + // is immediately after its complete template-parameter. + // Type and template template parameters are handled here; + // non-type template parameters are handled in the DECLARATOR_NAME + // case above. + nd = (ASTNode) nd.getParent(); + return (nd.getOffset() + nd.getLength()) * 2 - 1; + } else { + return (nd.getOffset() + nd.getLength()) * 2 - 1; + } } private static boolean acceptDeclaredAfter(ICPPInternalBinding cpp) { @@ -4232,4 +4256,16 @@ public class CPPSemantics { return binding; } + + public static void enablePromiscuousBindingResolution() { + fAllowPromiscuousBindingResolution.set(true); + } + + public static void disablePromiscuousBindingResolution() { + fAllowPromiscuousBindingResolution.set(false); + } + + public static boolean isUsingPromiscuousBindingResolution() { + return fAllowPromiscuousBindingResolution.get(); + } } diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/search/BasicSearchTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/search/BasicSearchTest.java index c99a0039a06..b320516e23b 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/search/BasicSearchTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/search/BasicSearchTest.java @@ -279,6 +279,7 @@ public class BasicSearchTest extends SearchTestBase { // void foo() {} + // #include "header.h" // void bar() { // foo(); // } @@ -297,6 +298,7 @@ public class BasicSearchTest extends SearchTestBase { // void foo() {} + // #include "header.h" // void bar() {foo();foo();foo();} public void testNewResultsOnSearchAgainB() throws Exception { CSearchQuery query= makeProjectQuery("foo"); @@ -304,7 +306,7 @@ public class BasicSearchTest extends SearchTestBase { assertOccurrences(query, 4); // whitespace s.t. new match offset is same as older - String newContent= "void bar() { foo(); }"; + String newContent= "#include \"header.h\"\nvoid bar() { foo(); }"; IFile file = fCProject.getProject().getFile(new Path("references.cpp")); file.setContents(new ByteArrayInputStream(newContent.getBytes()), IResource.FORCE, npm()); runEventQueue(1000); @@ -314,7 +316,7 @@ public class BasicSearchTest extends SearchTestBase { assertOccurrences(query, 2); - String newContent2= "void bar() {foo(); foo();}"; + String newContent2= "#include \"header.h\"\nvoid bar() {foo(); foo();}"; file.setContents(new ByteArrayInputStream(newContent2.getBytes()), IResource.FORCE, npm()); waitForIndexer(fCProject); @@ -326,6 +328,7 @@ public class BasicSearchTest extends SearchTestBase { // template void f(T) {}; // template void f(T*) {}; + // #include "header.h" // void a() { // CT* r1; // CT* r2; diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CPPSelectionTestsIndexer.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CPPSelectionTestsIndexer.java index 57d38c5d0e0..cf2e1c2b2c1 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CPPSelectionTestsIndexer.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CPPSelectionTestsIndexer.java @@ -184,6 +184,7 @@ public class CPPSelectionTestsIndexer extends BaseSelectionTestsIndexer { // public: void assign(const T* s) {} // }; + // #include "testTemplateClassMethod.h" // void main() { // C a; // a.assign("aaa"); @@ -1175,6 +1176,7 @@ public class CPPSelectionTestsIndexer extends BaseSelectionTestsIndexer { // T operator+(int); // }; + // #include "test.h" // void main() { // C a; // a + 2; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/AddIncludeAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/AddIncludeAction.java index 612267651ae..447d24e3548 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/AddIncludeAction.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/AddIncludeAction.java @@ -13,8 +13,10 @@ package org.eclipse.cdt.internal.ui.editor; import java.util.Collection; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; @@ -38,10 +40,10 @@ import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.index.IIndexManager; -import org.eclipse.cdt.core.model.ILanguage; import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.ui.CUIPlugin; -import org.eclipse.cdt.ui.text.SharedASTJob; + +import org.eclipse.cdt.internal.core.model.ASTCache; import org.eclipse.cdt.internal.ui.BusyCursorJobRunner; import org.eclipse.cdt.internal.ui.ICHelpContextIds; @@ -100,25 +102,32 @@ public class AddIncludeAction extends TextEditorAction { } final MultiTextEdit[] holder = new MultiTextEdit[1]; - SharedASTJob job = new SharedASTJob(CEditorMessages.AddInclude_action, tu) { + // We can't use SharedASTJob because IncludeCreator needs to disable promiscuous + // binding resolution, and you can't mix promiscuous and non-promiscuous binding + // resolution in the same AST. + Job job = new Job(CEditorMessages.AddInclude_action) { @Override - public IStatus runOnAST(ILanguage lang, IASTTranslationUnit ast) throws CoreException { - if (ast == null) { - return CUIPlugin.createErrorStatus( - NLS.bind(CEditorMessages.AddInclude_ast_not_available, tu.getPath().toOSString())); - } - - IIndex index= CCorePlugin.getIndexManager().getIndex(tu.getCProject(), - IIndexManager.ADD_DEPENDENCIES | IIndexManager.ADD_EXTENSION_FRAGMENTS_ADD_IMPORT); + public IStatus run(IProgressMonitor monitor) { try { - index.acquireReadLock(); - IncludeCreator creator = new IncludeCreator(tu, index, fAmbiguityResolver); - holder[0] = creator.createInclude(ast, (ITextSelection) selection); - return Status.OK_STATUS; - } catch (InterruptedException e) { - return Status.CANCEL_STATUS; - } finally { - index.releaseReadLock(); + IIndex index= CCorePlugin.getIndexManager().getIndex(tu.getCProject(), + IIndexManager.ADD_DEPENDENCIES | IIndexManager.ADD_EXTENSION_FRAGMENTS_ADD_IMPORT); + try { + index.acquireReadLock(); + IASTTranslationUnit ast = tu.getAST(index, ASTCache.PARSE_MODE); + if (ast == null) { + return CUIPlugin.createErrorStatus( + NLS.bind(CEditorMessages.AddInclude_ast_not_available, tu.getPath().toOSString())); + } + IncludeCreator creator = new IncludeCreator(tu, index, fAmbiguityResolver); + holder[0] = creator.createInclude(ast, (ITextSelection) selection); + return Status.OK_STATUS; + } catch (InterruptedException e) { + return Status.CANCEL_STATUS; + } finally { + index.releaseReadLock(); + } + } catch (CoreException e) { + return e.getStatus(); } } }; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/OrganizeIncludesAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/OrganizeIncludesAction.java index 3c0b745926f..7fb44bbae9f 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/OrganizeIncludesAction.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/OrganizeIncludesAction.java @@ -12,8 +12,10 @@ package org.eclipse.cdt.internal.ui.editor; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; @@ -30,10 +32,10 @@ import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.index.IIndexManager; -import org.eclipse.cdt.core.model.ILanguage; import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.ui.CUIPlugin; -import org.eclipse.cdt.ui.text.SharedASTJob; + +import org.eclipse.cdt.internal.core.model.ASTCache; import org.eclipse.cdt.internal.ui.BusyCursorJobRunner; import org.eclipse.cdt.internal.ui.ICHelpContextIds; @@ -67,25 +69,32 @@ public class OrganizeIncludesAction extends TextEditorAction { final IHeaderChooser headerChooser = new InteractiveHeaderChooser( CEditorMessages.OrganizeIncludes_label, editor.getSite().getShell()); final MultiTextEdit[] holder = new MultiTextEdit[1]; - SharedASTJob job = new SharedASTJob(CEditorMessages.OrganizeIncludes_action, tu) { + // We can't use SharedASTJob because IncludeOrganizer needs to disable promiscuous + // binding resolution, and you can't mix promiscuous and non-promiscuous binding + // resolution in the same AST. + Job job = new Job(CEditorMessages.OrganizeIncludes_action) { @Override - public IStatus runOnAST(ILanguage lang, IASTTranslationUnit ast) throws CoreException { - if (ast == null) { - return CUIPlugin.createErrorStatus( - NLS.bind(CEditorMessages.OrganizeIncludes_ast_not_available, tu.getPath().toOSString())); - } - - IIndex index= CCorePlugin.getIndexManager().getIndex(tu.getCProject(), - IIndexManager.ADD_DEPENDENCIES | IIndexManager.ADD_EXTENSION_FRAGMENTS_ADD_IMPORT); + public IStatus run(IProgressMonitor monitor) { try { - index.acquireReadLock(); - IncludeOrganizer organizer = new IncludeOrganizer(tu, index, headerChooser); - holder[0] = organizer.organizeIncludes(ast); - return Status.OK_STATUS; - } catch (InterruptedException e) { - return Status.CANCEL_STATUS; - } finally { - index.releaseReadLock(); + IIndex index= CCorePlugin.getIndexManager().getIndex(tu.getCProject(), + IIndexManager.ADD_DEPENDENCIES | IIndexManager.ADD_EXTENSION_FRAGMENTS_ADD_IMPORT); + try { + index.acquireReadLock(); + IASTTranslationUnit ast = tu.getAST(index, ASTCache.PARSE_MODE); + if (ast == null) { + return CUIPlugin.createErrorStatus( + NLS.bind(CEditorMessages.OrganizeIncludes_ast_not_available, tu.getPath().toOSString())); + } + IncludeOrganizer organizer = new IncludeOrganizer(tu, index, headerChooser); + holder[0] = organizer.organizeIncludes(ast); + return Status.OK_STATUS; + } catch (InterruptedException e) { + return Status.CANCEL_STATUS; + } finally { + index.releaseReadLock(); + } + } catch (CoreException e) { + return e.getStatus(); } } }; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/BindingClassifier.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/BindingClassifier.java index 67f6b5ab358..7e189b61fab 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/BindingClassifier.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/BindingClassifier.java @@ -977,7 +977,15 @@ public class BindingClassifier { if (fAst == null) { fAst = node.getTranslationUnit(); } - node.accept(fBindingCollector); + try { + // Enable promiscuous binding resolution for this AST traversal, + // to allow names to be resolved even if the declarations of their + // target bindings are in a header not reachable via includes. + CPPSemantics.enablePromiscuousBindingResolution(); + node.accept(fBindingCollector); + } finally { + CPPSemantics.disablePromiscuousBindingResolution(); + } } /** diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/IncludeCreator.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/IncludeCreator.java index 0c405abe6c2..3a593cff57a 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/IncludeCreator.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/IncludeCreator.java @@ -77,6 +77,7 @@ import org.eclipse.cdt.ui.IRequiredInclude; import org.eclipse.cdt.ui.text.ICHelpInvocationContext; import org.eclipse.cdt.internal.core.dom.parser.IASTInternalScope; +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; import org.eclipse.cdt.internal.core.dom.rewrite.commenthandler.ASTCommenter; @@ -106,6 +107,16 @@ public class IncludeCreator { public MultiTextEdit createInclude(IASTTranslationUnit ast, ITextSelection selection) throws CoreException { + try { + CPPSemantics.enablePromiscuousBindingResolution(); + return createIncludeImpl(ast, selection); + } finally { + CPPSemantics.disablePromiscuousBindingResolution(); + } + } + + private MultiTextEdit createIncludeImpl(IASTTranslationUnit ast, ITextSelection selection) + throws CoreException { MultiTextEdit rootEdit = new MultiTextEdit(); ITranslationUnit tu = fContext.getTranslationUnit(); IASTNodeSelector selector = ast.getNodeSelector(tu.getLocation().toOSString()); diff --git a/qt/org.eclipse.cdt.qt.ui.tests/src/org/eclipse/cdt/qt/tests/QmlRegistrationTests.java b/qt/org.eclipse.cdt.qt.ui.tests/src/org/eclipse/cdt/qt/tests/QmlRegistrationTests.java index dfc1b2ad34f..975f3abf0df 100644 --- a/qt/org.eclipse.cdt.qt.ui.tests/src/org/eclipse/cdt/qt/tests/QmlRegistrationTests.java +++ b/qt/org.eclipse.cdt.qt.ui.tests/src/org/eclipse/cdt/qt/tests/QmlRegistrationTests.java @@ -92,6 +92,7 @@ public class QmlRegistrationTests extends BaseQtTestCase { } } + // #include "junit-QObject.hh" // class T; // // static void func()