1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-05 23:35:48 +02:00

Bug 278337.

This commit is contained in:
Sergey Prigogin 2009-05-31 01:07:55 +00:00
parent aecdc9e38c
commit 75560d52b8
9 changed files with 240 additions and 141 deletions

View file

@ -48,6 +48,17 @@ public interface IProblemBinding extends IBinding, IScope, IType {
*/
public int getLineNumber();
/**
* Returns bindings that were considered when resolving the node corresponding
* to this problem binding, but rejected for some reason.
* @return an array of candidate bindings.
*
* This method is experimental. Clients calling this method should expect
* possible changes.
* @since 5.1 experimental
*/
public IBinding[] getCandidateBindings();
/*
* Parser Semantic Problems
* All Semantic problems take a char[] as an argument

View file

@ -40,16 +40,26 @@ public class ProblemBinding extends PlatformObject implements IProblemBinding, I
protected final int id;
protected char[] arg;
protected IASTNode node;
private String message = null;
private final String message = null;
private final IBinding[] candidateBindings;
public ProblemBinding(IASTName name, int id) {
this(name, id, null);
this(name, id, null, null);
}
public ProblemBinding(IASTName name, int id, IBinding[] candidateBindings) {
this(name, id, null, candidateBindings);
}
public ProblemBinding(IASTNode node, int id, char[] arg) {
this(node, id, arg, null);
}
public ProblemBinding(IASTNode node, int id, char[] arg, IBinding[] candidateBindings) {
this.id = id;
this.arg = arg;
this.node = node;
this.candidateBindings = candidateBindings;
}
public EScopeKind getKind() {
@ -60,6 +70,10 @@ public class ProblemBinding extends PlatformObject implements IProblemBinding, I
return node;
}
public IBinding[] getCandidateBindings() {
return candidateBindings != null ? candidateBindings : IBinding.EMPTY_BINDING_ARRAY;
}
protected static final String[] errorMessages;
static {
errorMessages = new String[IProblemBinding.SEMANTIC_INVALID_TEMPLATE_ARGUMENTS];
@ -134,6 +148,7 @@ public class ProblemBinding extends PlatformObject implements IProblemBinding, I
return getASTNode();
}
@Override
public Object clone() {
// Don't clone problems

View file

@ -839,7 +839,8 @@ public class CVisitor extends ASTQueries {
try {
IBinding binding = lookup(scope, ((IASTIdExpression) node).getName());
if (binding instanceof IType && !(binding instanceof IProblemBinding) ) {
return new ProblemBinding(node, IProblemBinding.SEMANTIC_INVALID_TYPE, binding.getNameCharArray());
return new ProblemBinding(node, IProblemBinding.SEMANTIC_INVALID_TYPE,
binding.getNameCharArray(), new IBinding[] { binding });
}
return binding;
} catch (DOMException e) {
@ -854,7 +855,8 @@ public class CVisitor extends ASTQueries {
return new ProblemBinding(node, IProblemBinding.SEMANTIC_NAME_NOT_FOUND, name.toCharArray());
if (binding instanceof IType)
return binding;
return new ProblemBinding(node, IProblemBinding.SEMANTIC_INVALID_TYPE, binding.getNameCharArray());
return new ProblemBinding(node, IProblemBinding.SEMANTIC_INVALID_TYPE, binding.getNameCharArray(),
new IBinding[] { binding });
} catch (DOMException e) {
return null;
}
@ -885,10 +887,12 @@ public class CVisitor extends ASTQueries {
}
if (name != null) {
IBinding binding = name.resolveBinding();
if (binding instanceof IType)
if (binding instanceof IType) {
return binding;
else if (binding != null)
return new ProblemBinding(node, IProblemBinding.SEMANTIC_INVALID_TYPE, binding.getNameCharArray());
} else if (binding != null) {
return new ProblemBinding(node, IProblemBinding.SEMANTIC_INVALID_TYPE,
binding.getNameCharArray(), new IBinding[] { binding });
}
return null;
}
} else if (node instanceof ICASTFieldDesignator) {

View file

@ -201,7 +201,8 @@ public class CPPASTFunctionCallExpression extends ASTNode implements
if (owner instanceof ICPPClassType) {
return (ICPPClassType) owner;
}
return new ProblemBinding(this, IProblemBinding.SEMANTIC_BAD_SCOPE, binding.getName().toCharArray());
return new ProblemBinding(this, IProblemBinding.SEMANTIC_BAD_SCOPE,
binding.getName().toCharArray());
} else if (binding instanceof IFunction) {
t = ((IFunction) binding).getType();
} else if (binding instanceof IVariable) {

View file

@ -329,7 +329,8 @@ public class CPPSemantics {
node= node.getParent();
}
if (!ok) {
binding = new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_INVALID_TYPE);
binding = new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_INVALID_TYPE,
data.getFoundBindings());
}
}
}
@ -414,11 +415,13 @@ public class CPPSemantics {
if (parent instanceof IASTTypeId && parent.getPropertyInParent() == ICPPASTTemplateId.TEMPLATE_ID_ARGUMENT) {
if (!(binding instanceof IType)) {
// a type id needs to hold a type
binding = new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_INVALID_TYPE);
binding = new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_INVALID_TYPE,
data.getFoundBindings());
}
// don't create a problem here
} else {
binding = new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_INVALID_TYPE);
binding = new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_INVALID_TYPE,
data.getFoundBindings());
}
}
} else if (namePropertyInParent == IASTIdExpression.ID_NAME) {
@ -430,7 +433,8 @@ public class CPPSemantics {
(binding instanceof ICPPUnknownType || binding instanceof ITypedef || binding instanceof IEnumeration)) {
// constructor or simple-type constructor
} else {
binding= new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_INVALID_TYPE);
binding= new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_INVALID_TYPE,
data.getFoundBindings());
}
}
}
@ -449,10 +453,13 @@ public class CPPSemantics {
}
// If we're still null...
if (binding == null) {
if (name instanceof ICPPASTQualifiedName && data.forFunctionDeclaration())
binding = new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_MEMBER_DECLARATION_NOT_FOUND);
else
binding = new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_NAME_NOT_FOUND);
if (name instanceof ICPPASTQualifiedName && data.forFunctionDeclaration()) {
binding = new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_MEMBER_DECLARATION_NOT_FOUND,
data.getFoundBindings());
} else {
binding = new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_NAME_NOT_FOUND,
data.getFoundBindings());
}
}
return binding;
}
@ -1060,7 +1067,8 @@ public class CPPSemantics {
Object temp = lookupInParents(data, classScope, overallScope, fileSet);
if (!isEmpty) {
inherited = mergePrefixResults(null, inCurrentScope, true);
inherited = mergePrefixResults((CharArrayObjectMap)inherited, (CharArrayObjectMap)temp, true);
inherited = mergePrefixResults((CharArrayObjectMap) inherited,
(CharArrayObjectMap) temp, true);
} else {
inherited= temp;
}
@ -1071,7 +1079,8 @@ public class CPPSemantics {
visitVirtualBaseClasses(data, cls);
}
} else {
data.problem = new ProblemBinding(null, IProblemBinding.SEMANTIC_CIRCULAR_INHERITANCE, cls.getNameCharArray());
data.problem = new ProblemBinding(null, IProblemBinding.SEMANTIC_CIRCULAR_INHERITANCE,
cls.getNameCharArray(), data.getFoundBindings());
return null;
}
}
@ -1085,14 +1094,14 @@ public class CPPSemantics {
for (int j = 0; j < r.length && r[j] != null; j++) {
if (checkForAmbiguity(data, r[j], inherited)) {
data.problem = new ProblemBinding(data.astName,
IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP);
IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, data.getFoundBindings());
return null;
}
}
} else {
if (checkForAmbiguity(data, result, inherited)) {
data.problem = new ProblemBinding(data.astName,
IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP);
IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, data.getFoundBindings());
return null;
}
}
@ -1852,7 +1861,8 @@ public class CPPSemantics {
type= temp;
}
} else {
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP);
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP,
data.getFoundBindings());
}
}
}
@ -1866,7 +1876,8 @@ public class CPPSemantics {
if (c < 0) {
obj= temp;
} else if (c == 0) {
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP);
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP,
data.getFoundBindings());
}
}
}
@ -1874,7 +1885,10 @@ public class CPPSemantics {
if (data.forUsingDeclaration()) {
IBinding[] bindings = null;
if (obj != null) {
if (fns.size() > 0) return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP);
if (fns.size() > 0) {
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP,
data.getFoundBindings());
}
// if (type == null) return obj;
bindings = (IBinding[]) ArrayUtil.append(IBinding.class, bindings, obj);
bindings = (IBinding[]) ArrayUtil.append(IBinding.class, bindings, type);
@ -1898,8 +1912,10 @@ public class CPPSemantics {
int numFns = fns.size();
if (numFns > 0) {
if (obj != null)
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP);
if (obj != null) {
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP,
data.getFoundBindings());
}
return resolveFunction(data, fns.keyArray(IFunction.class), true);
}
@ -2169,13 +2185,15 @@ public class CPPSemantics {
return null;
if (ambiguous || bestFnCost.hasAmbiguousUserDefinedConversion()) {
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP);
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP,
data.getFoundBindings());
}
return bestFnCost.getFunction();
}
private static FunctionCost costForFunctionCall(IFunction fn, IType[] argTypes, IASTExpression[] args, boolean allowUDC, LookupData data) throws DOMException {
private static FunctionCost costForFunctionCall(IFunction fn, IType[] argTypes, IASTExpression[] args,
boolean allowUDC, LookupData data) throws DOMException {
final ICPPFunctionType ftype= (ICPPFunctionType) fn.getType();
if (ftype == null)
return null;
@ -2270,7 +2288,7 @@ public class CPPSemantics {
ICPPASTConversionName astName= (ICPPASTConversionName) data.astName;
IType t= CPPVisitor.createType(astName.getTypeId());
if (t == null) {
return new ProblemBinding(astName, IProblemBinding.SEMANTIC_INVALID_TYPE);
return new ProblemBinding(astName, IProblemBinding.SEMANTIC_INVALID_TYPE, data.getFoundBindings());
}
if (!data.forFunctionDeclaration() || data.forExplicitFunctionSpecialization()) {
CPPTemplates.instantiateConversionTemplates(fns, t);
@ -2293,7 +2311,7 @@ public class CPPSemantics {
}
if (unknown != null)
return unknown;
return new ProblemBinding(astName, IProblemBinding.SEMANTIC_NAME_NOT_FOUND);
return new ProblemBinding(astName, IProblemBinding.SEMANTIC_NAME_NOT_FOUND, data.getFoundBindings());
}
/**
@ -2337,8 +2355,10 @@ public class CPPSemantics {
while (type != null) {
type = getUltimateType(type, false);
if (type == null || !(type instanceof IFunctionType))
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP);
if (type == null || !(type instanceof IFunctionType)) {
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP,
data.getFoundBindings());
}
for (IBinding fn2 : fns) {
IFunction fn = (IFunction) fn2;
@ -2356,13 +2376,9 @@ public class CPPSemantics {
if (c < 0) {
result= fn;
} else if (c == 0) {
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP);
return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP,
data.getFoundBindings());
}
// boolean fromIndex= isFromIndex(fn);
// if (isFromIndex(result) == fromIndex)
// return new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP);
// if (!fromIndex)
// result= fn;
}
}
}
@ -2374,7 +2390,8 @@ public class CPPSemantics {
}
}
return result != null ? result : new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP);
return result != null ? result :
new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, data.getFoundBindings());
}
private static Object getTargetType(LookupData data) {

View file

@ -631,8 +631,8 @@ public class CPPVisitor extends ASTQueries {
ASTInternal.addDeclaration(binding, name);
return binding;
}
} catch (DOMException e1) {
return e1.getProblem();
} catch (DOMException e) {
return e.getProblem();
}
return new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_REDECLARATION);
}

View file

@ -18,30 +18,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression;
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTExpressionList;
import org.eclipse.cdt.core.dom.ast.IASTFieldReference;
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTInitializer;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
import org.eclipse.cdt.core.dom.ast.IPointerType;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.*;
import org.eclipse.cdt.core.dom.ast.c.ICASTFieldDesignator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer;
@ -66,6 +43,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.core.parser.util.ObjectSet;
@ -641,4 +619,23 @@ public class LookupData {
public boolean hasArgumentTypes() {
return functionArgTypes != null || functionArgs != null;
}
public IBinding[] getFoundBindings() {
if (foundItems instanceof Object[]) {
Object[] items = (Object[]) foundItems;
if (items.length != 0) {
IBinding[] bindings = new IBinding[items.length];
int k = 0;
for (Object item : items) {
if (item instanceof IBinding) {
bindings[k++] = (IBinding) item;
}
}
if (k != 0) {
return ArrayUtil.trimAt(IBinding.class, bindings, k - 1);
}
}
}
return IBinding.EMPTY_BINDING_ARRAY;
}
}

View file

@ -66,9 +66,11 @@ import org.eclipse.cdt.internal.ui.editor.ASTProvider;
import org.eclipse.cdt.internal.ui.search.actions.OpenDeclarationsAction;
/**
* It is required to test the selection performance independent of the indexer to make sure that the DOM is functioning properly.
* It is required to test the selection performance independent of the indexer to make sure that the DOM
* is functioning properly.
*
* Indexer bugs can drastically influence the correctness of these tests so the indexer has to be off when performing them.
* Indexer bugs can drastically influence the correctness of these tests so the indexer has to be off when
* performing them.
*
* @author dsteffle
*/
@ -281,6 +283,10 @@ public class CPPSelectionTestsNoIndexer extends BaseUITestCase {
return null;
}
private void assertContents(String code, int offset, String expected) {
assertEquals(expected, code.substring(offset, offset + expected.length()));
}
public void testBug93281() throws Exception {
StringBuffer buffer = new StringBuffer();
buffer.append("class Point{ \n"); //$NON-NLS-1$
@ -1048,4 +1054,41 @@ public class CPPSelectionTestsNoIndexer extends BaseUITestCase {
assertEquals("myFunc", name.toString());
}
}
// struct A {
// void method(int p) {}
// };
//
// void test(A* a) {
// a->method();
// a.method(0);
// }
// void A::method(int a, int b) {}
// void B::method(int b) {}
public void testUnresolvedMethod_278337() throws Exception {
String code= getContentsForTest(1)[0].toString();
IFile file = importFile("testBug278337.cpp", code);
IASTNode node= testF3(file, code.indexOf("method();"));
assertContents(code, node.getFileLocation().getNodeOffset(), "method(int p)");
node= testF3(file, code.indexOf("method(0);"));
assertNull(node);
node= testF3(file, code.indexOf("method(int a, int b)"));
assertContents(code, node.getFileLocation().getNodeOffset(), "method(int p)");
node= testF3(file, code.indexOf("method(int b)"));
// Should not navigate away since there is no good candidate.
assertContents(code, node.getFileLocation().getNodeOffset(), "method(int b)");
}
// class A {
// class B {};
// };
//
// B b;
public void testUnresolvedType() throws Exception {
String code= getContentsForTest(1)[0].toString();
IFile file = importFile("testUndefinedType.cpp", code);
int offset= code.indexOf("B b;");
IASTNode node= testF3(file, offset);
assertNull(node);
}
}

View file

@ -88,6 +88,9 @@ import org.eclipse.cdt.internal.ui.editor.CEditorMessages;
import org.eclipse.cdt.internal.ui.text.CWordFinder;
import org.eclipse.cdt.internal.ui.viewsupport.IndexUI;
/**
* Navigates to the definition of a name, or to the declaration if invoked on the definition.
*/
public class OpenDeclarationsAction extends SelectionParseAction implements ASTRunnable {
public static boolean sIsJUnitTest = false;
@ -185,15 +188,22 @@ public class OpenDeclarationsAction extends SelectionParseAction implements ASTR
openInclude(((IASTPreprocessorIncludeStatement) parent));
return Status.OK_STATUS;
}
IBinding binding = sourceName.resolveBinding();
NameKind kind = getNameKind(sourceName);
if (binding != null && !(binding instanceof IProblemBinding)) {
if (kind == NameKind.DEFINITION && binding instanceof IType) {
IBinding b = sourceName.resolveBinding();
IBinding[] bindings = new IBinding[] { b };
if (b instanceof IProblemBinding) {
IBinding[] candidateBindings = ((IProblemBinding) b).getCandidateBindings();
if (candidateBindings.length != 0) {
bindings = candidateBindings;
}
} else if (kind == NameKind.DEFINITION && b instanceof IType) {
// Don't navigate away from a type definition.
// Select the name at the current location instead.
navigateToName(sourceName);
return Status.OK_STATUS;
}
for (IBinding binding : bindings) {
if (binding != null && !(binding instanceof IProblemBinding)) {
IName[] declNames = findDeclNames(ast, kind, binding);
// Exclude the current location.
for (int i = 0; i < declNames.length; i++) {
@ -219,6 +229,7 @@ public class OpenDeclarationsAction extends SelectionParseAction implements ASTR
found = navigateOneLocation(declNames);
}
}
}
if (!found && !navigationFallBack(ast, sourceName, kind)) {
reportSymbolLookupFailure(new String(sourceName.toCharArray()));
}
@ -372,10 +383,10 @@ public class OpenDeclarationsAction extends SelectionParseAction implements ASTR
continue;
}
IName[] names = findNames(fIndex, ast, kind, binding);
// Exclude the current location.
// Exclude names of the same kind.
for (int i = 0; i < names.length; i++) {
if (getNameKind(names[i]) == kind) {
names[i] = null; // Don' navigate to a name of the same kind.
names[i] = null;
}
}
names = (IName[]) ArrayUtil.removeNulls(IName.class, names);