mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-25 18:05:33 +02:00
Bug 258704.
This commit is contained in:
parent
48082ac842
commit
84903db3a6
4 changed files with 124 additions and 75 deletions
|
@ -1907,7 +1907,7 @@ public class IndexBugsTests extends BaseTestCase {
|
|||
// a.i = 0;
|
||||
// a.j = 0;
|
||||
// }
|
||||
public void _testDisambiguationByReachability_268704_1() throws Exception {
|
||||
public void testDisambiguationByReachability_268704_1() throws Exception {
|
||||
waitForIndexer();
|
||||
|
||||
String[] testData = getContentsForTest(4);
|
||||
|
@ -1948,7 +1948,7 @@ public class IndexBugsTests extends BaseTestCase {
|
|||
|
||||
// #include "b.h"
|
||||
// int i = e;
|
||||
public void _testDisambiguationByReachability_268704_2() throws Exception {
|
||||
public void testDisambiguationByReachability_268704_2() throws Exception {
|
||||
waitForIndexer();
|
||||
|
||||
String[] testData = getContentsForTest(4);
|
||||
|
@ -1972,45 +1972,4 @@ public class IndexBugsTests extends BaseTestCase {
|
|||
index.releaseReadLock();
|
||||
}
|
||||
}
|
||||
|
||||
// // a.h
|
||||
// namespace ns { namespace ns2 {
|
||||
// enum E { e = 1 };
|
||||
// }}
|
||||
// using namespace ns::ns2;
|
||||
|
||||
// #include "a.h"
|
||||
// E i = e;
|
||||
|
||||
// // b.h
|
||||
// enum E { e = 2 };
|
||||
|
||||
// #include "b.h"
|
||||
// E i = e;
|
||||
public void _testDisambiguationByReachability_268704_3() throws Exception {
|
||||
waitForIndexer();
|
||||
|
||||
String[] testData = getContentsForTest(4);
|
||||
TestSourceReader.createFile(fCProject.getProject(), "a.h", testData[0]);
|
||||
IFile a = TestSourceReader.createFile(fCProject.getProject(), "a.cpp", testData[1]);
|
||||
TestSourceReader.createFile(fCProject.getProject(), "b.h", testData[2]);
|
||||
IFile b = TestSourceReader.createFile(fCProject.getProject(), "b.cpp", testData[3]);
|
||||
final IIndexManager indexManager = CCorePlugin.getIndexManager();
|
||||
indexManager.reindex(fCProject);
|
||||
waitForIndexer();
|
||||
IIndex index= indexManager.getIndex(fCProject);
|
||||
index.acquireReadLock();
|
||||
try {
|
||||
BindingAssertionHelper aHelper = new BindingAssertionHelper(a, testData[1], index);
|
||||
aHelper.assertNonProblem("E i", 1, IEnumeration.class);
|
||||
IEnumerator e1 = aHelper.assertNonProblem("e;", 1, IEnumerator.class);
|
||||
assertEquals(1, e1.getValue().numericalValue().longValue());
|
||||
BindingAssertionHelper bHelper = new BindingAssertionHelper(b, testData[3], index);
|
||||
aHelper.assertNonProblem("E i", 1, IEnumeration.class);
|
||||
IEnumerator e2 = bHelper.assertNonProblem("e;", 1, IEnumerator.class);
|
||||
assertEquals(2, e2.getValue().numericalValue().longValue());
|
||||
} finally {
|
||||
index.releaseReadLock();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@
|
|||
*
|
||||
* Contributors:
|
||||
* Markus Schorn - initial API and implementation
|
||||
* Sergey Prigogin (Google)
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.core.index;
|
||||
|
||||
|
@ -29,6 +30,13 @@ public interface IIndexFileSet {
|
|||
*/
|
||||
boolean contains(IIndexFile file) throws CoreException;
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if this file set contains a declaration or definition of
|
||||
* the given binding.
|
||||
* @since 5.1
|
||||
*/
|
||||
boolean containsDeclaration(IIndexBinding binding);
|
||||
|
||||
/**
|
||||
* Returns an array of bindings where all local bindings that are not part of this file-set
|
||||
* have been removed.
|
||||
|
|
|
@ -1843,37 +1843,30 @@ public class CPPSemantics {
|
|||
if (type == null) {
|
||||
type = temp;
|
||||
} else if (type != temp) {
|
||||
boolean i1= isFromIndex(type);
|
||||
boolean i2= isFromIndex(temp);
|
||||
if (i1 != i2) {
|
||||
// prefer non-index bindings
|
||||
if (i1)
|
||||
type= temp;
|
||||
} else {
|
||||
if (((IType)type).isSameType((IType) temp)) {
|
||||
int c = compareByRelevance(data, type, temp);
|
||||
if (c < 0) {
|
||||
type= temp;
|
||||
} else if (c == 0) {
|
||||
if (((IType) type).isSameType((IType) temp)) {
|
||||
if (type instanceof ITypedef && !(temp instanceof ITypedef)) {
|
||||
// prefer non-typedefs
|
||||
// Between same types prefer non-typedef.
|
||||
type= temp;
|
||||
}
|
||||
} else {
|
||||
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (obj == null) {
|
||||
obj = temp;
|
||||
} else if (obj == temp) {
|
||||
//ok, delegates are synonyms
|
||||
// Ok, delegates are synonyms.
|
||||
} else {
|
||||
// ignore index stuff in case we have bindings from the ast
|
||||
boolean ibobj= isFromIndex(obj);
|
||||
boolean ibtemp= isFromIndex(temp);
|
||||
// blame it on the index
|
||||
if (ibobj != ibtemp) {
|
||||
if (ibobj)
|
||||
obj= temp;
|
||||
} else {
|
||||
int c = compareByRelevance(data, obj, temp);
|
||||
if (c < 0) {
|
||||
obj= temp;
|
||||
} else if (c == 0) {
|
||||
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP);
|
||||
}
|
||||
}
|
||||
|
@ -1917,6 +1910,36 @@ public class CPPSemantics {
|
|||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two bindings for relevance in the context of an AST. AST bindings are
|
||||
* considered more relevant than index ones since the index may be out of date,
|
||||
* built for a different configuration, etc. Index bindings reachable through includes
|
||||
* are more relevant than unreachable ones.
|
||||
* @param ast
|
||||
* @param b1
|
||||
* @param b2
|
||||
* @return 1 if binding <code>b1</code> is more relevant than <code>b2</code>; 0 if
|
||||
* the two bindings have the same relevance; -1 if <code>b1</code> is less relevant than
|
||||
* <code>b2</code>.
|
||||
*/
|
||||
private static int compareByRelevance(LookupData data, IBinding b1, IBinding b2) {
|
||||
boolean b1FromIndex= isFromIndex(b1);
|
||||
boolean b2FromIndex= isFromIndex(b2);
|
||||
if (b1FromIndex != b2FromIndex) {
|
||||
return !b1FromIndex ? 1 : -1;
|
||||
} else if (b1FromIndex) {
|
||||
// Both are from index.
|
||||
if (data.tu != null) {
|
||||
boolean b1Reachable= isReachableFromAst(data.tu, b1);
|
||||
boolean b2Reachable= isReachableFromAst(data.tu, b2);
|
||||
if (b1Reachable != b2Reachable) {
|
||||
return b1Reachable ? 1 : -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static boolean isFromIndex(IBinding binding) {
|
||||
if (binding instanceof IIndexBinding) {
|
||||
return true;
|
||||
|
@ -1926,7 +1949,32 @@ public class CPPSemantics {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if a binding belongs to an AST or is reachable from it through includes.
|
||||
* @param ast
|
||||
* @param binding
|
||||
* @return <code>true</code> if the <code>binding</code> is reachable from <code>ast</code>.
|
||||
*/
|
||||
private static boolean isReachableFromAst(IASTTranslationUnit ast, IBinding binding) {
|
||||
IIndexBinding indexBinding = null;
|
||||
if (binding instanceof IIndexBinding) {
|
||||
indexBinding = (IIndexBinding) binding;
|
||||
}
|
||||
if (binding instanceof ICPPSpecialization) {
|
||||
binding = ((ICPPSpecialization) binding).getSpecializedBinding();
|
||||
if (binding instanceof IIndexBinding) {
|
||||
indexBinding = (IIndexBinding) binding;
|
||||
}
|
||||
}
|
||||
if (indexBinding != null) {
|
||||
IIndexFileSet indexFileSet = ast.getIndexFileSet();
|
||||
return indexFileSet != null && indexFileSet.containsDeclaration(indexBinding);
|
||||
} else {
|
||||
return ast.getDeclarationsInAST(binding).length != 0;
|
||||
}
|
||||
}
|
||||
|
||||
static private void reduceToViable(LookupData data, IBinding[] functions) throws DOMException {
|
||||
if (functions == null || functions.length == 0)
|
||||
return;
|
||||
|
@ -2142,14 +2190,19 @@ public class CPPSemantics {
|
|||
}
|
||||
}
|
||||
|
||||
// if we are ambiguous at this point prefer non-index bindings
|
||||
// Ff we are ambiguous at this point, prefer a non-index binding or reachable index one.
|
||||
if (hasBetter == hasWorse) {
|
||||
final boolean bestIsFromIndex= isFromIndex(bestFn);
|
||||
final boolean currIsFromIndex= isFromIndex(fn);
|
||||
if (bestIsFromIndex != currIsFromIndex) {
|
||||
hasBetter= bestIsFromIndex;
|
||||
hasWorse= currIsFromIndex;
|
||||
int c = compareByRelevance(data, bestFn, fn);
|
||||
if (c != 0) {
|
||||
hasBetter = (c < 0);
|
||||
hasWorse = !hasBetter;
|
||||
}
|
||||
// final boolean bestIsFromIndex= isFromIndex(bestFn);
|
||||
// final boolean currIsFromIndex= isFromIndex(fn);
|
||||
// if (bestIsFromIndex != currIsFromIndex) {
|
||||
// hasBetter= bestIsFromIndex;
|
||||
// hasWorse= currIsFromIndex;
|
||||
// }
|
||||
}
|
||||
|
||||
// If function has a parameter match that is better than the current best,
|
||||
|
@ -2356,14 +2409,21 @@ public class CPPSemantics {
|
|||
ft = e.getProblem();
|
||||
}
|
||||
if (type.isSameType(ft)) {
|
||||
if (result != null) {
|
||||
boolean fromIndex= isFromIndex(fn);
|
||||
if (isFromIndex(result) == fromIndex)
|
||||
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP);
|
||||
if (!fromIndex)
|
||||
if (result == null) {
|
||||
result = fn;
|
||||
} else {
|
||||
int c = compareByRelevance(data, result, fn);
|
||||
if (c < 0) {
|
||||
result= fn;
|
||||
} else if (c == 0) {
|
||||
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP);
|
||||
}
|
||||
// boolean fromIndex= isFromIndex(fn);
|
||||
// if (isFromIndex(result) == fromIndex)
|
||||
// return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP);
|
||||
// if (!fromIndex)
|
||||
// result= fn;
|
||||
}
|
||||
result = fn;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,9 +12,11 @@ package org.eclipse.cdt.internal.core.index;
|
|||
|
||||
import java.util.BitSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.index.IIndexBinding;
|
||||
import org.eclipse.cdt.core.index.IIndexFile;
|
||||
import org.eclipse.cdt.core.index.IIndexFileSet;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
|
@ -37,6 +39,26 @@ public class IndexFileSet implements IIndexFileSet {
|
|||
subSet.add(fragFile);
|
||||
}
|
||||
|
||||
public boolean containsDeclaration(IIndexBinding binding) {
|
||||
for (Map.Entry<IIndexFragment, IIndexFragmentFileSet> entry : fSubSets.entrySet()) {
|
||||
try {
|
||||
IIndexFragmentName[] names =
|
||||
entry.getKey().findNames(binding, IIndexFragment.FIND_DECLARATIONS_DEFINITIONS);
|
||||
for (IIndexFragmentName name : names) {
|
||||
try {
|
||||
if (entry.getValue().contains((IIndexFragmentFile) name.getFile())) {
|
||||
return true;
|
||||
}
|
||||
} catch (CoreException e) {
|
||||
CCorePlugin.log(e);
|
||||
}
|
||||
}
|
||||
} catch (CoreException e) {
|
||||
CCorePlugin.log(e);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public IBinding[] filterFileLocalBindings(IBinding[] bindings) {
|
||||
if (bindings == null || bindings.length == 0) {
|
||||
|
|
Loading…
Add table
Reference in a new issue