Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathan Ridge2014-12-21 09:38:46 +0000
committerNathan Ridge2016-10-19 15:24:43 +0000
commitfbccef3ff12c3d394e30a8bd1f1198512cff3161 (patch)
tree6822b3b4ffe99f3dec6cf9e244c3d9bfae590e35
parented655597538879e68ea4c25f576d8b6e1787e72c (diff)
downloadorg.eclipse.cdt-fbccef3ff12c3d394e30a8bd1f1198512cff3161.tar.gz
org.eclipse.cdt-fbccef3ff12c3d394e30a8bd1f1198512cff3161.tar.xz
org.eclipse.cdt-fbccef3ff12c3d394e30a8bd1f1198512cff3161.zip
Bug 402498 - Apply declaredBefore() filtering to index bindings
Change-Id: I3086c35cf294970d4adbb65dd6aa3708710f9c02 Signed-off-by: Nathan Ridge <zeratul976@hotmail.com>
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java25
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java19
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java137
-rw-r--r--core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/search/BasicSearchTest.java7
-rw-r--r--core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CPPSelectionTestsIndexer.java2
-rw-r--r--core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/includes/BindingClassifier.java10
-rw-r--r--qt/org.eclipse.cdt.qt.ui.tests/src/org/eclipse/cdt/qt/tests/QmlRegistrationTests.java1
7 files changed, 144 insertions, 57 deletions
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 78245d1ce22..a114b7c5e50 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
@@ -8908,6 +8908,29 @@ public class AST2TemplateTests extends AST2TestBase {
assertFalse(x.getType().isSameType(CommonCPPTypes.int_));
}
+ // struct Cat { void meow(); };
+ // struct Dog { void woof(); };
+ //
+ // template <typename T>
+ // Dog bar(T);
+ //
+ // template <typename T>
+ // 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 <typename T>
@@ -8937,7 +8960,7 @@ public class AST2TemplateTests extends AST2TestBase {
public void testUnqualifiedFunctionCallInTemplate_458316b() throws Exception {
parseAndCheckBindings();
}
-
+
// template <typename>
// struct no_type {};
//
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 db5016d71d1..a39d330f162 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
@@ -2995,4 +2995,23 @@ public class IndexCPPTemplateResolutionTest extends IndexBindingResolutionTestBa
public void testBracedInitList_490475() throws Exception {
checkBindings();
}
+
+ // struct Cat { void meow(); };
+ // struct Dog { void woof(); };
+
+ // template <typename T>
+ // Dog bar(T);
+ //
+ // template <typename T>
+ // 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();
+ }
}
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 abdd2fcdc88..c43def304cd 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
@@ -279,6 +279,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<Boolean> fAllowPromiscuousBindingResolution = new ThreadLocal<Boolean>() {
+ @Override
+ protected Boolean initialValue() {
+ return false;
+ }
+ };
static protected IBinding resolveBinding(IASTName name) {
if (traceBindingResolution) {
@@ -1958,63 +1969,76 @@ public class CPPSemantics {
}
}
- 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();
- }
- 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();
- } 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();
- }
- } 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();
- } 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();
- } 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();
- } else {
- pointOfDecl = nd.getOffset() + nd.getLength();
- }
+ if (pointOfDecl < 0) {
+ if (nd != null) {
+ pointOfDecl = getPointOfDeclaration(nd);
+ } else if (obj instanceof IIndexBinding && !fAllowPromiscuousBindingResolution.get()) {
+ IIndexBinding indexBinding = ((IIndexBinding) obj);
+ if (indexBinding instanceof ICPPMethod && ((ICPPMethod) indexBinding).isImplicit()) {
+ return true;
+ }
+ IASTTranslationUnit tu = node.getTranslationUnit();
+ IIndexFileSet indexFileSet = tu.getIndexFileSet();
+ return (indexFileSet != null && indexFileSet.containsDeclaration(indexBinding));
+ }
}
return (pointOfDecl < pointOfRef);
}
+ 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() - 1;
+ else
+ return ((ASTNode) dtor).getOffset() + ((ASTNode) dtor).getLength();
+ } 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();
+ } else {
+ return nd.getOffset() + nd.getLength();
+ }
+ } else if (prop == ICPPASTUsingDeclaration.NAME) {
+ nd = (ASTNode) nd.getParent();
+ return nd.getOffset();
+ } else if (prop == ICPPASTNamespaceAlias.ALIAS_NAME) {
+ nd = (ASTNode) nd.getParent();
+ return nd.getOffset() + nd.getLength();
+ } 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();
+ } 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();
+ } else {
+ return nd.getOffset() + nd.getLength();
+ }
+ }
+
private static boolean acceptDeclaredAfter(ICPPInternalBinding cpp) {
try {
if (cpp instanceof ICPPNamespace || cpp instanceof ICPPFunction || cpp instanceof ICPPVariable) {
@@ -4222,4 +4246,11 @@ public class CPPSemantics {
return binding;
}
+
+ public static void enablePromiscuousBindingResolution() {
+ fAllowPromiscuousBindingResolution.set(true);
+ }
+ public static void disablePromiscuousBindingResolution() {
+ fAllowPromiscuousBindingResolution.set(false);
+ }
}
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 5db08148128..4c1558b73b5 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
@@ -315,6 +315,7 @@ public class BasicSearchTest extends BaseUITestCase {
// void foo() {}
+ // #include "header.h"
// void bar() {
// foo();
// }
@@ -333,6 +334,7 @@ public class BasicSearchTest extends BaseUITestCase {
// void foo() {}
+ // #include "header.h"
// void bar() {foo();foo();foo();}
public void testNewResultsOnSearchAgainB() throws Exception {
CSearchQuery query= makeProjectQuery("foo");
@@ -340,7 +342,7 @@ public class BasicSearchTest extends BaseUITestCase {
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);
@@ -350,7 +352,7 @@ public class BasicSearchTest extends BaseUITestCase {
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);
@@ -362,6 +364,7 @@ public class BasicSearchTest extends BaseUITestCase {
// template<typename T> void f(T) {};
// template<typename T> void f(T*) {};
+ // #include "header.h"
// void a() {
// CT<int>* r1;
// CT<char>* 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 c735035f10a..c3d6ec0a5f2 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<char> a;
// a.assign("aaa");
@@ -1175,6 +1176,7 @@ public class CPPSelectionTestsIndexer extends BaseSelectionTestsIndexer {
// T operator+(int);
// };
+ // #include "test.h"
// void main() {
// C<char> a;
// a + 2;
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 16aa93e922e..49fb6bb63ee 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
@@ -958,7 +958,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/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()

Back to the top