//===--- 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/Type.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/Support/Streams.h"
#include "llvm/ADT/StringExtras.h"
#include <sstream>
using namespace clang;
Type::~Type() {}
/// 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;
return false;
}
bool Type::isObjectType() const {
if (isa<FunctionType>(CanonicalType))
return false;
else if (CanonicalType->isIncompleteType())
return false;
else
return true;
}
bool Type::isDerivedType() const {
switch (CanonicalType->getTypeClass()) {
case Pointer:
case VariableArray:
case ConstantArray:
case IncompleteArray:
case FunctionProto:
case FunctionNoProto:
case Reference:
return true;
case Tagged: {
const TagType *TT = cast<TagType>(CanonicalType);
const Decl::Kind Kind = TT->getDecl()->getKind();
return Kind == Decl::Struct || Kind == Decl::Union;
}
default:
return false;
}
}
bool Type::isStructureType() const {
if (const RecordType *RT = dyn_cast<RecordType>(CanonicalType))
if (RT->getDecl()->getKind() == Decl::Struct)
return true;
return false;
}
bool Type::isUnionType() const {
if (const RecordType *RT = dyn_cast<RecordType>(CanonicalType))
if (RT->getDecl()->getKind() == Decl::Union)
return true;
return false;
}
bool Type::isComplexType() const {
if (const ComplexType *CT = dyn_cast<ComplexType>(CanonicalType))
return CT->getElementType()->isFloatingType();
return false;
}
bool Type::isComplexIntegerType() const {
// Check for GCC complex integer extension.
if (const ComplexType *CT = dyn_cast<ComplexType>(CanonicalType))
return CT->getElementType()->isIntegerType();
return false;
}
const ComplexType *Type::getAsComplexIntegerType() const {
// Are we directly a complex type?
if (const ComplexType *CTy = dyn_cast<ComplexType>(this)) {
if (CTy->getElementType()->isIntegerType())
return CTy;
}
// If the canonical form of this type isn't the right kind, reject it.
const ComplexType *CTy = dyn_cast<ComplexType>(CanonicalType);
if (!CTy || !CTy->getElementType()->isIntegerType())
return 0;
// If this is a typedef for a complex type, strip the typedef off without
// losing all typedef information.
return getDesugaredType()->getAsComplexIntegerType();
}
/// 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.
const Type *Type::getDesugaredType() const {
if (const TypedefType *TDT = dyn_cast<TypedefType>(this))
return TDT->LookThroughTypedefs().getTypePtr();
if (const TypeOfExpr *TOE = dyn_cast<TypeOfExpr>(this))
return TOE->getUnderlyingExpr()->getType().getTypePtr();
if (const TypeOfType *TOT = dyn_cast<TypeOfType>(this))
return TOT->getUnderlyingType().getTypePtr();
return this;
}
const BuiltinType *Type::getAsBuiltinType() const {
// If this is directly a builtin type, return it.
if (const BuiltinType *BTy = dyn_cast<BuiltinType>(this))
return BTy;
// If the canonical form of this type isn't a builtin type, reject it.
if (!isa<BuiltinType>(CanonicalType)) {
// Look through type qualifiers
if (isa<BuiltinType>(CanonicalType.getUnqualifiedType()))
return CanonicalType.getUnqualifiedType()->getAsBuiltinType();
return 0;
}
// If this is a typedef for a builtin type, strip the typedef off without
// losing all typedef information.
return getDesugaredType()->getAsBuiltinType();
}
const FunctionType *Type::getAsFunctionType() const {
// If this is directly a function type, return