/*******************************************************************************
* Copyright (c) 2005, 2010 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrew Niefer (IBM) - Initial API and implementation
* Bryan Wilkinson (QNX)
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IField;
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization;
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.ICPPTemplateDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.core.parser.util.ObjectMap;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates;
/**
* Specialization of a class.
*/
public class CPPClassSpecialization extends CPPSpecialization
implements ICPPClassSpecialization, ICPPInternalClassTypeMixinHost {
private ICPPClassSpecializationScope specScope;
private ObjectMap specializationMap= ObjectMap.EMPTY_MAP;
public CPPClassSpecialization(ICPPClassType specialized, IBinding owner, ICPPTemplateParameterMap argumentMap) {
super(specialized, owner, argumentMap);
}
@Override
public ICPPClassType getSpecializedBinding() {
return (ICPPClassType) super.getSpecializedBinding();
}
public IBinding specializeMember(IBinding original) {
synchronized(this) {
IBinding result= (IBinding) specializationMap.get(original);
if (result != null)
return result;
}
IBinding result= CPPTemplates.createSpecialization(this, original);
synchronized(this) {
IBinding concurrent= (IBinding) specializationMap.get(original);
if (concurrent != null)
return concurrent;
if (specializationMap == ObjectMap.EMPTY_MAP)
specializationMap = new ObjectMap(2);
specializationMap.put(original, result);
return result;
}
}
public void checkForDefinition() {
// Ambiguity resolution ensures that declarations and definitions are resolved.
}
public ICPPASTCompositeTypeSpecifier getCompositeTypeSpecifier() {
IASTNode definition= getDefinition();
if (definition != null) {
IASTNode node= definition;
while (node instanceof IASTName)
node= node.getParent();
if (node instanceof ICPPASTCompositeTypeSpecifier)
return (ICPPASTCompositeTypeSpecifier) node;
}
return null;
}
public ICPPBase[] getBases() {
ICPPClassSpecializationScope scope= getSpecializationScope();
if (scope == null)
return ClassTypeHelper.getBases(this);
return scope.getBases();
}
public ICPPField[] getDeclaredFields() {
ICPPClassSpecializationScope scope= getSpecializationScope();
if (scope == null)
return ClassTypeHelper.getDeclaredFields(this);
return scope.getDeclaredFields();
}
public ICPPMethod[] getDeclaredMethods() {
ICPPClassSpecializationScope scope= getSpecializationScope();
if (scope == null)
return ClassTypeHelper.getDeclaredMethods(this);
return scope.getDeclaredMethods();
}
public ICPPConstructor[] getConstructors() {
ICPPClassSpecializationScope scope= getSpecializationScope();
if (scope == null)
return ClassTypeHelper.getConstructors(this);
return scope.getConstructors();
}
public IBinding[] getFriends() {
ICPPClassSpecializationScope scope= getSpecializationScope();
if (scope == null)
return ClassTypeHelper.getFriends(this);
return scope.getFriends();
}
public ICPPClassType[] getNestedClasses() {
ICPPClassSpecializationScope scope= getSpecializationScope();
if (scope == null)
return ClassTypeHelper.getNestedClasses(this);
return scope.getNestedClasses();
}
public IField[] getFields() {
return ClassTypeHelper.getFields(this);
}
public IField findField(String name) {
return ClassTypeHelper.findField(this, name);
}
public ICPPMethod[] getMethods() {
return ClassTypeHelper.getMethods(this);
}
public ICPPMethod[] getAllDeclaredMethods() {
return ClassTypeHelper.getAllDeclaredMethods(this);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.ICompositeType#getKey()
*/
public int getKey() {
if (getDefinition() != null)
return getCompositeTypeSpecifier().getKey();
return getSpecializedBinding().getKey();
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.ICompositeType#getCompositeScope()
*/
public ICPPClassScope getCompositeScope() {
final ICPPClassScope specScope= getSpecializationScope();
if (specScope != null)
return specScope;
final ICPPASTCompositeTypeSpecifier typeSpecifier = getCompositeTypeSpecifier();
if (typeSpecifier != null)
return typeSpecifier.getScope();
return null;
}
protected ICPPClassSpecializationScope getSpecializationScope() {
checkForDefinition();
if (getDefinition() != null)
return null;
//implicit specialization: must specialize bindings in scope
if (specScope == null) {
specScope = new CPPClassSpecializationScope(this);
}
return specScope;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.IType#isSameType(org.eclipse.cdt.core.dom.ast.IType)
*/
public boolean isSameType(IType type) {
if (type == this)
return true;
if (type instanceof ITypedef)
return type.isSameType(this);
if (type instanceof ICPPClassSpecialization) {
return isSameClassSpecialization(this, (ICPPClassSpecialization) type);
}
return false;
}
@Override
public Object clone() {
// TODO Auto-generated method stub
return this;
}
public boolean isAnonymous() {
if (getNameCharArray().length > 0)
return false;
ICPPASTCompositeTypeSpecifier spec= getCompositeTypeSpecifier();
if (spec == null) {
return getSpecializedBinding().isAnonymous();
}
IASTNode node= spec.getParent();
if (node instanceof IASTSimpleDeclaration) {
if (((IASTSimpleDeclaration) node).getDeclarators().length == 0) {
return true;
}
}
return false;
}
public static boolean isSameClassSpecialization(ICPPClassSpecialization t1, ICPPClassSpecialization t2) {
// exclude class template specialization or class instance
if (t2 instanceof ICPPTemplateInstance || t2 instanceof ICPPTemplateDefinition ||
t2 instanceof IProblemBinding)
return false;
if (t1.getKey() != t2.getKey())
return false;
if (!CharArrayUtils.equals(t1.getNameCharArray(), t2.getNameCharArray()))
return false;
// the argument map is not significant for comparing specializations, the map is
// determined by the owner of the specialization. This is different for instances,
// which have a separate implementation for isSameType().
final IBinding owner1= t1.getOwner();
final IBinding owner2= t2.getOwner();
// for a specialization that is not an instance the owner has to be a class-type
if (owner1 instanceof ICPPClassType == false || owner2 instanceof ICPPClassType == false)
return false;
return ((ICPPClassType) owner1).isSameType((ICPPClassType) owner2);
}
}