1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-08 10:16:03 +02:00

Bug 416278 - Indexer gets confused by a class in an anonymous namespace.

This commit is contained in:
Sergey Prigogin 2013-09-09 14:14:23 -07:00
parent 2690b106c5
commit 1c122ce5af
8 changed files with 147 additions and 29 deletions

View file

@ -85,8 +85,9 @@ public abstract class IndexBindingResolutionTestBase extends BaseTestCase {
} }
protected IASTName findName(String section, int len, boolean preferImplicitName) { protected IASTName findName(String section, int len, boolean preferImplicitName) {
if (len == 0) if (len <= 0)
len= section.length(); len += section.length();
for (int i = 0; i < strategy.getAstCount(); i++) { for (int i = 0; i < strategy.getAstCount(); i++) {
IASTTranslationUnit ast = strategy.getAst(i); IASTTranslationUnit ast = strategy.getAst(i);
final IASTNodeSelector nodeSelector = ast.getNodeSelector(null); final IASTNodeSelector nodeSelector = ast.getNodeSelector(null);
@ -128,10 +129,10 @@ public abstract class IndexBindingResolutionTestBase extends BaseTestCase {
* @param clazz an expected class type or interface that the binding should extend/implement * @param clazz an expected class type or interface that the binding should extend/implement
* @return the associated name's binding * @return the associated name's binding
*/ */
protected <T> T getBindingFromASTName(String section, int len, Class<T> clazz, Class ... cs) { protected <T> T getBindingFromASTName(String section, int len, Class<T> clazz, Class... cs) {
if (len < 1) { if (len <= 0)
len= section.length()+len; len += section.length();
}
IASTName name= findName(section, len); IASTName name= findName(section, len);
assertNotNull("Name not found for \"" + section + "\"", name); assertNotNull("Name not found for \"" + section + "\"", name);
assertEquals(section.substring(0, len), name.getRawSignature()); assertEquals(section.substring(0, len), name.getRawSignature());
@ -156,10 +157,10 @@ public abstract class IndexBindingResolutionTestBase extends BaseTestCase {
* @param clazz an expected class type or interface that the binding should extend/implement * @param clazz an expected class type or interface that the binding should extend/implement
* @return the associated implicit name's binding * @return the associated implicit name's binding
*/ */
protected <T> T getBindingFromImplicitASTName(String section, int len, Class<T> clazz, Class ... cs) { protected <T> T getBindingFromImplicitASTName(String section, int len, Class<T> clazz, Class... cs) {
if (len < 1) { if (len <= 0)
len= section.length()+len; len += section.length();
}
IASTName name= findImplicitName(section, len); IASTName name= findImplicitName(section, len);
assertNotNull("Name not found for \"" + section + "\"", name); assertNotNull("Name not found for \"" + section + "\"", name);
assertEquals(section.substring(0, len), name.getRawSignature()); assertEquals(section.substring(0, len), name.getRawSignature());
@ -172,7 +173,7 @@ public abstract class IndexBindingResolutionTestBase extends BaseTestCase {
} }
/* /*
* @see IndexBindingResolutionTestBase#getBindingFromASTName(String, int, Class<T>, Class ...) * @see IndexBindingResolutionTestBase#getBindingFromASTName(String, int, Class<T>, Class...)
*/ */
protected <T extends IBinding> T getBindingFromASTName(String section, int len) { protected <T extends IBinding> T getBindingFromASTName(String section, int len) {
if (len <= 0) if (len <= 0)
@ -188,6 +189,14 @@ public abstract class IndexBindingResolutionTestBase extends BaseTestCase {
return (T) binding; return (T) binding;
} }
protected <T extends IBinding> T getBindingFromFirstIdentifier(String section) {
return getBindingFromASTName(section, getIdentifierLength(section));
}
protected <T extends IBinding> T getBindingFromFirstIdentifier(String section, Class<T> clazz, Class... cs) {
return getBindingFromASTName(section, getIdentifierLength(section), clazz, cs);
}
/* /*
* @see IndexBindingResolutionTestBase#getBindingFromImplicitASTName(String, int, Class<T>, Class ...) * @see IndexBindingResolutionTestBase#getBindingFromImplicitASTName(String, int, Class<T>, Class ...)
*/ */
@ -201,7 +210,8 @@ public abstract class IndexBindingResolutionTestBase extends BaseTestCase {
IBinding binding = name.resolveBinding(); IBinding binding = name.resolveBinding();
assertNotNull("No binding for " + name.getRawSignature(), binding); assertNotNull("No binding for " + name.getRawSignature(), binding);
assertFalse("Binding is a ProblemBinding for name \"" + name.getRawSignature() + "\"", IProblemBinding.class.isAssignableFrom(name.resolveBinding().getClass())); assertFalse("Binding is a ProblemBinding for name \"" + name.getRawSignature() + "\"",
IProblemBinding.class.isAssignableFrom(name.resolveBinding().getClass()));
return (T) binding; return (T) binding;
} }
@ -218,10 +228,15 @@ public abstract class IndexBindingResolutionTestBase extends BaseTestCase {
IBinding binding = name.resolveBinding(); IBinding binding = name.resolveBinding();
assertNotNull("No binding for " + name.getRawSignature(), binding); assertNotNull("No binding for " + name.getRawSignature(), binding);
assertTrue("Binding is not a ProblemBinding for name \"" + name.getRawSignature() + "\"", IProblemBinding.class.isAssignableFrom(name.resolveBinding().getClass())); assertTrue("Binding is not a ProblemBinding for name \"" + name.getRawSignature() + "\"",
IProblemBinding.class.isAssignableFrom(name.resolveBinding().getClass()));
return name.resolveBinding(); return name.resolveBinding();
} }
protected IBinding getProblemFromFirstIdentifier(String section) {
return getProblemFromASTName(section, getIdentifierLength(section));
}
protected static void assertQNEquals(String expectedQN, IBinding b) { protected static void assertQNEquals(String expectedQN, IBinding b) {
assertInstance(b, IBinding.class); assertInstance(b, IBinding.class);
if (b instanceof ICPPBinding) { if (b instanceof ICPPBinding) {
@ -308,6 +323,13 @@ public abstract class IndexBindingResolutionTestBase extends BaseTestCase {
} }
} }
protected int getIdentifierLength(String str) {
int i;
for (i = 0; i < str.length() && Character.isJavaIdentifierPart(str.charAt(i)); ++i) {
}
return i;
}
static protected class NameCollector extends ASTVisitor { static protected class NameCollector extends ASTVisitor {
{ {
shouldVisitNames = true; shouldVisitNames = true;

View file

@ -1715,6 +1715,16 @@ public abstract class IndexCPPBindingResolutionTest extends IndexBindingResoluti
getBindingFromASTName("g(b)", 1, ICPPFunction.class); getBindingFromASTName("g(b)", 1, ICPPFunction.class);
} }
// namespace {
// class A {};
// }
// A a;
public void testAnonymousNamespace() throws Exception {
getBindingFromFirstIdentifier("A", ICPPClassType.class);
}
// namespace ns { // namespace ns {
// namespace { // namespace {
// const char str[] = ""; // const char str[] = "";
@ -1735,6 +1745,6 @@ public abstract class IndexCPPBindingResolutionTest extends IndexBindingResoluti
// //
// } // }
public void testAnonymousNamespaces_392577() throws Exception { public void testAnonymousNamespaces_392577() throws Exception {
getBindingFromASTName("f(str)", 1, ICPPFunction.class); getBindingFromFirstIdentifier("f(str)", ICPPFunction.class);
} }
} }

View file

@ -0,0 +1,59 @@
/*******************************************************************************
* Copyright (c) 2013 Google, Inc and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.index.tests;
import junit.framework.TestSuite;
/**
* Tests for header files included in multiple variants.
*
* The first line of each comment section preceding a test contains the name of the file
* to put the contents of the section to. To request the AST of a file, put an asterisk after
* the file name.
*/
public class IndexMultiFileTest extends IndexBindingResolutionTestBase {
public IndexMultiFileTest() {
setStrategy(new SinglePDOMTestNamedFilesStrategy(true));
}
public static TestSuite suite() {
return suite(IndexMultiFileTest.class);
}
// A.h
// template <typename T>
// struct A {
// void m(T p);
// };
// B.h
// struct B {};
// confuser.cpp
// #include "A.h"
//
// namespace {
// struct B {};
// }
// A<B*> z;
// test.cpp *
// #include "A.h"
// #include "B.h"
//
// void test(A<B*> a, B* b) {
// a.m(b);
// }
public void testAnonymousNamespace_416278() throws Exception {
checkBindings();
}
}

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2006, 2007 Wind River Systems, Inc. and others. * Copyright (c) 2006, 2013 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -7,6 +7,7 @@
* *
* Contributors: * Contributors:
* Markus Schorn - initial API and implementation * Markus Schorn - initial API and implementation
* Sergey Prigogin (Google)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.index.tests; package org.eclipse.cdt.internal.index.tests;
@ -31,6 +32,7 @@ public class IndexTests extends TestSuite {
suite.addTest(TeamSharedIndexTest.suite()); suite.addTest(TeamSharedIndexTest.suite());
suite.addTest(IndexProviderManagerTest.suite()); suite.addTest(IndexProviderManagerTest.suite());
suite.addTest(IndexMultiVariantHeaderTest.suite()); suite.addTest(IndexMultiVariantHeaderTest.suite());
suite.addTest(IndexMultiFileTest.suite());
IndexCPPBindingResolutionBugs.addTests(suite); IndexCPPBindingResolutionBugs.addTests(suite);
IndexCPPBindingResolutionTest.addTests(suite); IndexCPPBindingResolutionTest.addTests(suite);

View file

@ -17,6 +17,7 @@ import java.util.ArrayList;
import java.util.BitSet; import java.util.BitSet;
import java.util.List; import java.util.List;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.IBasicType.Kind; import org.eclipse.cdt.core.dom.ast.IBasicType.Kind;
import org.eclipse.cdt.core.dom.ast.c.ICArrayType; import org.eclipse.cdt.core.dom.ast.c.ICArrayType;
import org.eclipse.cdt.core.dom.ast.c.ICQualifierType; import org.eclipse.cdt.core.dom.ast.c.ICQualifierType;
@ -32,6 +33,8 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPQualifierType; import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPQualifierType;
import org.eclipse.cdt.core.index.IIndexBinding;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.parser.GCCKeywords; import org.eclipse.cdt.core.parser.GCCKeywords;
import org.eclipse.cdt.core.parser.Keywords; import org.eclipse.cdt.core.parser.Keywords;
import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.core.parser.util.ArrayUtil;
@ -47,6 +50,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownMemberClassInstan
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; 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.parser.cpp.semantics.SemanticUtil;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.TypeOfDependentExpression; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.TypeOfDependentExpression;
import org.eclipse.core.runtime.CoreException;
/** /**
* This is a utility class to help convert AST elements to Strings corresponding to * This is a utility class to help convert AST elements to Strings corresponding to
@ -735,6 +739,18 @@ public class ASTTypeUtil {
if (owner instanceof ICPPNamespace || owner instanceof IType) { if (owner instanceof ICPPNamespace || owner instanceof IType) {
int pos= result.length(); int pos= result.length();
appendCppName(owner, normalize, qualify, result); appendCppName(owner, normalize, qualify, result);
if (binding instanceof IIndexBinding && owner instanceof ICPPNamespace && owner.getNameCharArray().length == 0) {
try {
IIndexFile file = ((IIndexBinding) binding).getLocalToFile();
if (file != null) {
result.append('{');
result.append(file.getLocation().getURI().toString());
result.append('}');
}
} catch (CoreException e) {
CCorePlugin.log(e);
}
}
if (result.length() > pos) if (result.length() > pos)
result.append("::"); //$NON-NLS-1$ result.append("::"); //$NON-NLS-1$
} }
@ -804,8 +820,10 @@ public class ASTTypeUtil {
int fnamestart= findFileNameStart(fname); int fnamestart= findFileNameStart(fname);
buf.append('{'); buf.append('{');
buf.append(fname, fnamestart, fname.length - fnamestart); buf.append(fname, fnamestart, fname.length - fnamestart);
if (!(binding instanceof ICPPNamespace)) {
buf.append(':'); buf.append(':');
buf.append(loc.getNodeOffset()); buf.append(loc.getNodeOffset());
}
buf.append('}'); buf.append('}');
} }
} }

View file

@ -8,6 +8,7 @@
* Contributors: * Contributors:
* Markus Schorn - initial API and implementation * Markus Schorn - initial API and implementation
* Thomas Corbat (IFS) * Thomas Corbat (IFS)
* Sergey Prigogin (Google)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.dom; package org.eclipse.cdt.internal.core.pdom.dom;
@ -39,6 +40,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumeration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumeration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.core.index.IIndexBinding; import org.eclipse.cdt.core.index.IIndexBinding;
@ -657,6 +659,8 @@ public class PDOMASTAdapter {
if (name != null) { if (name != null) {
return new AnonymousCompositeType(name, (ICompositeType) binding); return new AnonymousCompositeType(name, (ICompositeType) binding);
} }
} else if (binding instanceof ICPPNamespace) {
return binding;
} else if (binding instanceof ICPPTemplateParameter) { } else if (binding instanceof ICPPTemplateParameter) {
return binding; return binding;
} else if (binding instanceof ICPPConstructor) { } else if (binding instanceof ICPPConstructor) {

View file

@ -864,15 +864,6 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
if (ib.isFileLocal()) { if (ib.isFileLocal()) {
return null; return null;
} }
} else {
// Skip anonymous namespaces.
while (owner instanceof ICPPNamespace) {
char[] name= owner.getNameCharArray();
if (name.length > 0) {
break;
}
owner= owner.getOwner();
}
} }
if (owner == null) if (owner == null)

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2006, 2011 QNX Software Systems and others. * Copyright (c) 2006, 2013 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -11,6 +11,7 @@
* Andrew Ferguson (Symbian) * Andrew Ferguson (Symbian)
* Bryan Wilkinson (QNX) * Bryan Wilkinson (QNX)
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion) * Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
* Sergey Prigogin (Google)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.dom.cpp; package org.eclipse.cdt.internal.core.pdom.dom.cpp;
@ -30,6 +31,7 @@ import org.eclipse.cdt.core.index.IIndexFileSet;
import org.eclipse.cdt.core.index.IndexFilter; import org.eclipse.cdt.core.index.IndexFilter;
import org.eclipse.cdt.core.parser.Keywords; import org.eclipse.cdt.core.parser.Keywords;
import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; 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.CPPVisitor;
import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants; import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants;
@ -135,6 +137,16 @@ class PDOMCPPNamespace extends PDOMCPPBinding
if (child instanceof PDOMCPPNamespace) { if (child instanceof PDOMCPPNamespace) {
((PDOMCPPNamespace) child).addToList(record + FIRST_NAMESPACE_CHILD_OFFSET); ((PDOMCPPNamespace) child).addToList(record + FIRST_NAMESPACE_CHILD_OFFSET);
} }
if (hasName(CharArrayUtils.EMPTY_CHAR_ARRAY)) {
// The parent of the anonymous namespace adopts its children so that they could be
// found up there.
PDOMNode parent = getParentNode();
if (parent instanceof PDOMCPPNamespace) {
parent.addChild(child);
} else {
getLinkage().addChild(child);
}
}
} }
public void addToList(final long listRecord) throws CoreException { public void addToList(final long listRecord) throws CoreException {