1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

A cleaner fix for bug 214447. Result of a joint hackathon with Markus Schorn.

This commit is contained in:
Sergey Prigogin 2008-03-23 23:00:35 +00:00
parent 415fa11ce8
commit e7858c339d
14 changed files with 124 additions and 149 deletions

View file

@ -12,8 +12,6 @@ package org.eclipse.cdt.core.dom.ast.cpp;
/**
* @author Bryan Wilkinson
*
*/
public interface ICPPDeferredTemplateInstance extends ICPPTemplateInstance {
}

View file

@ -12,11 +12,10 @@ package org.eclipse.cdt.core.dom.ast.cpp;
import org.eclipse.cdt.core.dom.ast.DOMException;
/**
* @author Doug Schaefer
*/
public interface ICPPTemplateDefinition extends ICPPBinding{
public interface ICPPTemplateDefinition extends ICPPBinding {
/**
* Returns an array of the template parameters.
@ -25,6 +24,4 @@ public interface ICPPTemplateDefinition extends ICPPBinding{
* @return array of ICPPTemplateParameter
*/
public ICPPTemplateParameter[] getTemplateParameters() throws DOMException;
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2005, 2007 IBM Corporation and others.
* Copyright (c) 2005, 2008 IBM Corporation 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
@ -8,22 +8,16 @@
* Contributors:
* IBM - Initial API and implementation
*******************************************************************************/
/*
* Created on Mar 28, 2005
*/
package org.eclipse.cdt.core.dom.ast.cpp;
import org.eclipse.cdt.core.dom.ast.IType;
/**
* @author aniefer
*/
/**
* This interface represents an instantiation of a class or function template.
* An instantiated template is a specialization of that template.
*
* An instance of a class template will also implement ICPPClassType and similarily
* An instance of a class template will also implement ICPPClassType and similarly
* a function template instance will also implement ICPPFunction (or even ICPPMethod
* or ICPPConstructor as appropriate)
*
@ -41,5 +35,5 @@ public interface ICPPTemplateInstance extends ICPPSpecialization {
* get the types of the arguments the template was instantiated with.
* @return
*/
public IType [] getArguments();
public IType[] getArguments();
}

View file

@ -64,36 +64,43 @@ public class CPPASTNamedTypeSpecifier extends CPPASTBaseDeclSpecifier implements
}
}
public boolean accept( ASTVisitor action ){
if( action.shouldVisitDeclSpecifiers ){
switch( action.visit( this ) ){
case ASTVisitor.PROCESS_ABORT : return false;
case ASTVisitor.PROCESS_SKIP : return true;
default : break;
public boolean accept(ASTVisitor action) {
if (action.shouldVisitDeclSpecifiers) {
switch (action.visit(this)) {
case ASTVisitor.PROCESS_ABORT:
return false;
case ASTVisitor.PROCESS_SKIP:
return true;
default:
break;
}
}
if( name != null ) if( !name.accept( action ) ) return false;
if (name != null && !name.accept(action))
return false;
if( action.shouldVisitDeclSpecifiers ){
switch( action.leave( this ) ){
case ASTVisitor.PROCESS_ABORT : return false;
case ASTVisitor.PROCESS_SKIP : return true;
default : break;
if (action.shouldVisitDeclSpecifiers ){
switch (action.leave(this)) {
case ASTVisitor.PROCESS_ABORT:
return false;
case ASTVisitor.PROCESS_SKIP:
return true;
default:
break;
}
}
return true;
}
public int getRoleForName(IASTName n) {
if( n == name )
if (n == name)
return r_reference;
return r_unclear;
}
public IBinding[] findBindings(IASTName n, boolean isPrefix) {
IBinding[] bindings = CPPSemantics.findBindingsForContentAssist(n, isPrefix);
List filtered = new ArrayList();
List<IBinding> filtered = new ArrayList<IBinding>();
for (int i = 0; i < bindings.length; i++) {
if (bindings[i] instanceof ICPPClassType
|| bindings[i] instanceof IEnumeration
@ -103,7 +110,7 @@ public class CPPASTNamedTypeSpecifier extends CPPASTBaseDeclSpecifier implements
filtered.add(bindings[i]);
}
}
return (IBinding[]) filtered.toArray(new IBinding[filtered.size()]);
return filtered.toArray(new IBinding[filtered.size()]);
}
}

View file

@ -13,9 +13,6 @@
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IField;
@ -29,7 +26,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPDeferredTemplateInstance;
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.ICPPScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.ObjectMap;
@ -206,63 +202,6 @@ public class CPPClassInstance extends CPPInstance implements ICPPClassType, ICPP
return ICPPMethod.EMPTY_CPPMETHOD_ARRAY;
}
/**
* Returns a combined argument map of this class and all its base template classes.
* This combined map helps with instantiation of members of template classes that subclass
* other template classes (see AST2TemplateTests#testRebindPattern_214017_2()).
*/
@Override
public ObjectMap getArgumentMap() {
ObjectMap argMap = argumentMap;
List<ICPPSpecialization> bases = null;
try {
for (ICPPBase base : getBases()) {
IBinding baseClass = base.getBaseClass();
if (baseClass instanceof ICPPSpecialization) {
if (bases == null) {
bases = new ArrayList<ICPPSpecialization>();
}
bases.add((ICPPSpecialization) baseClass);
}
}
if (bases != null) {
for (int i = 0; i < bases.size(); i++) {
for (ICPPBase base : ((ICPPClassType) bases.get(i)).getBases()) {
IBinding baseClass = base.getBaseClass();
if (baseClass instanceof ICPPSpecialization) {
bases.add((ICPPSpecialization) baseClass);
}
}
if (bases.size() > 20) { // Protect against cyclic inheritance.
break;
}
}
}
} catch (DOMException e) {
// Ignore
}
if (bases != null) {
for (ICPPSpecialization base : bases) {
// Protect against infinite recursion.
ObjectMap baseArgMap = base instanceof CPPClassInstance ?
((CPPClassInstance) base).argumentMap : base.getArgumentMap();
if (!baseArgMap.isEmpty()) {
if (argMap == argumentMap) {
argMap = (ObjectMap) argumentMap.clone();
}
for (int i = 0; i < baseArgMap.size(); i++) {
Object key = baseArgMap.keyAt(i);
if (!argMap.containsKey(key)) {
argMap.put(key, baseArgMap.getAt(i));
}
}
}
}
}
return argMap;
}
@Override
public boolean equals(Object obj) {
return obj instanceof ICPPClassType && isSameType((ICPPClassType) obj);

View file

@ -28,10 +28,13 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.core.parser.util.ObjectMap;
/**
* Represents a partially instantiated C++ class template, who's arguments contain at least one template
* type parameter.
*
* @author aniefer
*/
public class CPPDeferredClassInstance extends CPPInstance implements
ICPPClassType, ICPPDeferredTemplateInstance, ICPPInternalDeferredClassInstance {
public class CPPDeferredClassInstance extends CPPInstance
implements ICPPClassType, ICPPDeferredTemplateInstance, ICPPInternalDeferredClassInstance {
public CPPDeferredClassInstance(ICPPClassTemplate orig, IType[] arguments) {
super(null, orig, buildArgumentMap(orig, arguments), arguments);

View file

@ -29,17 +29,13 @@ import org.eclipse.core.runtime.PlatformObject;
/**
* @author aniefer
*/
public class CPPUnknownBinding extends PlatformObject implements ICPPInternalUnknown {
public class CPPUnknownBinding extends PlatformObject implements ICPPInternalUnknown, Cloneable {
private ICPPScope unknownScope = null;
private IBinding scopeBinding = null;
private ICPPScope scope = null;
protected ICPPInternalUnknown scopeBinding = null;
protected IASTName name = null;
/**
*
*/
public CPPUnknownBinding(ICPPScope scope, IBinding scopeBinding, IASTName name) {
public CPPUnknownBinding(ICPPInternalUnknown scopeBinding, IASTName name) {
super();
this.scope = scope;
this.name = name;
this.scopeBinding = scopeBinding;
}
@ -125,7 +121,7 @@ public class CPPUnknownBinding extends PlatformObject implements ICPPInternalUnk
* @see org.eclipse.cdt.core.dom.ast.IBinding#getScope()
*/
public IScope getScope() {
return scope;
return scopeBinding.getUnknownScope();
}
/* (non-Javadoc)
@ -146,6 +142,10 @@ public class CPPUnknownBinding extends PlatformObject implements ICPPInternalUnk
IScope s = ((ICPPClassType) t).getCompositeScope();
if (s != null && ASTInternal.isFullyCached(s))
result = s.getBinding(name, true);
} else if (t instanceof ICPPInternalUnknown) {
CPPUnknownBinding res = (CPPUnknownBinding) clone();
res.scopeBinding = (ICPPInternalUnknown) t;
result = res;
}
}
return result;
@ -154,10 +154,20 @@ public class CPPUnknownBinding extends PlatformObject implements ICPPInternalUnk
public ILinkage getLinkage() {
return Linkage.CPP_LINKAGE;
}
@Override
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
return null; // Never happens
}
}
/* (non-Javadoc)
* For debug purposes only
*/
@Override
public String toString() {
return getName();
}

View file

@ -24,21 +24,19 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
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.ICPPScope;
/**
* Represents a C++ class for which we don't yet have a complete declaration.
* Represents a C++ class, declaration of which is not yet available.
*
* @author aniefer
*/
public class CPPUnknownClass extends CPPUnknownBinding implements ICPPClassType {
/**
* @param scope
* @param name
*/
public CPPUnknownClass(ICPPScope scope, IBinding scopeBinding, IASTName name) {
super(scope, scopeBinding, name);
public CPPUnknownClass(ICPPInternalUnknown scopeBinding, IASTName name) {
super(scopeBinding, name);
}
/* (non-Javadoc)

View file

@ -10,34 +10,31 @@
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.ObjectMap;
/*
* Represents a C++ class template for which we don't yet have a complete declaration.
* Represents a partially instantiated C++ class template, declaration of which is not yet available.
*
* @author Sergey Prigogin
*/
public class CPPUnknownClassTemplate extends CPPUnknownClass
implements ICPPClassTemplate, ICPPInternalClassTemplate {
public class CPPUnknownClassInstance extends CPPUnknownClass implements ICPPInternalUnknownClassInstance {
private ICPPClassTemplatePartialSpecialization[] partialSpecializations;
private ObjectMap instances;
private final IType[] arguments;
public CPPUnknownClassTemplate(ICPPScope scope, IBinding scopeBinding, IASTName name) {
super(scope, scopeBinding, name);
public CPPUnknownClassInstance(ICPPInternalUnknown scopeBinding, IASTName name, IType[] arguments) {
super(scopeBinding, name);
this.arguments = arguments;
}
public ICPPClassTemplatePartialSpecialization[] getPartialSpecializations()
@ -78,7 +75,7 @@ public class CPPUnknownClassTemplate extends CPPUnknownClass
public ICPPSpecialization getInstance(IType[] arguments) {
if (instances == null)
return null;
for (int i = 0; i < instances.size(); i++) {
IType[] args = (IType[]) instances.keyAt(i);
if (args.length == arguments.length) {
@ -99,28 +96,29 @@ public class CPPUnknownClassTemplate extends CPPUnknownClass
return deferredInstance(arguments);
}
public IType[] getArguments() {
return arguments;
}
@Override
public IBinding resolveUnknown(ObjectMap argMap) throws DOMException {
IBinding result = super.resolveUnknown(argMap);
IType[] newArgs = new IType[arguments.length];
for (int i = 0; i < newArgs.length; i++) {
newArgs[i] = CPPTemplates.instantiateType(arguments[i], argMap);
}
if (result instanceof ICPPSpecialization) {
ICPPSpecialization specialization = (ICPPSpecialization) result;
IASTNode parent = name.getParent();
if (parent instanceof ICPPASTTemplateId) {
IBinding binding = ((ICPPASTTemplateId) parent).resolveBinding();
if (binding instanceof ICPPInternalDeferredClassInstance) {
// This is a hack to get proper arguments for the template instantiation.
// A proper solution should probably be implemented inside
// CPPTemplates.instantiateTemplate, but I don't know how to do it.
// When making any changes to this code please make sure to run
// AST2TemplateTests.testRebindPattern_214447* tests.
IType type = ((ICPPInternalDeferredClassInstance) binding).instantiate(argMap);
IType[] arguments = ((ICPPTemplateInstance) type).getArguments();
ICPPTemplateDefinition template =
(ICPPTemplateDefinition) specialization.getSpecializedBinding();
result = CPPTemplates.instantiateTemplate(template, arguments, null);
}
}
result = CPPTemplates.instantiateTemplate((ICPPTemplateDefinition) specialization, newArgs, null);
} else {
result = new CPPUnknownClassInstance(scopeBinding, name, newArgs);
}
return result;
}
@Override
public String toString() {
return getName() + " <" + ASTTypeUtil.getTypeListString(arguments) + ">"; //$NON-NLS-1$ //$NON-NLS-2$
}
}

View file

@ -23,6 +23,7 @@ import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope;
import org.eclipse.cdt.core.index.IIndexFileSet;
@ -35,11 +36,11 @@ import org.eclipse.cdt.internal.core.dom.parser.IASTInternalScope;
* @author aniefer
*/
public class CPPUnknownScope implements ICPPScope, IASTInternalScope {
private IBinding binding;
private IASTName scopeName;
private final ICPPInternalUnknown binding;
private final IASTName scopeName;
private CharArrayObjectMap map;
public CPPUnknownScope(IBinding binding, IASTName name) {
public CPPUnknownScope(ICPPInternalUnknown binding, IASTName name) {
super();
this.scopeName = name;
this.binding = binding;
@ -105,9 +106,16 @@ public class CPPUnknownScope implements ICPPScope, IASTInternalScope {
return (IBinding) map.get(c);
}
IBinding b = name.getParent() instanceof ICPPASTTemplateId ?
new CPPUnknownClassTemplate(this, binding, name) :
new CPPUnknownClass(this, binding, name);
IBinding b;
IASTNode parent = name.getParent();
if (parent instanceof ICPPASTTemplateId) {
IASTNode[] args = ((ICPPASTTemplateId) parent).getTemplateArguments();
IType[] arguments = CPPTemplates.createTypeArray(args);
b = new CPPUnknownClassInstance(binding, name, arguments);
} else {
b = new CPPUnknownClass(binding, name);
}
name.setBinding(b);
map.put(c, b);
return b;

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2007 IBM Corporation and others.
* Copyright (c) 2007, 2008 IBM Corporation 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
@ -17,5 +17,5 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecialization;
*
*/
public interface ICPPInternalClassTemplate extends ICPPInternalTemplate {
public void addPartialSpecialization( ICPPClassTemplatePartialSpecialization spec );
public void addPartialSpecialization(ICPPClassTemplatePartialSpecialization spec);
}

View file

@ -19,8 +19,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
/**
* @author aniefer
*
*/
public interface ICPPInternalTemplate extends ICPPInternalBinding, ICPPInternalTemplateInstantiator {
public void addSpecialization( IType [] arguments, ICPPSpecialization specialization );
public void addSpecialization(IType[] arguments, ICPPSpecialization specialization);
}

View file

@ -30,5 +30,5 @@ public interface ICPPInternalUnknown extends ICPPInternalBinding {
* @return
* @throws DOMException
*/
public IBinding resolveUnknown( ObjectMap argMap ) throws DOMException;
public IBinding resolveUnknown(ObjectMap argMap) throws DOMException;
}

View file

@ -0,0 +1,24 @@
/*******************************************************************************
* Copyright (c) 2008 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.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate;
/*
* Represents a partially instantiated C++ class template, declaration of which is not yet available.
*
* @author Sergey Prigogin
*/
public interface ICPPInternalUnknownClassInstance extends ICPPClassTemplate, ICPPInternalUnknown,
ICPPInternalClassTemplate {
public IType[] getArguments();
}