mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-23 08:55:25 +02:00
Bug 450888. Fixed the problem decribed in comment #0
This commit is contained in:
parent
ef9d90c4f5
commit
24ab006419
6 changed files with 105 additions and 64 deletions
|
@ -63,7 +63,6 @@ import org.eclipse.cdt.core.parser.util.ObjectMap;
|
|||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateTypeArgument;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInstanceCache;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
|
||||
/**
|
||||
* For testing PDOM binding resolution
|
||||
|
@ -71,13 +70,13 @@ import org.eclipse.core.runtime.CoreException;
|
|||
public class IndexCPPBindingResolutionBugs extends IndexBindingResolutionTestBase {
|
||||
|
||||
public static class SingleProject extends IndexCPPBindingResolutionBugs {
|
||||
public SingleProject() {setStrategy(new SinglePDOMTestStrategy(true));}
|
||||
public static TestSuite suite() {return suite(SingleProject.class);}
|
||||
public SingleProject() { setStrategy(new SinglePDOMTestStrategy(true)); }
|
||||
public static TestSuite suite() { return suite(SingleProject.class); }
|
||||
}
|
||||
|
||||
public static class ProjectWithDepProj extends IndexCPPBindingResolutionBugs {
|
||||
public ProjectWithDepProj() {setStrategy(new ReferencedProject(true));}
|
||||
public static TestSuite suite() {return suite(ProjectWithDepProj.class);}
|
||||
public ProjectWithDepProj() { setStrategy(new ReferencedProject(true)); }
|
||||
public static TestSuite suite() { return suite(ProjectWithDepProj.class); }
|
||||
}
|
||||
|
||||
public static void addTests(TestSuite suite) {
|
||||
|
@ -103,7 +102,7 @@ public class IndexCPPBindingResolutionBugs extends IndexBindingResolutionTestBas
|
|||
// OBJ {}
|
||||
// FUNC() {}
|
||||
// FUNC2(1) {}
|
||||
public void testBug208558() throws CoreException {
|
||||
public void testBug208558() throws Exception {
|
||||
IIndex index= getIndex();
|
||||
|
||||
IIndexMacro[] macrosA= index.findMacros("OBJ".toCharArray(), IndexFilter.ALL, npm());
|
||||
|
@ -1153,13 +1152,13 @@ public class IndexCPPBindingResolutionBugs extends IndexBindingResolutionTestBas
|
|||
// class Base {};
|
||||
// void useBase(Base* b);
|
||||
|
||||
// class Derived: Base {};
|
||||
// class Derived : Base {};
|
||||
// void test() {
|
||||
// X x;
|
||||
// useBase(x.d);
|
||||
// }
|
||||
public void testLateDefinitionOfInheritance_Bug292749() throws Exception {
|
||||
getBindingFromASTName("useBase(x.d", 7, ICPPFunction.class);
|
||||
getBindingFromFirstIdentifier("useBase(x.d)", ICPPFunction.class);
|
||||
}
|
||||
|
||||
// namespace one {
|
||||
|
@ -1369,14 +1368,17 @@ public class IndexCPPBindingResolutionBugs extends IndexBindingResolutionTestBas
|
|||
// waldo(new B<E>());
|
||||
// }
|
||||
// };
|
||||
public void _testTemplateArgumentResolution_450888() throws Exception {
|
||||
getProblemFromFirstIdentifier("waldo"); // waldo is not resolved because E doesn't extend C.
|
||||
public void testTemplateArgumentResolution_450888() throws Exception {
|
||||
getProblemFromFirstIdentifier("waldo"); // waldo is unresolved because E doesn't extend C.
|
||||
IASTTranslationUnit ast = strategy.getAst(0);
|
||||
ITranslationUnit tu = ast.getOriginatingTranslationUnit();
|
||||
IWorkingCopy workingCopy = tu.getWorkingCopy();
|
||||
IBuffer buffer = workingCopy.getBuffer();
|
||||
buffer.setContents(buffer.getContents().replace("E {", "E : public C<int> {"));
|
||||
// Release and re-acquire the index lock to clear the caches.
|
||||
getIndex().releaseReadLock();
|
||||
getIndex().acquireReadLock();
|
||||
ast = workingCopy.getAST(strategy.getIndex(), ITranslationUnit.AST_SKIP_INDEXED_HEADERS);
|
||||
checkBindings(ast); // E now extends C, there should be no unresolved symbols.
|
||||
checkBindings(ast);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -813,8 +813,8 @@ public class CPPSemantics {
|
|||
if (binding == null)
|
||||
return null;
|
||||
IScope scope = binding.getScope();
|
||||
if (scope instanceof IIndexScope && tu != null) {
|
||||
scope= tu.mapToASTScope((IIndexScope) scope);
|
||||
if (tu != null) {
|
||||
scope= tu.mapToASTScope(scope);
|
||||
}
|
||||
while (scope != null && !(scope instanceof ICPPNamespaceScope)) {
|
||||
scope = getParentScope(scope, tu);
|
||||
|
@ -982,7 +982,7 @@ public class CPPSemantics {
|
|||
}
|
||||
|
||||
while (nextScope != null || nextTmplScope != null) {
|
||||
// when the non-template scope is no longer contained within the first template scope,
|
||||
// When the non-template scope is no longer contained within the first template scope,
|
||||
// we use the template scope for the next iteration.
|
||||
boolean useTemplScope= false;
|
||||
if (nextTmplScope != null) {
|
||||
|
@ -996,8 +996,8 @@ public class CPPSemantics {
|
|||
}
|
||||
ICPPScope scope= useTemplScope ? nextTmplScope : nextScope;
|
||||
CPPASTTranslationUnit tu = data.getTranslationUnit();
|
||||
if (scope instanceof IIndexScope && tu != null) {
|
||||
scope= (ICPPScope) tu.mapToASTScope(((IIndexScope) scope));
|
||||
if (tu != null) {
|
||||
scope= (ICPPScope) tu.mapToASTScope((scope));
|
||||
}
|
||||
|
||||
if (!data.usingDirectivesOnly && !(data.ignoreMembers && scope instanceof ICPPClassScope)) {
|
||||
|
@ -1355,13 +1355,13 @@ public class CPPSemantics {
|
|||
|
||||
static ICPPScope getParentScope(IScope scope, ICPPASTTranslationUnit unit) throws DOMException {
|
||||
IScope parentScope= scope.getParent();
|
||||
// the index cannot return the translation unit as parent scope
|
||||
// The index cannot return the translation unit as parent scope.
|
||||
if (unit instanceof CPPASTTranslationUnit) {
|
||||
if (parentScope == null
|
||||
&& (scope instanceof IIndexScope || scope instanceof ICPPClassSpecializationScope)) {
|
||||
parentScope = unit.getScope();
|
||||
} else if (parentScope instanceof IIndexScope) {
|
||||
parentScope = ((CPPASTTranslationUnit) unit).mapToASTScope((IIndexScope) parentScope);
|
||||
} else {
|
||||
parentScope = ((CPPASTTranslationUnit) unit).mapToASTScope(parentScope);
|
||||
}
|
||||
}
|
||||
return (ICPPScope) parentScope;
|
||||
|
@ -1377,8 +1377,8 @@ public class CPPSemantics {
|
|||
ICPPUsingDirective directive, Set<ICPPNamespaceScope> handled) throws DOMException {
|
||||
ICPPNamespaceScope nominated= directive.getNominatedScope();
|
||||
CPPASTTranslationUnit tu= data.getTranslationUnit();
|
||||
if (nominated instanceof IIndexScope && tu != null) {
|
||||
nominated= (ICPPNamespaceScope) tu.mapToASTScope((IIndexScope) nominated);
|
||||
if (tu != null) {
|
||||
nominated= (ICPPNamespaceScope) tu.mapToASTScope(nominated);
|
||||
}
|
||||
if (nominated == null || data.visited.containsKey(nominated) || (handled != null && !handled.add(nominated))) {
|
||||
return;
|
||||
|
|
|
@ -170,6 +170,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownMemberClassInstan
|
|||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Conversions.Context;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Conversions.UDCMode;
|
||||
import org.eclipse.cdt.internal.core.index.IIndexType;
|
||||
|
||||
/**
|
||||
* Collection of static methods to perform template instantiation, member specialization and
|
||||
|
@ -420,6 +421,17 @@ public class CPPTemplates {
|
|||
ICPPTemplateInstance result = ((ICPPInstanceCache) template).getInstance(args);
|
||||
if (forDefinition && result instanceof IIndexBinding)
|
||||
return null;
|
||||
if (result != null) {
|
||||
// Don't use the cached instance if its argument is an index type and the requested
|
||||
// argument is an AST type. Despite identical signatures the types may be different.
|
||||
ICPPTemplateArgument[] instanceArgs = result.getTemplateArguments();
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
if (!(args[i].getTypeValue() instanceof IIndexType) &&
|
||||
(instanceArgs[i].getTypeValue() instanceof IIndexType)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
|
|
|
@ -183,7 +183,6 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTFieldReference;
|
|||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTFunctionCallExpression;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTIdExpression;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTranslationUnit;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTUnaryExpression;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPAliasTemplate;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPArrayType;
|
||||
|
@ -517,7 +516,7 @@ public class CPPVisitor extends ASTQueries {
|
|||
binding = CPPSemantics.resolveBinding(elabType.getName());
|
||||
}
|
||||
if (binding instanceof IIndexBinding && binding instanceof ICPPClassType) {
|
||||
binding= ((CPPASTTranslationUnit) elabType.getTranslationUnit()).mapToAST((ICPPClassType) binding, elabType);
|
||||
binding= (ICPPClassType) SemanticUtil.mapToAST((ICPPClassType) binding, elabType);
|
||||
ASTInternal.addDeclaration(binding, elabType);
|
||||
}
|
||||
|
||||
|
@ -1270,9 +1269,7 @@ public class CPPVisitor extends ASTQueries {
|
|||
boolean done= true;
|
||||
IScope scope= null;
|
||||
if (binding instanceof ICPPClassType) {
|
||||
if (binding instanceof IIndexBinding && tu != null) {
|
||||
binding= (((CPPASTTranslationUnit) tu)).mapToAST((ICPPClassType) binding, name);
|
||||
}
|
||||
binding= (ICPPClassType) SemanticUtil.mapToAST((ICPPClassType) binding, name);
|
||||
scope= ((ICPPClassType) binding).getCompositeScope();
|
||||
} else if (binding instanceof ICPPNamespace) {
|
||||
scope= ((ICPPNamespace) binding).getNamespaceScope();
|
||||
|
@ -2556,7 +2553,7 @@ public class CPPVisitor extends ASTQueries {
|
|||
break;
|
||||
IBinding binding = segments[i].resolveBinding();
|
||||
if (binding instanceof IIndexBinding && binding instanceof ICPPClassType) {
|
||||
binding = ((CPPASTTranslationUnit) name.getTranslationUnit()).mapToAST((ICPPClassType) binding, name);
|
||||
binding = (ICPPClassType) SemanticUtil.mapToAST((ICPPClassType) binding, name);
|
||||
}
|
||||
return bindingToOwner(binding);
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ import org.eclipse.cdt.core.dom.ast.IFunctionType;
|
|||
import org.eclipse.cdt.core.dom.ast.IPointerType;
|
||||
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IQualifierType;
|
||||
import org.eclipse.cdt.core.dom.ast.IScope;
|
||||
import org.eclipse.cdt.core.dom.ast.ISemanticProblem;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.ITypedef;
|
||||
|
@ -406,7 +407,7 @@ public class SemanticUtil {
|
|||
if (newNestedType == null)
|
||||
return type;
|
||||
|
||||
// Bug 249085 make sure not to add unnecessary qualifications
|
||||
// Do not to add unnecessary qualifications (bug 24908).
|
||||
if (type instanceof IQualifierType) {
|
||||
IQualifierType qt= (IQualifierType) type;
|
||||
return addQualifiers(newNestedType, qt.isConst(), qt.isVolatile(), false);
|
||||
|
@ -489,40 +490,64 @@ public class SemanticUtil {
|
|||
}
|
||||
}
|
||||
|
||||
public static IType mapToAST(IType type, IASTNode node) {
|
||||
if (node == null)
|
||||
return type;
|
||||
|
||||
if (type instanceof IFunctionType) {
|
||||
final ICPPFunctionType ft = (ICPPFunctionType) type;
|
||||
final IType r = ft.getReturnType();
|
||||
final IType ret = mapToAST(r, node);
|
||||
if (ret == r) {
|
||||
return type;
|
||||
}
|
||||
return new CPPFunctionType(ret, ft.getParameterTypes(), ft.isConst(), ft.isVolatile(),
|
||||
ft.hasRefQualifier(), ft.isRValueReference(), ft.takesVarArgs());
|
||||
}
|
||||
if (type instanceof ITypeContainer) {
|
||||
final ITypeContainer tc = (ITypeContainer) type;
|
||||
final IType nestedType= tc.getType();
|
||||
if (nestedType == null)
|
||||
return type;
|
||||
|
||||
IType newType= mapToAST(nestedType, node);
|
||||
if (newType != nestedType) {
|
||||
return replaceNestedType(tc, newType);
|
||||
}
|
||||
return type;
|
||||
} else if (type instanceof ICPPClassType && type instanceof IIndexBinding) {
|
||||
IASTTranslationUnit tu = node.getTranslationUnit();
|
||||
if (tu instanceof CPPASTTranslationUnit) {
|
||||
return ((CPPASTTranslationUnit) tu).mapToAST((ICPPClassType) type, node);
|
||||
public static IType mapToAST(IType type, IASTNode point) {
|
||||
if (point != null && type instanceof IIndexBinding && type instanceof ICPPClassType) {
|
||||
IASTTranslationUnit ast = point.getTranslationUnit();
|
||||
if (ast instanceof CPPASTTranslationUnit) {
|
||||
return ((CPPASTTranslationUnit) ast).mapToAST((ICPPClassType) type, point);
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
public static ICPPTemplateArgument[] mapToAST(ICPPTemplateArgument[] args, IASTNode point) {
|
||||
if (point == null)
|
||||
return args;
|
||||
|
||||
// Don't create a new array until it's really needed.
|
||||
ICPPTemplateArgument[] result = args;
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
final ICPPTemplateArgument arg = args[i];
|
||||
ICPPTemplateArgument newArg = arg;
|
||||
if (arg != null) {
|
||||
newArg = mapToAST(arg, point);
|
||||
if (result != args) {
|
||||
result[i] = newArg;
|
||||
} else if (arg != newArg) {
|
||||
result = new ICPPTemplateArgument[args.length];
|
||||
if (i > 0) {
|
||||
System.arraycopy(args, 0, result, 0, i);
|
||||
}
|
||||
result[i] = newArg;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static ICPPTemplateArgument mapToAST(ICPPTemplateArgument arg, IASTNode point) {
|
||||
IType type = arg.getTypeValue();
|
||||
if (type != null) {
|
||||
IType mappedType = mapToAST(type, point);
|
||||
IType originalType = arg.getOriginalTypeValue();
|
||||
IType mappedOriginalType = originalType == type ? mappedType : mapToAST(originalType, point);
|
||||
if (mappedType != type || mappedOriginalType != originalType) {
|
||||
return new CPPTemplateTypeArgument(mappedType, mappedOriginalType);
|
||||
}
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
|
||||
public static IScope mapToAST(IScope scope, IASTNode point) {
|
||||
if (point != null) {
|
||||
IASTTranslationUnit ast = point.getTranslationUnit();
|
||||
if (ast instanceof CPPASTTranslationUnit) {
|
||||
return ((CPPASTTranslationUnit) ast).mapToASTScope(scope);
|
||||
}
|
||||
}
|
||||
return scope;
|
||||
}
|
||||
|
||||
public static IType[] getSimplifiedTypes(IType[] types) {
|
||||
// Don't create a new array until it's really needed.
|
||||
IType[] result = types;
|
||||
|
@ -713,13 +738,16 @@ public class SemanticUtil {
|
|||
clazz= (ICPPClassType) ((ICPPDeferredClassInstance) clazz).getSpecializedBinding();
|
||||
}
|
||||
|
||||
// The base classes may have changed since the definition of clazz was indexed.
|
||||
clazz = (ICPPClassType) mapToAST(clazz, point);
|
||||
|
||||
for (ICPPBase cppBase : ClassTypeHelper.getBases(clazz, point)) {
|
||||
IBinding base= cppBase.getBaseClass();
|
||||
if (base instanceof IType && hashSet.add(base)) {
|
||||
IType tbase= (IType) base;
|
||||
if (tbase.isSameType(baseClass) ||
|
||||
(baseClass instanceof ICPPSpecialization && // allow some flexibility with templates
|
||||
((IType)((ICPPSpecialization) baseClass).getSpecializedBinding()).isSameType(tbase))) {
|
||||
(baseClass instanceof ICPPSpecialization && // Allow some flexibility with templates.
|
||||
((IType) ((ICPPSpecialization) baseClass).getSpecializedBinding()).isSameType(tbase))) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -973,7 +973,6 @@ public class PDOM extends PlatformObject implements IPDOM {
|
|||
|
||||
@Override
|
||||
public void releaseReadLock() {
|
||||
boolean clearCache= false;
|
||||
synchronized (mutex) {
|
||||
assert lockCount > 0: "No lock to release"; //$NON-NLS-1$
|
||||
if (sDEBUG_LOCKS) {
|
||||
|
@ -984,12 +983,15 @@ public class PDOM extends PlatformObject implements IPDOM {
|
|||
if (lockCount > 0)
|
||||
--lockCount;
|
||||
mutex.notifyAll();
|
||||
clearCache= lockCount == 0;
|
||||
db.setLocked(lockCount != 0);
|
||||
}
|
||||
if (clearCache) {
|
||||
clearResultCache();
|
||||
}
|
||||
// A lock release probably means that some AST is going away. The result cache has to be
|
||||
// cleared since it may contain objects belonging to the AST that is going away. A failure
|
||||
// to release an AST object would cause a memory leak since the whole AST would remain
|
||||
// pinned to memory.
|
||||
// TODO(sprigogin): It would be more efficient to replace the global result cache with
|
||||
// separate caches for each AST.
|
||||
clearResultCache();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Reference in a new issue