//===--- Type.cpp - Type representation and manipulation ------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements type-related functionality.
//
//===----------------------------------------------------------------------===//
#include "clang/AST/ASTContext.h"
#include "clang/AST/Type.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "llvm/ADT/StringExtras.h"
using namespace clang;
bool QualType::isConstant(ASTContext &Ctx) const {
if (isConstQualified())
return true;
if (getTypePtr()->isArrayType())
return Ctx.getAsArrayType(*this)->getElementType().isConstant(Ctx);
return false;
}
void Type::Destroy(ASTContext& C) { delete this; }
void FunctionTypeProto::Destroy(ASTContext& C) {
// Destroy the object, but don't call delete. These are malloc'd.
this->~FunctionTypeProto();
free(this);
}
void VariableArrayType::Destroy(ASTContext& C) {
SizeExpr->Destroy(C);
delete this;
}
void DependentSizedArrayType::Destroy(ASTContext& C) {
SizeExpr->Destroy(C);
delete this;
}
/// getArrayElementTypeNoTypeQual - If this is an array type, return the
/// element type of the array, potentially with type qualifiers missing.
/// This method should never be used when type qualifiers are meaningful.
const Type *Type::getArrayElementTypeNoTypeQual() const {
// If this is directly an array type, return it.
if (const ArrayType *ATy = dyn_cast<ArrayType>(this))
return ATy->getElementType().getTypePtr();
// If the canonical form of this type isn't the right kind, reject it.
if (!isa<ArrayType>(CanonicalType)) {
// Look through type qualifiers
if (ArrayType *AT = dyn_cast<ArrayType>(CanonicalType.getUnqualifiedType()))
return AT->getElementType().getTypePtr();
return 0;
}
// If this is a typedef for an array type, strip the typedef off without
// losing all typedef information.
return getDesugaredType()->getArrayElementTypeNoTypeQual();
}
/// getDesugaredType - Return the specified type with any "sugar" removed from
/// type type. This takes off typedefs, typeof's etc. If the outer level of
/// the type is already concrete, it returns it unmodified. This is similar
/// to getting the canonical type, but it doesn't remove *all* typedefs. For
/// example, it return "T*" as "T*", (not as "int*"), because the pointer is
/// concrete.
QualType Type::getDesugaredType() const {
if (const TypedefType *TDT = dyn_cast<TypedefType>(this))
return TDT->LookThroughTypedefs();
if (const TypeOfExpr *TOE = dyn_cast<TypeOfExpr>(this))
return TOE->getUnderlyingExpr()->getType();
if (const TypeOfType *TOT = dyn_cast<TypeOfType>(this))
return TOT->getUnderlyingType();
// FIXME: remove this cast.
return QualType(const_cast<Type*>(this), 0);
}
/// isVoidType - Helper method to determine if this is the 'void' type.
bool Type::isVoidType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() == BuiltinType::Void;
if (const ASQualType *AS = dyn_cast<ASQualType>(CanonicalType))
return AS->getBaseType()->isVoidType();
return false;
}
bool Type::isObjectType() const {
if (isa<FunctionType>(CanonicalType))
return false;
if (const ASQualType *AS = dyn_cast<ASQualType>(CanonicalType))
return AS->getBaseType()->isObjectType();
return !CanonicalType->isIncompleteType();
}
bool Type::isDerivedType() const {
switch (CanonicalType->getTypeClass()) {
case ASQual:
return cast<ASQualType>(CanonicalType)->getBaseType