//===--- 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/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/AST/PrettyPrinter.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
bool QualType::isConstant(QualType T, ASTContext &Ctx) {
if (T.isConstQualified())
return true;
if (const ArrayType *AT = Ctx.getAsArrayType(T))
return AT->getElementType().isConstant(Ctx);
return false;
}
void Type::Destroy(ASTContext& C) {
this->~Type();
C.Deallocate(this);
}
void VariableArrayType::Destroy(ASTContext& C) {
if (SizeExpr)
SizeExpr->Destroy(C);
this->~VariableArrayType();
C.Deallocate(this);
}
void DependentSizedArrayType::Destroy(ASTContext& C) {
// FIXME: Resource contention like in ConstantArrayWithExprType ?
// May crash, depending on platform or a particular build.
// SizeExpr->Destroy(C);
this->~DependentSizedArrayType();
C.Deallocate(this);
}
void DependentSizedArrayType::Profile(llvm::FoldingSetNodeID &ID,
ASTContext &Context,
QualType ET,
ArraySizeModifier SizeMod,
unsigned TypeQuals,
Expr *E) {
ID.AddPointer(ET.getAsOpaquePtr());
ID.AddInteger(SizeMod);
ID.AddInteger(TypeQuals);
E->Profile(ID, Context, true);
}
void
DependentSizedExtVectorType::Profile(llvm::FoldingSetNodeID &ID,
ASTContext &Context,
QualType ElementType, Expr *SizeExpr) {
ID.AddPointer(ElementType.getAsOpaquePtr());
SizeExpr->Profile(ID, Context, true);
}
void DependentSizedExtVectorType::Destroy(ASTContext& C) {
// FIXME: Deallocate size expression, once we're cloning properly.
// if (SizeExpr)
// SizeExpr->Destroy(C);
this->~DependentSizedExtVectorType();
C.Deallocate(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))
return 0;
// If this is a typedef for an array type, strip the typedef off without
// losing all typedef information.
return cast<ArrayType>(getUnqualifiedDesugaredType())
->getElementType().getTypePtr();
}
/// \brief Retrieve the unqualified variant of the given type, removing as
/// little sugar as possible.
///
/// This routine looks through various kinds of sugar to find the
/// least-desuraged type that is unqualified. For example, given:
///
/// \code
/// typedef int Integer;
/// typedef const Integer CInteger;
/// typedef CInteger DifferenceType;
/// \endcode
///
/// Executing \c getUnqualifiedTypeSlow() on the type \c DifferenceType will
/// desugar until we hit the type \c Integer, which has no qualifiers on it.
QualType QualType::getUnqualifiedTypeSlow() const {
QualType Cur = *this;
while (true) {
if (!Cur.hasQualifiers())
return Cur;
const Type *CurTy = Cur.getTypePtr();
switch (CurTy->getTypeClass()) {
#define ABSTRACT_TYPE(Class, Parent)
#define TYPE(Class, Parent) \
case Type::Class: { \
const Class##Type *Ty = cast<Class##Type>(CurTy); \
if (!Ty->isSugared()) \
return Cur.getLocalUnqualifiedType(); \
Cur = Ty->desugar(); \
break; \
}
#include "clang/AST/TypeNodes.def"
}
}
return Cur.