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

Resolution of template parameters in two phases, bug 252554.

This commit is contained in:
Markus Schorn 2008-11-04 08:55:46 +00:00
parent 98a2fa70c3
commit b64db6fe09
31 changed files with 421 additions and 403 deletions

View file

@ -111,7 +111,7 @@ import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPPointerToMemberType;
import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPPointerType;
import org.eclipse.cdt.core.parser.ParserLanguage;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.dom.parser.cpp.AbstractCPPASTName;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTNameBase;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
import org.eclipse.cdt.internal.core.dom.parser.cpp.OverloadableOperator;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
@ -1671,7 +1671,7 @@ public class AST2CPPTests extends AST2BaseTest {
// };
public void testBug84692() throws Exception {
// also tests bug 234042.
AbstractCPPASTName.sAllowRecursionBindings= false;
CPPASTNameBase.sAllowRecursionBindings= false;
IASTTranslationUnit tu = parse(getAboveComment(), ParserLanguage.CPP);
CPPNameCollector col = new CPPNameCollector();

View file

@ -2940,16 +2940,17 @@ public class AST2TemplateTests extends AST2BaseTest {
// These intermediate assertions will not hold until deferred non-type arguments are
// correctly modelled
/*
ICPPClassType tid= ba.assertNonProblem("This<I>::T", 7, ICPPClassType.class);
assertFalse(tid instanceof ICPPSpecialization);
ICPPConstructor th1sCtor= ba.assertNonProblem("This() :", 4, ICPPConstructor.class);
assertFalse(th1sCtor instanceof ICPPSpecialization);ICPPTemplateNonTypeParameter np= ba.assertNonProblem("I)", 1, ICPPTemplateNonTypeParameter.class);
*/
assertFalse(th1sCtor instanceof ICPPSpecialization);
ICPPTemplateNonTypeParameter np= ba.assertNonProblem("I>(I)", 1, ICPPTemplateNonTypeParameter.class);
ICPPTemplateNonTypeParameter np = ba.assertNonProblem("I>(I)", 1, ICPPTemplateNonTypeParameter.class);
ICPPClassType clazz= ba.assertNonProblem("That<I>(I)", 4, ICPPClassType.class);
ICPPConstructor ctor= ba.assertNonProblem("That<I>(I)", 7, ICPPConstructor.class);
ICPPTemplateNonTypeParameter np1 = ba.assertNonProblem("I)", 1, ICPPTemplateNonTypeParameter.class);
assertSame(np, np1);
}
// template<typename I>

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2006, 2007 Wind River Systems, Inc. and others.
* Copyright (c) 2006, 2008 Wind River Systems, 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
@ -9,7 +9,6 @@
* Markus Schorn - initial API and implementation
* Andrew Ferguson (Symbian)
*******************************************************************************/
package org.eclipse.cdt.core.testplugin.util;
import java.lang.reflect.Method;
@ -32,7 +31,7 @@ import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.ElementChangedEvent;
import org.eclipse.cdt.core.model.IElementChangedListener;
import org.eclipse.cdt.core.testplugin.TestScannerProvider;
import org.eclipse.cdt.internal.core.dom.parser.cpp.AbstractCPPASTName;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTNameBase;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.ILogListener;
import org.eclipse.core.runtime.IProgressMonitor;
@ -57,7 +56,7 @@ public class BaseTestCase extends TestCase {
@Override
protected void setUp() throws Exception {
AbstractCPPASTName.sAllowRecursionBindings= true;
CPPASTNameBase.sAllowRecursionBindings= true;
}
@Override

View file

@ -6,13 +6,17 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
* Doug Schaefer (IBM) - Initial API and implementation
* Sergey Prigogin (Google)
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.core.dom.ast;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTypeParameter;
/**
* @author Doug Schaefer
* Interface for all c- and c++ types.
*/
public interface IType extends Cloneable {
public static final IType[] EMPTY_TYPE_ARRAY = new IType[0];
@ -21,8 +25,10 @@ public interface IType extends Cloneable {
public Object clone();
/**
* is the given type the same as this type?
* @param type
* Test whether this type is the same as the given one. A typedef is considered to be the same type as
* it's target type.
* See {@link ICPPTemplateTemplateParameter#isSameType(IType)} or {@link ICPPTemplateTypeParameter#isSameType(IType)}
* for the semantics of comparing template parameters denoting types.
*/
public boolean isSameType(IType type);
}

View file

@ -37,7 +37,7 @@ public interface ICPPClassTemplatePartialSpecialization extends ICPPClassTemplat
* Returns the arguments of this partial specialization.
* @since 5.1
*/
public ICPPTemplateArgument[] getTemplateArguments();
public ICPPTemplateArgument[] getTemplateArguments() throws DOMException;
/**
* @deprecated use {@link #getTemplateArguments()}, instead.

View file

@ -15,6 +15,8 @@ import org.eclipse.cdt.core.dom.ast.IType;
/**
* Template parameters of type template
*
* @noimplement This interface is not intended to be implemented by clients.
*/
public interface ICPPTemplateTemplateParameter extends ICPPTemplateParameter, ICPPClassTemplate {
@ -24,4 +26,14 @@ public interface ICPPTemplateTemplateParameter extends ICPPTemplateParameter, IC
* Return the default value for this parameter, or <code>null</code>.
*/
public IType getDefault() throws DOMException;
/**
* Types containing template parameters need to be compared even before it is known to which
* binding the template parameter belongs to. Therefore {@link #isSameType(IType)} compares the
* kind and the parameter position of the template parameter, only. The name and the owner
* is ignored.
*
* @since 5.1
*/
public boolean isSameType(IType type);
}

View file

@ -24,4 +24,13 @@ public interface ICPPTemplateTypeParameter extends ICPPTemplateParameter, IType
*/
public IType getDefault() throws DOMException;
/**
* Types containing template parameters need to be compared even before it is known to which
* binding the template parameter belongs to. Therefore {@link #isSameType(IType)} compares the
* kind and the parameter position of the template parameter, only. The name and the owner
* is ignored.
*
* @since 5.1
*/
public boolean isSameType(IType type);
}

View file

@ -19,6 +19,7 @@ import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTNameBase;
/**
* Base implementation for all ambiguous nodes.
@ -94,7 +95,7 @@ public abstract class ASTAmbiguousNode extends ASTNode {
int issues= 0;
for (IASTName name : names) {
try {
IBinding b = name.resolveBinding();
IBinding b= CPPASTNameBase.resolvePreBinding(name);
if (b instanceof IProblemBinding) {
issues++;
}

View file

@ -28,6 +28,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLiteralExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBinding;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTNameBase;
import org.eclipse.cdt.internal.core.parser.scanner.ExpressionEvaluator;
import org.eclipse.cdt.internal.core.parser.scanner.ExpressionEvaluator.EvalException;
@ -199,7 +200,7 @@ public class Value implements IValue {
return o + "," + evaluate(cexpr.getNegativeResultExpression(), maxdepth) + "," + po + '?';
}
if (e instanceof IASTIdExpression) {
IBinding b= ((IASTIdExpression) e).getName().resolveBinding();
IBinding b= CPPASTNameBase.resolvePreBinding(((IASTIdExpression) e).getName());
if (b instanceof ICPPTemplateParameter) {
if (b instanceof ICPPTemplateNonTypeParameter) {
return evaluate((ICPPTemplateParameter) b);

View file

@ -17,6 +17,7 @@ import java.util.List;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTAmbiguousTemplateArgument;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
import org.eclipse.cdt.internal.core.parser.ParserMessages;
@ -25,6 +26,7 @@ import org.eclipse.cdt.internal.core.parser.ParserMessages;
* Ambiguity node for deciding between type-id and id-expression in a template argument.
*/
public class CPPASTAmbiguousTemplateArgument extends CPPASTAmbiguity implements ICPPASTAmbiguousTemplateArgument {
private List<IASTNode> fNodes;
/**
@ -46,7 +48,13 @@ public class CPPASTAmbiguousTemplateArgument extends CPPASTAmbiguity implements
}
}
}
@Override
protected IScope getAffectedScope() {
// a template argument does not introduce names to a parent scope.
return null;
}
@Override
protected IASTNode[] getNodes() {
return fNodes.toArray(new IASTNode[fNodes.size()]);

View file

@ -37,7 +37,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
/**
* Unqualified name, also base class for operator and conversion name.
*/
public class CPPASTName extends AbstractCPPASTName implements IASTCompletionContext {
public class CPPASTName extends CPPASTNameBase implements IASTCompletionContext {
private char[] name;
public CPPASTName(char[] name) {
this.name = name;

View file

@ -21,7 +21,7 @@ import org.eclipse.core.runtime.Assert;
* Common base class for all sorts of c++ names: unqualified, qualified, operator and conversion
* names plus template-ids
*/
public abstract class AbstractCPPASTName extends ASTNode implements IASTName {
public abstract class CPPASTNameBase extends ASTNode implements IASTName {
/**
* For test-purposes, only.
@ -39,23 +39,25 @@ public abstract class AbstractCPPASTName extends ASTNode implements IASTName {
/**
* Helper method to resolve intermediate bindings without casting the name.
*/
public static IBinding resolveIntermediateBinding(IASTName name) {
public static IBinding resolvePreBinding(IASTName name) {
if (name == null)
return null;
if (name instanceof AbstractCPPASTName)
return ((AbstractCPPASTName) name).resolveIntermediateBinding();
if (name instanceof CPPASTNameBase)
return ((CPPASTNameBase) name).resolvePreBinding();
return name.resolveBinding();
}
/**
* Helper method to get intermediate bindings without casting the name.
*/
public static IBinding getIntermediateBinding(IASTName name) {
public static IBinding getPreBinding(IASTName name) {
if (name == null)
return null;
if (name instanceof AbstractCPPASTName)
return ((AbstractCPPASTName) name).getIntermediateBinding();
return name.resolveBinding();
if (name instanceof CPPASTNameBase)
return ((CPPASTNameBase) name).getPreBinding();
return name.getBinding();
}
private IBinding fBinding = null;
@ -78,7 +80,7 @@ public abstract class AbstractCPPASTName extends ASTNode implements IASTName {
* Resolves the name at least up to the intermediate binding and returns it.
* @see ICPPTwoPhaseBinding
*/
public IBinding resolveIntermediateBinding() {
public IBinding resolvePreBinding() {
if (fBinding == null) {
if (++fResolutionDepth > MAX_RESOLUTION_DEPTH) {
fBinding= new RecursionResolvingBinding(this);
@ -94,11 +96,12 @@ public abstract class AbstractCPPASTName extends ASTNode implements IASTName {
if (++fResolutionDepth > MAX_RESOLUTION_DEPTH) {
fBinding= new RecursionResolvingBinding(this);
} else {
fIsFinal= false;
fBinding= createIntermediateBinding();
}
}
if (!fIsFinal)
resolveFinalBinding();
resolveFinalBinding(this);
return fBinding;
}
@ -108,7 +111,7 @@ public abstract class AbstractCPPASTName extends ASTNode implements IASTName {
* Otherwise the intermediate or final binding for this name is returned.
* @see ICPPTwoPhaseBinding
*/
public IBinding getIntermediateBinding() {
public IBinding getPreBinding() {
final IBinding cand= fBinding;
if (cand == null)
return null;
@ -122,23 +125,22 @@ public abstract class AbstractCPPASTName extends ASTNode implements IASTName {
return null;
if (!fIsFinal)
resolveFinalBinding();
resolveFinalBinding(this);
return fBinding;
}
private void resolveFinalBinding() {
private void resolveFinalBinding(CPPASTNameBase astName) {
if (fBinding instanceof ICPPTwoPhaseBinding) {
ICPPTwoPhaseBinding lazyBinding= (ICPPTwoPhaseBinding) fBinding;
ICPPTwoPhaseBinding intermediateBinding= (ICPPTwoPhaseBinding) fBinding;
if (++fResolutionDepth > MAX_RESOLUTION_DEPTH) {
fBinding= new RecursionResolvingBinding(this);
} else {
IBinding finalBinding= lazyBinding.resolveFinalBinding();
assert finalBinding.getClass().equals(lazyBinding.getClass());
IBinding finalBinding= intermediateBinding.resolveFinalBinding(astName);
fBinding= finalBinding;
}
}
fIsFinal= true;
}

View file

@ -45,7 +45,7 @@ import org.eclipse.core.runtime.Assert;
* Qualified name, which can contain any other name (unqualified, operator-name, conversion name,
* template id).
*/
public class CPPASTQualifiedName extends AbstractCPPASTName
public class CPPASTQualifiedName extends CPPASTNameBase
implements ICPPASTQualifiedName, IASTCompletionContext {
private IASTName[] names = null;
@ -57,9 +57,9 @@ public class CPPASTQualifiedName extends AbstractCPPASTName
}
@Override
public final IBinding resolveIntermediateBinding() {
public final IBinding resolvePreBinding() {
// The full qualified name resolves to the same thing as the last name
return resolveIntermediateBinding(getLastName());
return resolvePreBinding(getLastName());
}
@Override
@ -70,9 +70,9 @@ public class CPPASTQualifiedName extends AbstractCPPASTName
}
@Override
public final IBinding getIntermediateBinding() {
public final IBinding getPreBinding() {
// The full qualified name resolves to the same thing as the last name
return getIntermediateBinding(getLastName());
return getPreBinding(getLastName());
}
@Override

View file

@ -34,7 +34,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates;
* Template ids consist of an unqualified name (or operator or conversion name)
* and an array of template arguments.
*/
public class CPPASTTemplateId extends AbstractCPPASTName implements ICPPASTTemplateId, IASTAmbiguityParent {
public class CPPASTTemplateId extends CPPASTNameBase implements ICPPASTTemplateId, IASTAmbiguityParent {
private IASTName templateName;
private IASTNode[] templateArguments = null;
public CPPASTTemplateId() {

View file

@ -12,6 +12,7 @@
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.IBinding;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
@ -35,7 +36,7 @@ public class CPPClassTemplatePartialSpecialization extends CPPClassTemplate
super(name);
}
public ICPPTemplateArgument[] getTemplateArguments() {
public ICPPTemplateArgument[] getTemplateArguments() throws DOMException {
if (arguments == null) {
arguments= CPPTemplates.createTemplateArgumentArray((ICPPASTTemplateId) getTemplateName());
}
@ -55,12 +56,20 @@ public class CPPClassTemplatePartialSpecialization extends CPPClassTemplate
}
public ICPPTemplateParameterMap getTemplateParameterMap() {
return CPPTemplates.createParameterMap(getPrimaryClassTemplate(), getTemplateArguments());
try {
return CPPTemplates.createParameterMap(getPrimaryClassTemplate(), getTemplateArguments());
} catch (DOMException e) {
return CPPTemplateParameterMap.EMPTY;
}
}
@Override
public String toString() {
return super.toString() + '<' + ASTTypeUtil.getArgumentListString(getTemplateArguments(), true) + '>';
try {
return super.toString() + '<' + ASTTypeUtil.getArgumentListString(getTemplateArguments(), true) + '>';
} catch (DOMException e) {
return super.toString() + '<' + e.getProblem().toString() + '>';
}
}
@Deprecated
@ -69,7 +78,7 @@ public class CPPClassTemplatePartialSpecialization extends CPPClassTemplate
}
@Deprecated
public IType[] getArguments() {
public IType[] getArguments() throws DOMException {
return CPPTemplates.getArguments(getTemplateArguments());
}
}

View file

@ -14,6 +14,7 @@ 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.IBinding;
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.ICPPClassType;
@ -39,6 +40,7 @@ public class CPPClassTemplateSpecialization extends CPPClassSpecialization
* @see org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate#getPartialSpecializations()
*/
public ICPPClassTemplatePartialSpecialization[] getPartialSpecializations() throws DOMException {
// mstodo the partial specializations need to be specialized
return ((ICPPClassTemplate) getSpecializedBinding()).getPartialSpecializations();
}
@ -77,11 +79,25 @@ public class CPPClassTemplateSpecialization extends CPPClassSpecialization
}
public void addPartialSpecialization(ICPPClassTemplatePartialSpecialization spec) {
//should not occur mstodo- why not??
// mstodo partial specializations for class template specializations.
// this is legal code:
// template<typename T> class CT {
// template<typename S> class NT {
// };
// };
// // creates a partial spec for the specialization of CT::NT
// template<> template<typename S> class CT<char>::NT<S*> {
// public:
// int spec;
// };
}
@Override
public String toString() {
return getName();
}
public IBinding resolveTemplateParameter(ICPPTemplateParameter param) {
return param;
}
}

View file

@ -64,4 +64,8 @@ public class CPPFunctionTemplateSpecialization extends CPPFunctionSpecialization
}
return ICPPTemplateInstance.EMPTY_TEMPLATE_INSTANCE_ARRAY;
}
public IBinding resolveTemplateParameter(ICPPTemplateParameter param) {
return param;
}
}

View file

@ -25,9 +25,7 @@ import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleTypeTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecialization;
@ -124,71 +122,6 @@ public abstract class CPPTemplateDefinition extends PlatformObject implements IC
}
return ICPPTemplateInstance.EMPTY_TEMPLATE_INSTANCE_ARRAY;
}
public IBinding resolveTemplateParameter(ICPPASTTemplateParameter templateParameter) {
IASTName name = CPPTemplates.getTemplateParameterName(templateParameter);
IASTName preferredName= name;
IBinding binding = name.getBinding();
if (binding != null)
return binding;
ICPPASTTemplateDeclaration templateDecl = (ICPPASTTemplateDeclaration) templateParameter.getParent();
ICPPASTTemplateParameter[] ps = templateDecl.getTemplateParameters();
int i = 0;
for (; i < ps.length; i++) {
if (templateParameter == ps[i])
break;
}
if (definition != null || (declarations != null && declarations.length > 0)) {
IASTName templateName = (definition != null) ? definition : declarations[0];
ICPPASTTemplateDeclaration temp = CPPTemplates.getTemplateDeclaration(templateName);
ICPPASTTemplateParameter[] params = temp.getTemplateParameters();
if (params.length > i) {
IASTName paramName = CPPTemplates.getTemplateParameterName(params[i]);
preferredName= paramName;
if (paramName.getBinding() != null) {
binding = paramName.getBinding();
name.setBinding(binding);
if(binding instanceof ICPPInternalBinding)
((ICPPInternalBinding)binding).addDeclaration(name);
return binding;
}
}
}
//create a new binding and set it for the corresponding parameter in all known decls
if (templateParameter instanceof ICPPASTSimpleTypeTemplateParameter) {
binding = new CPPTemplateTypeParameter(preferredName);
} else if (templateParameter instanceof ICPPASTParameterDeclaration) {
binding = new CPPTemplateNonTypeParameter(preferredName);
} else {
binding = new CPPTemplateTemplateParameter(preferredName);
}
int length = (declarations != null) ? declarations.length : 0;
int j = (definition != null) ? -1 : 0;
for (; j < length; j++) {
ICPPASTTemplateDeclaration template = (j == -1)
? CPPTemplates.getTemplateDeclaration(definition)
: CPPTemplates.getTemplateDeclaration(declarations[j]);
if (template == null)
continue;
ICPPASTTemplateParameter[] temp = template.getTemplateParameters();
if (temp.length <= i)
continue;
IASTName n = CPPTemplates.getTemplateParameterName(temp[i]);
if (n != null && n != name && n.getBinding() == null) {
n.setBinding(binding);
if (binding instanceof ICPPInternalBinding)
((ICPPInternalBinding)binding).addDeclaration(n);
}
}
return binding;
}
public IASTName getTemplateName() {
if (definition != null)
@ -313,20 +246,59 @@ public abstract class CPPTemplateDefinition extends PlatformObject implements IC
}
ArrayUtil.remove(declarations, node);
}
protected void updateTemplateParameterBindings(IASTName name) {
IASTName orig = definition != null ? definition : declarations[0];
ICPPASTTemplateDeclaration origTemplate = CPPTemplates.getTemplateDeclaration(orig);
ICPPASTTemplateDeclaration newTemplate = CPPTemplates.getTemplateDeclaration(name);
ICPPASTTemplateParameter[] ops = origTemplate.getTemplateParameters();
ICPPASTTemplateParameter[] nps = newTemplate.getTemplateParameters();
ICPPInternalBinding temp = null;
int end= Math.min(ops.length, nps.length);
for (int i = 0; i < end; i++) {
temp = (ICPPInternalBinding) CPPTemplates.getTemplateParameterName(ops[i]).getBinding();
if (temp != null) {
IASTName n = CPPTemplates.getTemplateParameterName(nps[i]);
n.setBinding(temp);
temp.addDeclaration(n);
public IBinding resolveTemplateParameter(ICPPTemplateParameter templateParameter) {
int pos= templateParameter.getParameterPosition() & 0xff;
int tdeclLen= declarations == null ? 0 : declarations.length;
for (int i=-1; i<tdeclLen; i++) {
IASTName tdecl;
if (i == -1) {
tdecl= definition;
if (tdecl == null)
continue;
} else {
tdecl= declarations[i];
if (tdecl == null)
break;
}
ICPPASTTemplateParameter[] params = CPPTemplates.getTemplateDeclaration(tdecl).getTemplateParameters();
if (pos < params.length) {
final IASTName oName = CPPTemplates.getTemplateParameterName(params[pos]);
return CPPASTNameBase.resolvePreBinding(oName);
}
}
return templateParameter;
}
final protected void updateTemplateParameterBindings(IASTName name) {
ICPPASTTemplateParameter[] updateParams = CPPTemplates.getTemplateDeclaration(name).getTemplateParameters();
int k=0;
int tdeclLen= declarations == null ? 0 : declarations.length;
for (int i=-1; i<tdeclLen && k<updateParams.length; i++) {
IASTName tdecl;
if (i == -1) {
tdecl= definition;
if (tdecl == null)
continue;
} else {
tdecl= declarations[i];
if (tdecl == null)
break;
}
ICPPASTTemplateParameter[] params = CPPTemplates.getTemplateDeclaration(tdecl).getTemplateParameters();
int end= Math.min(params.length, updateParams.length);
for (; k < end; k++) {
final IASTName oName = CPPTemplates.getTemplateParameterName(params[k]);
IBinding b= CPPASTNameBase.resolvePreBinding(oName);
IASTName n = CPPTemplates.getTemplateParameterName(updateParams[k]);
n.setBinding(b);
if (b instanceof ICPPInternalBinding) {
((ICPPInternalBinding) b).addDeclaration(n);
}
}
}
}

View file

@ -16,15 +16,18 @@ 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.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplatedTypeTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.internal.core.dom.Linkage;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.core.runtime.PlatformObject;
@ -32,13 +35,17 @@ import org.eclipse.core.runtime.PlatformObject;
/**
* Base implementation for template parameter bindings in the AST.
*/
public abstract class CPPTemplateParameter extends PlatformObject implements ICPPTemplateParameter, ICPPInternalBinding {
public abstract class CPPTemplateParameter extends PlatformObject
implements ICPPTemplateParameter, ICPPInternalBinding, ICPPTwoPhaseBinding {
private IASTName [] declarations;
private final int position;
public CPPTemplateParameter(IASTName name) {
declarations = new IASTName[] {name};
position= computeParameterPosition(name);
}
private int computeParameterPosition(IASTName name) {
int pos= -1;
int nesting= -1;
ICPPASTTemplateParameter tp= null;
@ -70,7 +77,7 @@ public abstract class CPPTemplateParameter extends PlatformObject implements ICP
if (pos < 0)
pos= 0;
position= (nesting << 16) + pos;
return (nesting << 16) + pos;
}
@Override
@ -106,6 +113,15 @@ public abstract class CPPTemplateParameter extends PlatformObject implements ICP
public IASTName getPrimaryDeclaration () {
return declarations[0];
}
private ICPPASTTemplateParameter getASTTemplateParameter() {
IASTNode node= declarations[0];
while (node != null && !(node instanceof ICPPASTTemplateParameter))
node= node.getParent();
assert node != null;
return (ICPPASTTemplateParameter) node;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.IBinding#getScope()
*/
@ -204,4 +220,32 @@ public abstract class CPPTemplateParameter extends PlatformObject implements ICP
return CPPTemplates.getContainingTemplate((ICPPASTTemplateParameter) node);
}
public IBinding resolveFinalBinding(CPPASTNameBase name) {
// check if the binding has been updated.
IBinding current= name.getPreBinding();
if (current != this)
return current;
ICPPTemplateDefinition template= CPPTemplates.getContainingTemplate(getASTTemplateParameter());
if (template instanceof ICPPInternalTemplate) {
return ((ICPPInternalTemplate) template).resolveTemplateParameter(this);
}
// problem finding the containing template
if (template == null) {
return this;
}
// use parameter from the index
try {
ICPPTemplateParameter[] params = template.getTemplateParameters();
final int pos= position & 0xff;
if (pos < params.length)
return params[pos];
} catch (DOMException e) {
return e.getProblem();
}
return new ProblemBinding(getPrimaryDeclaration(), IProblemBinding.SEMANTIC_DEFINITION_NOT_FOUND, getNameCharArray());
}
}

View file

@ -22,8 +22,6 @@ import org.eclipse.cdt.core.dom.ast.IField;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleTypeTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplatedTypeTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase;
@ -87,21 +85,8 @@ public class CPPTemplateTemplateParameter extends CPPTemplateParameter implement
return templateParameters;
}
public IBinding resolveTemplateParameter(ICPPASTTemplateParameter templateParameter) {
IASTName name = CPPTemplates.getTemplateParameterName(templateParameter);
IBinding binding = name.getBinding();
if (binding == null) {
//create a new binding and set it for the corresponding parameter in all known decls
if (templateParameter instanceof ICPPASTSimpleTypeTemplateParameter)
binding = new CPPTemplateTypeParameter(name);
else if (templateParameter instanceof ICPPASTParameterDeclaration)
binding = new CPPTemplateNonTypeParameter(name);
else
binding = new CPPTemplateTemplateParameter(name);
name.setBinding(binding);
}
return binding;
public IBinding resolveTemplateParameter(ICPPTemplateParameter templateParameter) {
return templateParameter;
}
public ICPPClassTemplatePartialSpecialization[] getTemplateSpecializations() throws DOMException {
@ -176,12 +161,15 @@ public class CPPTemplateTemplateParameter extends CPPTemplateParameter implement
}
public boolean isSameType(IType type) {
if (type == this)
return true;
if (type instanceof ITypedef)
return ((ITypedef)type).isSameType(this);
return false;
}
if (type == this)
return true;
if (type instanceof ITypedef)
return type.isSameType(this);
if (!(type instanceof ICPPTemplateTemplateParameter))
return false;
return getParameterPosition() == ((ICPPTemplateParameter) type).getParameterPosition();
}
public ICPPClassTemplatePartialSpecialization[] getPartialSpecializations() throws DOMException {
return ICPPClassTemplatePartialSpecialization.EMPTY_PARTIAL_SPECIALIZATION_ARRAY;

View file

@ -6,7 +6,7 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Andrew Niefer (IBM Corporation) - initial API and implementation
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
@ -19,12 +19,12 @@ import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleTypeTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTypeParameter;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.cdt.internal.core.index.IIndexType;
/**
* @author aniefer
* The standard template parameter (template<typename T> or template<class T>).
*/
public class CPPTemplateTypeParameter extends CPPTemplateParameter implements
ICPPTemplateTypeParameter, IType, ICPPUnknownBinding {
@ -68,9 +68,12 @@ public class CPPTemplateTypeParameter extends CPPTemplateParameter implements
public boolean isSameType(IType type) {
if (type == this)
return true;
if (type instanceof ITypedef || type instanceof IIndexType)
if (type instanceof ITypedef)
return type.isSameType(this);
return false;
if (!(type instanceof ICPPTemplateTypeParameter))
return false;
return getParameterPosition() == ((ICPPTemplateParameter) type).getParameterPosition();
}
public IASTName getUnknownName() {

View file

@ -6,7 +6,7 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Andrew Niefer (IBM Corporation) - initial API and implementation
* Markus Schorn (Wind River Systems)
* Bryan Wilkinson (QNX)
* Sergey Prigogin (Google)
@ -31,7 +31,8 @@ import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates;
/**
* @author aniefer
* Models the scope represented by an unknown binding such (e.g.: template type parameter). Used within
* the context of templates, only.
*/
public class CPPUnknownScope implements ICPPScope, ICPPInternalUnknownScope {
private final ICPPUnknownBinding binding;
@ -111,8 +112,12 @@ public class CPPUnknownScope implements ICPPScope, ICPPInternalUnknownScope {
IBinding b;
IASTNode parent = name.getParent();
if (parent instanceof ICPPASTTemplateId) {
ICPPTemplateArgument[] arguments = CPPTemplates.createTemplateArgumentArray((ICPPASTTemplateId) parent);
b = new CPPUnknownClassInstance(binding, name, arguments);
try {
ICPPTemplateArgument[] arguments = CPPTemplates.createTemplateArgumentArray((ICPPASTTemplateId) parent);
b = new CPPUnknownClassInstance(binding, name, arguments);
} catch (DOMException e) {
return e.getProblem();
}
} else {
b = new CPPUnknownClass(binding, name);
}

View file

@ -10,9 +10,14 @@
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
/**
* Interface for templates from the ast.
*/
public interface ICPPInternalTemplate extends ICPPInternalBinding, ICPPInstanceCache {
IBinding resolveTemplateParameter(ICPPTemplateParameter param);
}

View file

@ -17,7 +17,8 @@ import org.eclipse.cdt.core.dom.ast.IBinding;
* by the first step is an intermediate binding that can be replaced in a second
* step before the binding is exposed via public API.
* <p>
* The bindings of the two phases may not be equal, but they must have the <b> same type</b>.
* The bindings of the two phases may not be equal, but they must implement the
* same public interfaces.
* <p>
* This allows for having multiple bindings for one final binding and deferring
* the act of unifying them to a later point in time.
@ -30,7 +31,7 @@ public interface ICPPTwoPhaseBinding extends IBinding {
* {@code this} must be returned.
* <p> Note, that the result of this operation is an instance of
* {@link ICPPTwoPhaseBinding}, however it must resolve to itself using
* {@link #resolveFinalBinding()}.
* {@link #resolveFinalBinding(CPPASTNameBase)}.
*/
ICPPTwoPhaseBinding resolveFinalBinding();
IBinding resolveFinalBinding(CPPASTNameBase astName);
}

View file

@ -133,10 +133,10 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.IASTInternalScope;
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
import org.eclipse.cdt.internal.core.dom.parser.Value;
import org.eclipse.cdt.internal.core.dom.parser.cpp.AbstractCPPASTName;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTFieldReference;
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.CPPASTNameBase;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTranslationUnit;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPCompositeBinding;
@ -170,13 +170,17 @@ public class CPPSemantics {
// Set to true for debugging.
public static boolean traceBindingResolution = false;
public static int traceIndent= 0;
static protected IBinding resolveBinding(IASTName name) {
if (traceBindingResolution) {
System.out.println("Resolving " + name); //$NON-NLS-1$
for (int i = 0; i < traceIndent; i++)
System.out.print(" "); //$NON-NLS-1$
System.out.println("Resolving " + name + ':' + ((ASTNode)name).getOffset()); //$NON-NLS-1$
traceIndent++;
}
if (name instanceof AbstractCPPASTName) {
((AbstractCPPASTName) name).incResolutionDepth();
if (name instanceof CPPASTNameBase) {
((CPPASTNameBase) name).incResolutionDepth();
}
// 1: get some context info off of the name to figure out what kind of lookup we want
@ -202,7 +206,11 @@ public class CPPSemantics {
// 4: post processing
binding = postResolution(binding, data);
if (traceBindingResolution) {
System.out.println("Resolved " + name + " to " + DebugUtil.toStringWithClass(binding)); //$NON-NLS-1$ //$NON-NLS-2$
traceIndent--;
for (int i = 0; i < traceIndent; i++)
System.out.print(" "); //$NON-NLS-1$
System.out.println("Resolved " + name + ':' + ((ASTNode)name).getOffset() + //$NON-NLS-1$
" to " + DebugUtil.toStringWithClass(binding) + ':' + System.identityHashCode(binding)); //$NON-NLS-1$
}
return binding;
}
@ -290,28 +298,27 @@ public class CPPSemantics {
}
if (binding instanceof ICPPClassType && data.considerConstructors) {
ICPPClassType cls = (ICPPClassType) binding;
if (data.astName instanceof ICPPASTTemplateId && cls instanceof ICPPClassTemplate) {
if (data.tu != null) {
ICPPASTTemplateId id = (ICPPASTTemplateId) data.astName;
ICPPTemplateArgument[] args = CPPTemplates.createTemplateArgumentArray(id);
IBinding inst= CPPTemplates.instantiate((ICPPClassTemplate) cls, args);
cls = inst instanceof ICPPClassType && !(inst instanceof ICPPDeferredTemplateInstance) ? (ICPPClassType)inst : cls;
}
}
if (cls != null) {
try {
//force resolution of constructor bindings
IBinding[] ctors = cls.getConstructors();
if (ctors.length > 0 && !(ctors[0] instanceof IProblemBinding)) {
//then use the class scope to resolve which one.
binding = ((ICPPClassScope)cls.getCompositeScope()).getBinding(data.astName, true);
}
} catch (DOMException e) {
binding = e.getProblem();
}
}
try {
ICPPClassType cls = (ICPPClassType) binding;
if (data.astName instanceof ICPPASTTemplateId && cls instanceof ICPPClassTemplate) {
if (data.tu != null) {
ICPPASTTemplateId id = (ICPPASTTemplateId) data.astName;
ICPPTemplateArgument[] args = CPPTemplates.createTemplateArgumentArray(id);
IBinding inst= CPPTemplates.instantiate((ICPPClassTemplate) cls, args);
cls = inst instanceof ICPPClassType && !(inst instanceof ICPPDeferredTemplateInstance) ? (ICPPClassType)inst : cls;
}
}
if (cls != null) {
//force resolution of constructor bindings
IBinding[] ctors = cls.getConstructors();
if (ctors.length > 0 && !(ctors[0] instanceof IProblemBinding)) {
//then use the class scope to resolve which one.
binding = ((ICPPClassScope)cls.getCompositeScope()).getBinding(data.astName, true);
}
}
} catch (DOMException e) {
binding = e.getProblem();
}
}
// mstodo this looks like a hack?
@ -1563,7 +1570,7 @@ public class CPPSemantics {
if (bindings[0] instanceof IBinding) {
candidate= (IBinding) bindings[0];
} else if (bindings[0] instanceof IASTName) {
candidate= ((IASTName) bindings[0]).getBinding();
candidate= CPPASTNameBase.getPreBinding((IASTName) bindings[0]);
} else {
return null;
}
@ -1718,7 +1725,11 @@ public class CPPSemantics {
}
if (o instanceof IASTName) {
IASTName on= (IASTName) o;
temp = checkResolvedNamesOnly ? on.getBinding() : on.resolveBinding();
if (checkResolvedNamesOnly) {
temp = CPPASTNameBase.getPreBinding(on);
} else {
temp= CPPASTNameBase.resolvePreBinding(on);
}
if (temp == null)
continue;
} else if (o instanceof IBinding) {

View file

@ -30,7 +30,6 @@ import org.eclipse.cdt.core.dom.ast.IASTName;
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.IASTStatement;
import org.eclipse.cdt.core.dom.ast.IArrayType;
import org.eclipse.cdt.core.dom.ast.IBasicType;
import org.eclipse.cdt.core.dom.ast.IBinding;
@ -44,7 +43,6 @@ import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.IValue;
import org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier;
@ -116,8 +114,10 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPQualifierType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateArgument;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateDefinition;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateNonTypeParameter;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateParameterMap;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateTemplateParameter;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateTypeParameter;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTypedefSpecialization;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownClass;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownClassInstance;
@ -399,42 +399,17 @@ public class CPPTemplates {
}
public static IBinding createBinding(ICPPASTTemplateParameter templateParameter) {
// mstodo allow incomplete bindings
ICPPTemplateDefinition template = getContainingTemplate(templateParameter);
IBinding binding = null;
if (template instanceof CPPTemplateTemplateParameter) {
binding = ((CPPTemplateTemplateParameter) template).resolveTemplateParameter(templateParameter);
} else if (template instanceof CPPTemplateDefinition) {
binding = ((CPPTemplateDefinition) template).resolveTemplateParameter(templateParameter);
} else if (template != null) {
IASTName name = CPPTemplates.getTemplateParameterName(templateParameter);
binding = name.getBinding();
if (binding == null) {
ICPPASTTemplateDeclaration templateDecl = (ICPPASTTemplateDeclaration) templateParameter.getParent();
ICPPASTTemplateParameter[] ps = templateDecl.getTemplateParameters();
int i = 0;
for (; i < ps.length; i++) {
if (templateParameter == ps[i])
break;
}
try {
ICPPTemplateParameter[] params = template.getTemplateParameters();
if (i < params.length) {
binding = params[i];
name.setBinding(binding);
}
} catch (DOMException e) {
}
}
}
return binding;
if (templateParameter instanceof ICPPASTSimpleTypeTemplateParameter) {
return new CPPTemplateTypeParameter(((ICPPASTSimpleTypeTemplateParameter) templateParameter).getName());
}
if (templateParameter instanceof ICPPASTTemplatedTypeTemplateParameter) {
return new CPPTemplateTemplateParameter(((ICPPASTTemplatedTypeTemplateParameter) templateParameter).getName());
}
assert templateParameter instanceof ICPPASTParameterDeclaration;
final IASTDeclarator dtor = ((ICPPASTParameterDeclaration) templateParameter).getDeclarator();
return new CPPTemplateNonTypeParameter(CPPVisitor.findInnermostDeclarator(dtor).getName());
}
static public ICPPScope getContainingScope(IASTNode node) {
while (node != null) {
if (node instanceof ICPPASTTemplateParameter) {
@ -479,45 +454,44 @@ public class CPPTemplates {
} else if (parent instanceof ICPPASTFunctionDeclarator && segment != 0) {
return createFunctionSpecialization(id);
}
//a reference: class or function template?
IBinding template = null;
if (parent instanceof ICPPASTNamedTypeSpecifier ||
parent instanceof ICPPASTElaboratedTypeSpecifier ||
parent instanceof ICPPASTBaseSpecifier ||
segment == 0) {
//class template
IASTName templateName = id.getTemplateName();
template = templateName.resolveBinding();
if (template instanceof ICPPClassTemplatePartialSpecialization) {
//specializations are selected during the instantiation, start with the primary template
try {
template = ((ICPPClassTemplatePartialSpecialization) template).getPrimaryClassTemplate();
} catch (DOMException e) {
return e.getProblem();
}
} else if (template instanceof ICPPSpecialization && !(template instanceof ICPPTemplateDefinition)) {
template = ((ICPPSpecialization) template).getSpecializedBinding();
}
if (template instanceof ICPPTemplateDefinition) {
ICPPTemplateArgument[] args= CPPTemplates.createTemplateArgumentArray(id);
IBinding instance= instantiate((ICPPTemplateDefinition) template, args);
return CPPSemantics.postResolution(instance, id);
}
} else {
//functions are instantiated as part of the resolution process
template = CPPVisitor.createBinding(id);
if (template instanceof ICPPTemplateInstance) {
IASTName templateName = id.getTemplateName();
templateName.setBinding(((ICPPTemplateInstance) template).getTemplateDefinition());
}
}
return template;
} catch (DOMException e) {
return e.getProblem();
}
//a reference: class or function template?
IBinding template = null;
if (parent instanceof ICPPASTNamedTypeSpecifier ||
parent instanceof ICPPASTElaboratedTypeSpecifier ||
parent instanceof ICPPASTBaseSpecifier ||
segment == 0) {
//class template
IASTName templateName = id.getTemplateName();
template = templateName.resolveBinding();
if (template instanceof ICPPClassTemplatePartialSpecialization) {
//specializations are selected during the instantiation, start with the primary template
try {
template = ((ICPPClassTemplatePartialSpecialization) template).getPrimaryClassTemplate();
} catch (DOMException e) {
return e.getProblem();
}
} else if (template instanceof ICPPSpecialization && !(template instanceof ICPPTemplateDefinition)) {
template = ((ICPPSpecialization) template).getSpecializedBinding();
}
if (template instanceof ICPPTemplateDefinition) {
ICPPTemplateArgument[] args= CPPTemplates.createTemplateArgumentArray(id);
IBinding instance= instantiate((ICPPTemplateDefinition) template, args);
return CPPSemantics.postResolution(instance, id);
}
} else {
//functions are instantiated as part of the resolution process
template = CPPVisitor.createBinding(id);
if (template instanceof ICPPTemplateInstance) {
IASTName templateName = id.getTemplateName();
templateName.setBinding(((ICPPTemplateInstance) template).getTemplateDefinition());
}
}
return template;
}
protected static IBinding createExplicitClassInstantiation(ICPPASTElaboratedTypeSpecifier elabSpec) {
@ -528,12 +502,16 @@ public class CPPTemplates {
}
ICPPASTTemplateId id = (ICPPASTTemplateId) name;
IBinding template = id.getTemplateName().resolveBinding();
if (template instanceof ICPPClassTemplate) {
ICPPClassTemplate classTemplate = (ICPPClassTemplate) template;
ICPPTemplateArgument[] args= createTemplateArgumentArray(id);
IBinding binding= instantiate(classTemplate, args);
if (binding != null)
return binding;
try {
if (template instanceof ICPPClassTemplate) {
ICPPClassTemplate classTemplate = (ICPPClassTemplate) template;
ICPPTemplateArgument[] args= createTemplateArgumentArray(id);
IBinding binding= instantiate(classTemplate, args);
if (binding != null)
return binding;
}
} catch (DOMException e) {
return e.getProblem();
}
return new ProblemBinding(elabSpec, IProblemBinding.SEMANTIC_INVALID_TYPE, name.toCharArray());
}
@ -699,7 +677,11 @@ public class CPPTemplates {
ICPPTemplateArgument[] templateArguments = null;
if (name instanceof ICPPASTTemplateId) {
templateArguments= createTemplateArgumentArray((ICPPASTTemplateId) name);
try {
templateArguments= createTemplateArgumentArray((ICPPASTTemplateId) name);
} catch (DOMException e) {
return null;
}
}
int numArgs = (templateArguments != null) ? templateArguments.length : 0;
@ -1169,44 +1151,6 @@ public class CPPTemplates {
return null;
}
private static class ClearBindingAction extends CPPASTVisitor {
public ObjectSet<IBinding> bindings = null;
public ClearBindingAction(ObjectSet<IBinding> bindings) {
shouldVisitNames = true;
shouldVisitStatements = true;
this.bindings = bindings;
}
@Override
public int visit(IASTName name) {
if (name.getBinding() != null) {
IBinding binding = name.getBinding();
boolean clear = bindings.containsKey(name.getBinding());
if (!clear && binding instanceof ICPPTemplateInstance) {
ICPPTemplateArgument[] args = ((ICPPTemplateInstance) binding).getTemplateArguments();
for (ICPPTemplateArgument arg : args) {
IType t= arg.getTypeValue();
if (t instanceof IBinding) {
if (bindings.containsKey((IBinding)t)) {
clear = true;
break;
}
}
}
}
if (clear) {
if (binding instanceof ICPPInternalBinding)
((ICPPInternalBinding) binding).removeDeclaration(name);
name.setBinding(null);
}
}
return PROCESS_CONTINUE;
}
@Override
public int visit(IASTStatement statement) {
return PROCESS_SKIP;
}
}
public static boolean isSameTemplate(ICPPTemplateDefinition definition, IASTName name) {
ICPPTemplateParameter[] defParams = null;
try {
@ -1222,24 +1166,9 @@ public class CPPTemplates {
if (defParams.length != templateParams.length)
return false;
// mstodo interesting side-effect, why not make this more explicit?
ObjectSet<IBinding> bindingsToClear = null;
for (int i = 0; i < templateParams.length; i++) {
IASTName tn = getTemplateParameterName(templateParams[i]);
if (tn.getBinding() != null)
return (tn.getBinding() == defParams[i]);
if (bindingsToClear == null)
bindingsToClear = new ObjectSet<IBinding>(templateParams.length);
tn.setBinding(defParams[i]);
if (defParams[i] instanceof ICPPInternalBinding)
((ICPPInternalBinding) defParams[i]).addDeclaration(tn);
bindingsToClear.put(defParams[i]);
}
boolean result = false;
IASTNode parent = name.getParent();
if (parent instanceof ICPPASTFunctionDeclarator) {
try {
try {
if (parent instanceof ICPPASTFunctionDeclarator) {
IASTParameterDeclaration[] params = ((ICPPASTFunctionDeclarator) parent).getParameters();
IParameter[] ps = ((ICPPFunction) definition).getParameters();
if (ps.length == params.length) {
@ -1247,51 +1176,43 @@ public class CPPTemplates {
for (; i < ps.length; i++) {
IType t1 = CPPVisitor.createType(params[i].getDeclarator());
IType t2 = ps[i].getType();
if (! t1.isSameType(t2)) {
break;
}
if (!t1.isSameType(t2))
return false;
}
if (i == ps.length)
result = true;
return true;
}
} catch (DOMException e) {
}
} else if (parent instanceof IASTDeclSpecifier) {
if (name instanceof ICPPASTTemplateId) {
if (definition instanceof ICPPClassTemplatePartialSpecialization) {
ICPPClassTemplatePartialSpecialization spec = (ICPPClassTemplatePartialSpecialization) definition;
ICPPTemplateArgument[] args= createTemplateArgumentArray((ICPPASTTemplateId)name);
ICPPTemplateArgument[] specArgs = spec.getTemplateArguments();
if (args.length == specArgs.length) {
result= true;
for (int i=0; i < args.length; i++) {
if (!specArgs[i].isSameValue(args[i])) {
result= false;
break;
return false;
}
if (parent instanceof IASTDeclSpecifier) {
if (name instanceof ICPPASTTemplateId) {
if (definition instanceof ICPPClassTemplatePartialSpecialization) {
ICPPClassTemplatePartialSpecialization spec = (ICPPClassTemplatePartialSpecialization) definition;
ICPPTemplateArgument[] args= createTemplateArgumentArray((ICPPASTTemplateId)name);
ICPPTemplateArgument[] specArgs = spec.getTemplateArguments();
if (args.length == specArgs.length) {
for (int i=0; i < args.length; i++) {
if (!specArgs[i].isSameValue(args[i]))
return false;
}
}
}
}
} else {
result = CharArrayUtils.equals(definition.getNameCharArray(), name.toCharArray());
return true;
}
return CharArrayUtils.equals(definition.getNameCharArray(), name.toCharArray());
}
} catch (DOMException e) {
}
// mstodo we should not add the binding in the first place??
if (bindingsToClear != null && !result) {
ClearBindingAction action = new ClearBindingAction(bindingsToClear);
templateDecl.accept(action);
}
return result;
return false;
}
/**
* @param id the template id containing the template arguments
* @return an array of template arguments, currently modeled as IType objects. The
* empty IType array is returned if id is <code>null</code>
* @throws DOMException
*/
static public ICPPTemplateArgument[] createTemplateArgumentArray(ICPPASTTemplateId id) {
static public ICPPTemplateArgument[] createTemplateArgumentArray(ICPPASTTemplateId id) throws DOMException {
ICPPTemplateArgument[] result= ICPPTemplateArgument.EMPTY_ARGUMENTS;
if (id != null) {
IASTNode[] params= id.getTemplateArguments();
@ -1299,12 +1220,8 @@ public class CPPTemplates {
for (int i = 0; i < params.length; i++) {
IASTNode param= params[i];
IType type= CPPVisitor.createType(param);
// prevent null pointer exception when the type cannot be determined
// happens when templates with still ambiguous template-ids are accessed during
// resolution of other template-id ambiguities.
// mstodo: fix by introducing partially resolved template parameters
if (type == null)
type= new CPPBasicType(-1, 0);
throw new DOMException(new ProblemBinding(id, IProblemBinding.SEMANTIC_INVALID_TYPE, id.toCharArray()));
if (param instanceof IASTExpression) {
IValue value= Value.create((IASTExpression) param, Value.MAX_RECURSION_DEPTH);
@ -1361,7 +1278,11 @@ public class CPPTemplates {
int numTemplateArgs = 0;
ICPPTemplateArgument[] templateArguments = null;
if (name instanceof ICPPASTTemplateId) {
templateArguments = createTemplateArgumentArray((ICPPASTTemplateId) name);
try {
templateArguments = createTemplateArgumentArray((ICPPASTTemplateId) name);
} catch (DOMException e) {
return new IFunction[0];
}
numTemplateArgs = templateArguments.length;
}
@ -1829,16 +1750,16 @@ public class CPPTemplates {
* arguments of the partial specialization
*/
static private ICPPFunctionTemplate classTemplateSpecializationToFunctionTemplate(ICPPClassTemplatePartialSpecialization specialization) {
ICPPTemplateDefinition template = specialization;
ICPPTemplateArgument[] args= specialization.getTemplateArguments();
IType paramType = (IType) instantiate(template, args);
if (paramType == null)
return null;
IParameter[] functionParameters = new IParameter[] { new CPPParameter(paramType) };
try {
ICPPTemplateDefinition template = specialization;
ICPPTemplateArgument[] args= specialization.getTemplateArguments();
IType paramType = (IType) instantiate(template, args);
if (paramType == null)
return null;
IParameter[] functionParameters = new IParameter[] { new CPPParameter(paramType) };
return new CPPImplicitFunctionTemplate(specialization.getTemplateParameters(), functionParameters);
} catch (DOMException e) {
return null;

View file

@ -147,6 +147,7 @@ import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer;
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTNameBase;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPArrayType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassTemplate;
@ -1032,7 +1033,7 @@ public class CPPVisitor {
}
if (name != null) {
name= name.getLastName();
IBinding binding = name.getBinding();
IBinding binding = CPPASTNameBase.getPreBinding(name);
if (binding == null) {
binding = CPPSemantics.resolveBinding(name);
name.setBinding(binding);
@ -1678,7 +1679,7 @@ public class CPPVisitor {
}
}
if (name != null) {
IBinding binding = name.resolveBinding();
IBinding binding = CPPASTNameBase.resolvePreBinding(name);
if (binding instanceof ICPPConstructor) {
try {
type= ((ICPPConstructor) binding).getClassOwner();

View file

@ -55,7 +55,13 @@ public class TemplateInstanceUtil {
}
public static ICPPTemplateArgument[] getTemplateArguments(ICompositesFactory cf, ICPPClassTemplatePartialSpecialization rbinding) {
return convert(cf, rbinding.getTemplateArguments());
try {
return convert(cf, rbinding.getTemplateArguments());
} catch (DOMException e) {
// index bindings don't throw DOMExceptions
assert false;
}
return ICPPTemplateArgument.EMPTY_ARGUMENTS;
}
public static IBinding getSpecializedBinding(ICompositesFactory cf, IIndexBinding rbinding) {

View file

@ -169,6 +169,8 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
partial.setArguments(args);
} catch (CoreException e) {
CCorePlugin.log(e);
} catch (DOMException e) {
CCorePlugin.log(e);
} finally {
partial = null;
binding = null;

View file

@ -20,9 +20,9 @@ import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTypeParameter;
import org.eclipse.cdt.internal.core.Util;
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateArgument;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
@ -111,24 +111,11 @@ class PDOMCPPTemplateTypeParameter extends PDOMCPPBinding implements IPDOMMember
if (type instanceof ITypedef) {
return type.isSameType(this);
}
if (type instanceof PDOMNode) {
PDOMNode node= (PDOMNode) type;
if (node.getPDOM() == getPDOM()) {
return node.getRecord() == getRecord();
}
}
if (type instanceof ICPPTemplateTypeParameter && !(type instanceof ProblemBinding)) {
ICPPTemplateTypeParameter ttp= (ICPPTemplateTypeParameter) type;
try {
char[][] ttpName= ttp.getQualifiedNameCharArray();
return hasQualifiedName(ttpName, ttpName.length - 1);
} catch (DOMException e) {
CCorePlugin.log(e);
}
}
return false;
if (!(type instanceof ICPPTemplateTypeParameter))
return false;
return getParameterPosition() == ((ICPPTemplateParameter) type).getParameterPosition();
}
public IType getDefault() {

View file

@ -112,11 +112,15 @@ public class IndexLabelProvider extends LabelProvider {
StringBuffer buffer = new StringBuffer("Part: "); //$NON-NLS-1$
buffer.append(result);
buffer.append('<');
ICPPTemplateArgument[] types = ((ICPPClassTemplatePartialSpecialization) element).getTemplateArguments();
for (int i = 0; i < types.length; i++) {
if (i > 0)
buffer.append(',');
buffer.append(ASTTypeUtil.getArgumentString(types[i], false));
try {
ICPPTemplateArgument[] types = ((ICPPClassTemplatePartialSpecialization) element).getTemplateArguments();
for (int i = 0; i < types.length; i++) {
if (i > 0)
buffer.append(',');
buffer.append(ASTTypeUtil.getArgumentString(types[i], false));
}
} catch (DOMException e) {
buffer.append(e.getProblem().toString());
}
buffer.append('>');
result = buffer.toString();