/*******************************************************************************
* Copyright (c) 2006, 2013 IBM Corporation.
* 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 Corporation - initial API and implementation
* Markus Schorn (Wind River Systems)
* Thomas Corbat (IFS)
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.dom.cpp;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBinding;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMember;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable;
import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
class PDOMCPPAnnotations {
private static final int VISIBILITY_OFFSET = 0;
private static final int VISIBILITY_MASK = 0x03;
private static final int EXTERN_OFFSET = 2;
private static final int MUTABLE_OFFSET = 3;
private static final int STATIC_OFFSET = 4;
private static final int CONSTEXPR_OFFSET = 5;
// "Inline" shares the same offset as "mutable" because
// only fields can be mutable and only functions can be inline.
private static final int INLINE_OFFSET = MUTABLE_OFFSET;
// "extern C" shares the same offset as visibility because
// only members have visibility and they cannot be extern C.
private static final int EXTERN_C_OFFSET = VISIBILITY_OFFSET;
// Function annotations start here.
private static final int VARARGS_OFFSET = 6;
private static final int PARAMETER_PACK_OFFSET = 7;
private static final int DELETED_OFFSET = 8;
private static final int NO_RETURN_OFFSET = 9;
// Method annotations that don't fit on the first 16 bits of annotations.
private static final int VIRTUAL_OFFSET = 0;
private static final int DESTRUCTOR_OFFSET = 1;
private static final int IMPLICIT_OFFSET = 2;
private static final int EXPLICIT_OFFSET = 3;
private static final int PURE_VIRTUAL_OFFSET = 4;
private static final int OVERRIDE_OFFSET = 5;
private static final int FINAL_OFFSET = 6;
/**
* Encodes annotations applicable to C++ functions.
*
* @param function the function whose annotations will be encoded
* @return a bit vector of the annotations
*/
public static short encodeFunctionAnnotations(ICPPFunction function) {
short annotation = encodeVisibility(function);
if (function.isExtern())
annotation |= 1 << EXTERN_OFFSET;
if (ASTInternal.isStatic(function, false))
annotation |= 1 << STATIC_OFFSET;
if (function.isInline())
annotation |= 1 << INLINE_OFFSET;
if (function.takesVarArgs())
annotation |= 1 << VARARGS_OFFSET;
if (function.isNoReturn())
annotation |= 1 << NO_RETURN_OFFSET;
if (function.isExternC())
annotation |= 1 << EXTERN_C_OFFSET;
if (function.isConstexpr())
annotation |= 1 << CONSTEXPR_OFFSET;
if (function.hasParameterPack())
annotation |= 1 << PARAMETER_PACK_OFFSET;
if (function.isDeleted())
annotation |= 1 << DELETED_OFFSET;
return annotation;
}
/**
* Encodes annotations applicable to C++ variables.
*
* @param variable the IBinding whose annotations will be encoded
* @return a bit vector of the annotations
*/
public static byte encodeVariableAnnotations(ICPPVariable variable) {
byte annotation = encodeVisibility(variable);
if (variable.isExtern())
annotation |= 1 << EXTERN_OFFSET;
if (variable.isStatic())
annotation |= 1 << STATIC_OFFSET;
if (variable.isExternC())
annotation |= 1 << EXTERN_C_OFFSET;
if (variable.isConstexpr())
annotation |= 1 << CONSTEXPR_OFFSET;
if (variable instanceof ICPPField && ((ICPPField) variable).isMutable())
annotation |= 1 << MUTABLE_OFFSET;
return annotation;
}
private static byte encodeVisibility(ICPPBinding binding) {
byte annotation = 0;
if (binding instanceof ICPPMember) {
ICPPMember member = (ICPPMember) binding;
annotation = (byte) ((member.getVisibility() & VISIBILITY_MASK) << VISIBILITY_OFFSET);
}
return annotation;
}
/**
* Encodes extra annotations applicable to C++ methods.
*
* @param binding the IBinding whose annotations will be encoded
* @return a bit vector of the annotation
*/
public static byte encodeExtraMethodAnnotations(IBinding binding) {
byte annotation = 0;
if (binding instanceof ICPPMethod) {
ICPPMethod method = (ICPPMethod) binding;
if (method.isVirtual())
annotation |= 1 << VIRTUAL_OFFSET;
if (method.isDestructor())
annotation |= 1 << DESTRUCTOR_OFFSET;
if (method.isImplicit())
annotation |= 1 << IMPLICIT_OFFSET;
if (method.isPureVirtual())
annotation |= 1 << PURE_VIRTUAL_OFFSET;
if (method.isExplicit())
annotation |= 1 << EXPLICIT_OFFSET;
if (method.isOverride())
annotation |= 1 << OVERRIDE_OFFSET;
if (method.isFinal())
annotation |= 1 << FINAL_OFFSET;
}
return annotation;
}
/**
* Unpacks visibility information from a bit vector of annotation.
*
* @param annotation the annotation containing visibility information.
* @return the visibility component of the annotation.
*/
public static int getVisibility(short annotation) {
return (annotation >> VISIBILITY_OFFSET) & VISIBILITY_MASK;
}
/**
* Checks if the "extern" annotation is set.
*/
public static boolean isExtern(short annotation) {
return (annotation & (1 << EXTERN_OFFSET)) != 0;
}
/**
* Checks if the "mutable" annotation is set.
*/
public static boolean isMutable(short annotation) {
return (annotation & (1 << MUTABLE_OFFSET)) != 0;
}
/**
* Checks if the "static" annotation is set.
*/
public static boolean isStatic(short annotation) {
return (annotation & (1 << STATIC_OFFSET)) != 0;
}
/**
* Checks if the "constexpr" annotation is set.
*/
public static boolean isConstexpr(short annotation) {
return (annotation & (1 << CONSTEXPR_OFFSET)) != 0;
}
/**
* Checks if the "inline" annotation is set.
*/
public static boolean isInline(short annotation) {
return (annotation & (1 << INLINE_OFFSET)) != 0;
}
/**
* Checks if the "extern C" annotation is set.
*/
public static boolean isExternC(short annotation) {
return (annotation & (1 << EXTERN_C_OFFSET)) != 0;
}
/**
* Checks if the "varargs" annotation is set.
*/
public static boolean isVarargsFunction(short annotation) {
return (annotation & (1 << VARARGS_OFFSET)) != 0;
}
/**
* Checks if the "has parameter pack" annotation is set.
*/
public static boolean hasParameterPack(short annotation) {
return (annotation & (1 << PARAMETER_PACK_OFFSET)) != 0;
}
/**
* Checks if the "deleted" annotation is set.
*/
public static boolean isDeletedFunction(short annotation) {
return (annotation & (1 << DELETED_OFFSET)) != 0;
}
/**
* Checks if the "no return" annotation is set.
*/
public static boolean isNoReturnFunction(short annotation) {
return (annotation & (1 << NO_RETURN_OFFSET)) != 0;
}
/**
* Checks if the "virtual" annotation is set.
*/
public static boolean isVirtualMethod(byte annotation) {
return (annotation & (1 << VIRTUAL_OFFSET)) != 0;
}
/**
* Checks if the "destructor" annotation is set.
*/
public static boolean isDestructor(byte annotation) {
return (annotation & (1 << DESTRUCTOR_OFFSET)) != 0;
}
/**
* Checks if the "implicit" annotation is set.
*/
public static boolean isImplicitMethod(byte annotation) {
return (annotation & (1 << IMPLICIT_OFFSET)) != 0;
}
/**
* Checks if the "explicit" annotation is set.
*/
public static boolean isExplicitMethod(byte annotation) {
return (annotation & (1 << EXPLICIT_OFFSET)) != 0;
}
/**
* Checks if the "pure virtual " annotation is set.
*/
public static boolean isPureVirtualMethod(byte annotation) {
return (annotation & (1 << PURE_VIRTUAL_OFFSET)) != 0;
}
/**
* Checks if the "override" annotation is set.
*/
public static boolean isOverrideMethod(byte annotation) {
return (annotation & (1 << OVERRIDE_OFFSET)) != 0;
}
/**
* Checks if the "final" annotation is set.
*/
public static boolean isFinalMethod(byte annotation) {
return (annotation & (1 << FINAL_OFFSET)) != 0;
}
/**
* Checks if the "explicit" annotation is set.
*/
public static byte clearImplicitMethodFlag(byte annotation) {
return (byte) (annotation & ~(1 << IMPLICIT_OFFSET));
}
}