1
0
Fork 0
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:
Sergey Prigogin 2014-12-08 16:17:59 -08:00
parent ef9d90c4f5
commit 24ab006419
6 changed files with 105 additions and 64 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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