1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-25 18:05:33 +02:00

Bug 258704.

This commit is contained in:
Sergey Prigogin 2009-03-23 20:11:14 +00:00
parent 48082ac842
commit 84903db3a6
4 changed files with 124 additions and 75 deletions

View file

@ -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();
}
}
}

View file

@ -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.

View file

@ -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;
}
}

View file

@ -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) {