/*******************************************************************************
* Copyright (c) 2004, 2015 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:
* IBM - Initial API and implementation
* Markus Schorn (Wind River Systems)
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.cdt.core.dom.ILinkage;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
import org.eclipse.cdt.core.dom.ast.IBasicType;
import org.eclipse.cdt.core.dom.ast.IBasicType.Kind;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IMacroBinding;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter;
import org.eclipse.cdt.core.parser.ParserLanguage;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.internal.core.dom.Linkage;
import org.eclipse.cdt.internal.core.dom.parser.ASTTranslationUnit;
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPInheritance.FinalOverriderMap;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.cdt.internal.core.index.IIndexScope;
import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContent;
/**
* C++-specific implementation of a translation-unit.
*/
public class CPPASTTranslationUnit extends ASTTranslationUnit implements ICPPASTTranslationUnit, IASTAmbiguityParent {
private CPPNamespaceScope fScope;
private ICPPNamespace fBinding;
private final CPPScopeMapper fScopeMapper= new CPPScopeMapper(this);
private CPPASTAmbiguityResolver fAmbiguityResolver;
// Caches
private Map<ICPPClassType, FinalOverriderMap> fFinalOverriderMapCache = new HashMap<>();
public CPPASTTranslationUnit() {
}
@Override
public CPPASTTranslationUnit copy() {
return copy(CopyStyle.withoutLocations);
}
@Override
public CPPASTTranslationUnit copy(CopyStyle style) {
CPPASTTranslationUnit copy = new CPPASTTranslationUnit();
return copy(copy, style);
}
@Override
public CPPNamespaceScope getScope() {
if (fScope == null) {
fScope = new CPPNamespaceScope(this);
addBuiltinOperators(fScope);
}
return fScope;
}
private void addBuiltinOperators(CPPScope theScope) {
// void
IType cpp_void = new CPPBasicType(Kind.eVoid, 0);
// void*
IType cpp_void_p = new CPPPointerType(new CPPQualifierType(new CPPBasicType(Kind.eVoid, 0), false, false), new CPPASTPointer());
// size_t // assumed: unsigned long int
IType cpp_size_t = new CPPBasicType(Kind.eInt, IBasicType.IS_LONG & IBasicType.IS_UNSIGNED);
// void* operator new(std::size_t);
IBinding temp = null;
IType[] newParms = new IType[1];
newParms[0] = cpp_size_t;
ICPPFunctionType newFunctionType = new CPPFunctionType(cpp_void_p, newParms);
ICPPParameter[] newTheParms = new ICPPParameter[1];
newTheParms[0] = new CPPBuiltinParameter(newParms[0]);
temp = new CPPImplicitFunction(OverloadableOperator.NEW.toCharArray(), theScope, newFunctionType, newTheParms, false, false);
theScope.addBinding(temp);
// void* operator new[](std::size_t);
temp = null;
temp = new CPPImplicitFunction(OverloadableOperator.NEW_ARRAY.toCharArray(), theScope, newFunctionType, newTheParms, false, false);
theScope.addBinding(temp);
// void operator delete(void*);
temp = null;
IType[] deleteParms = new IType[1];
deleteParms[0] = cpp_void_p;
ICPPFunctionType deleteFunctionType = new CPPFunctionType(cpp_void, deleteParms);
ICPPParameter[] deleteTheParms = new ICPPParameter[1];
deleteTheParms[0] = new CPPBuiltinParameter(deleteParms[0]);
temp = new CPPImplicitFunction(OverloadableOperator.DELETE.toCharArray(), theScope,
deleteFunctionType, deleteTheParms, false, false);
theScope.addBinding(temp);
// void operator delete[](void*);
temp = null;
temp = new CPPImplicitFunction(OverloadableOperator.DELETE_ARRAY.toCharArray(), theScope,
deleteFunctionType, deleteTheParms, false, false);
theScope.addBinding(temp);
}
@Override
public IASTName[] getDeclarationsInAST(IBinding binding) {
if (binding instanceof IMacroBinding) {
return getMacroDefinitionsInAST((IMacroBinding) binding);
}
return CPPVisitor.getDeclarations(this, binding);
}
@Override
public IASTName[] getDefinitionsInAST(IBinding binding) {
if (binding instanceof IMacroBinding) {
return getMacroDefinitionsInAST((IMacroBinding) binding);
}
IASTName[] names = CPPVisitor.getDeclarations(this, binding);
for (int i = 0; i < names.length; i++) {
if (!names[i].isDefinition())
names[i] = null;
}
// nulls can be anywhere, don't use trim()
return ArrayUtil.removeNulls(IASTName.class, names);
}
@Override
public IASTName[] getReferences(IBinding binding) {
if (binding instanceof IMacroBinding) {
return getMacroReferencesInAST((IMacroBinding) binding);
}
return CPPVisitor.getReferences(this, binding);
}
@Override
public ICPPNamespace getGlobalNamespace() {
if (fBinding == null)
fBinding = new CPPNamespace(this);
return fBinding;
}
@Override @Deprecated
public IBinding resolveBinding() {
return getGlobalNamespace();
}
@Override @Deprecated
public ParserLanguage getParserLanguage() {
return ParserLanguage.CPP;
}
@Override
public ILinkage getLinkage() {
return Linkage.CPP_LINKAGE;
}
@Override
public void skippedFile(int offset, InternalFileContent fileContent) {
super.skippedFile(offset, fileContent);
fScopeMapper.registerAdditionalDirectives(offset, fileContent.getUsingDirectives());
}
@Override
public IScope mapToASTScope(IScope scope) {
if (scope instanceof IIndexScope) {
return fScopeMapper.mapToASTScope((IIndexScope) scope);
}
return scope;
}
/**
* Maps a class type to the AST.
*
* @param binding a class type, possibly from index
* @param point a lookup point in the AST
* @return the corresponding class in the AST, or the original class type if it doesn't have
* a counterpart in the AST.
*/
public ICPPClassType mapToAST(ICPPClassType binding, IASTNode point) {
return fScopeMapper.mapToAST(binding, point);
}
/**
* Stores directives from the index into this scope.
*/
public void handleAdditionalDirectives(ICPPNamespaceScope scope) {
fScopeMapper.handleAdditionalDirectives(scope);
}
@Override
public void resolveAmbiguities() {
fAmbiguityResolver = new CPPASTAmbiguityResolver();
accept(fAmbiguityResolver);
fAmbiguityResolver = null;
}
@Override
protected IType createType(IASTTypeId typeid) {
return CPPVisitor.createType(typeid);
}
@Override
public void resolvePendingAmbiguities(IASTNode node) {
if (fAmbiguityResolver != null) {
fAmbiguityResolver.resolvePendingAmbiguities(node);
}
}
public Map<ICPPClassType, FinalOverriderMap> getFinalOverriderMapCache() {
return fFinalOverriderMapCache;
}
public void recordPartialSpecialization(ICPPClassTemplatePartialSpecialization indexSpec,
ICPPClassTemplatePartialSpecialization astSpec) {
fScopeMapper.recordPartialSpecialization(indexSpec, astSpec);
}
public ICPPClassTemplatePartialSpecialization mapToAST(ICPPClassTemplatePartialSpecialization indexSpec) {
return fScopeMapper.mapToAST(indexSpec);
}
}