Newer
Older
//===--- ASTContext.cpp - Context to hold long-lived AST nodes ------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the ASTContext interface.
//
//===----------------------------------------------------------------------===//
#include "clang/AST/ASTContext.h"
#include "clang/AST/Expr.h"
#include "clang/AST/RecordLayout.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/Bitcode/Serialize.h"
#include "llvm/Bitcode/Deserialize.h"
using namespace clang;
enum FloatingRank {
FloatRank, DoubleRank, LongDoubleRank
};
ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM, TargetInfo &t,
IdentifierTable &idents, SelectorTable &sels,
unsigned size_reserve) :
CFConstantStringTypeDecl(0), SourceMgr(SM), LangOpts(LOpts), Target(t),
Idents(idents), Selectors(sels)
{
if (size_reserve > 0) Types.reserve(size_reserve);
InitBuiltinTypes();
BuiltinInfo.InitializeBuiltins(idents, Target);
TUDecl = TranslationUnitDecl::Create(*this);
}
ASTContext::~ASTContext() {
// Deallocate all the types.
while (!Types.empty()) {
Types.back()->Destroy(*this);
Types.pop_back();
}
void ASTContext::PrintStats() const {
fprintf(stderr, "*** AST Context Stats:\n");
fprintf(stderr, " %d types total.\n", (int)Types.size());
unsigned NumBuiltin = 0, NumPointer = 0, NumArray = 0, NumFunctionP = 0;
unsigned NumFunctionNP = 0, NumTypeName = 0, NumTagged = 0, NumReference = 0;
unsigned NumTagStruct = 0, NumTagUnion = 0, NumTagEnum = 0, NumTagClass = 0;
unsigned NumObjCInterfaces = 0, NumObjCQualifiedInterfaces = 0;
unsigned NumObjCQualifiedIds = 0;
unsigned NumTypeOfTypes = 0, NumTypeOfExprs = 0;
for (unsigned i = 0, e = Types.size(); i != e; ++i) {
Type *T = Types[i];
if (isa<BuiltinType>(T))
++NumBuiltin;
else if (isa<PointerType>(T))
++NumPointer;
else if (isa<ComplexType>(T))
++NumComplex;
else if (isa<ArrayType>(T))
++NumArray;
else if (isa<VectorType>(T))
++NumVector;
else if (isa<FunctionTypeNoProto>(T))
++NumFunctionNP;
else if (isa<FunctionTypeProto>(T))
++NumFunctionP;
else if (isa<TypedefType>(T))
++NumTypeName;
++NumTagged;
default: assert(0 && "Unknown tagged type!");
case TagDecl::TK_struct: ++NumTagStruct; break;
case TagDecl::TK_union: ++NumTagUnion; break;
case TagDecl::TK_class: ++NumTagClass; break;
case TagDecl::TK_enum: ++NumTagEnum; break;
} else if (isa<ObjCInterfaceType>(T))
++NumObjCInterfaces;
else if (isa<ObjCQualifiedInterfaceType>(T))
++NumObjCQualifiedInterfaces;
else if (isa<ObjCQualifiedIdType>(T))
++NumObjCQualifiedIds;
else if (isa<TypeOfType>(T))
++NumTypeOfTypes;
else if (isa<TypeOfExpr>(T))
++NumTypeOfExprs;
assert(0 && "Unknown type!");
}
}
fprintf(stderr, " %d builtin types\n", NumBuiltin);
fprintf(stderr, " %d pointer types\n", NumPointer);
fprintf(stderr, " %d complex types\n", NumComplex);
fprintf(stderr, " %d array types\n", NumArray);
fprintf(stderr, " %d vector types\n", NumVector);
fprintf(stderr, " %d function types with proto\n", NumFunctionP);
fprintf(stderr, " %d function types with no proto\n", NumFunctionNP);
fprintf(stderr, " %d typename (typedef) types\n", NumTypeName);
fprintf(stderr, " %d tagged types\n", NumTagged);
fprintf(stderr, " %d struct types\n", NumTagStruct);
fprintf(stderr, " %d union types\n", NumTagUnion);
fprintf(stderr, " %d class types\n", NumTagClass);
fprintf(stderr, " %d enum types\n", NumTagEnum);
fprintf(stderr, " %d interface types\n", NumObjCInterfaces);
fprintf(stderr, " %d protocol qualified interface types\n",
NumObjCQualifiedInterfaces);
Fariborz Jahanian
committed
fprintf(stderr, " %d protocol qualified id types\n",
NumObjCQualifiedIds);
fprintf(stderr, " %d typeof types\n", NumTypeOfTypes);
fprintf(stderr, " %d typeof exprs\n", NumTypeOfExprs);
fprintf(stderr, "Total bytes = %d\n", int(NumBuiltin*sizeof(BuiltinType)+
NumComplex*sizeof(ComplexType)+NumVector*sizeof(VectorType)+
NumFunctionP*sizeof(FunctionTypeProto)+
NumFunctionNP*sizeof(FunctionTypeNoProto)+
NumTypeName*sizeof(TypedefType)+NumTagged*sizeof(TagType)+
NumTypeOfTypes*sizeof(TypeOfType)+NumTypeOfExprs*sizeof(TypeOfExpr)));
}
void ASTContext::InitBuiltinType(QualType &R, BuiltinType::Kind K) {
Types.push_back((R = QualType(new BuiltinType(K),0)).getTypePtr());
void ASTContext::InitBuiltinTypes() {
assert(VoidTy.isNull() && "Context reinitialized?");
// C99 6.2.5p19.
Chris Lattner
committed
InitBuiltinType(VoidTy, BuiltinType::Void);
// C99 6.2.5p2.
Chris Lattner
committed
InitBuiltinType(BoolTy, BuiltinType::Bool);
// C99 6.2.5p3.
if (Target.isCharSigned())
Chris Lattner
committed
InitBuiltinType(CharTy, BuiltinType::Char_S);
else
InitBuiltinType(CharTy, BuiltinType::Char_U);
// C99 6.2.5p4.
Chris Lattner
committed
InitBuiltinType(SignedCharTy, BuiltinType::SChar);
InitBuiltinType(ShortTy, BuiltinType::Short);
InitBuiltinType(IntTy, BuiltinType::Int);
InitBuiltinType(LongTy, BuiltinType::Long);
InitBuiltinType(LongLongTy, BuiltinType::LongLong);
// C99 6.2.5p6.
Chris Lattner
committed
InitBuiltinType(UnsignedCharTy, BuiltinType::UChar);
InitBuiltinType(UnsignedShortTy, BuiltinType::UShort);
InitBuiltinType(UnsignedIntTy, BuiltinType::UInt);
InitBuiltinType(UnsignedLongTy, BuiltinType::ULong);
InitBuiltinType(UnsignedLongLongTy, BuiltinType::ULongLong);
// C99 6.2.5p10.
Chris Lattner
committed
InitBuiltinType(FloatTy, BuiltinType::Float);
InitBuiltinType(DoubleTy, BuiltinType::Double);
InitBuiltinType(LongDoubleTy, BuiltinType::LongDouble);
// C++ 3.9.1p5
InitBuiltinType(WCharTy, BuiltinType::WChar);
// C99 6.2.5p11.
Chris Lattner
committed
FloatComplexTy = getComplexType(FloatTy);
DoubleComplexTy = getComplexType(DoubleTy);
LongDoubleComplexTy = getComplexType(LongDoubleTy);
ObjCIdType = QualType();
ObjCClassType = QualType();
ObjCConstantStringType = QualType();
// void * type
VoidPtrTy = getPointerType(VoidTy);
}
//===----------------------------------------------------------------------===//
// Type Sizing and Analysis
//===----------------------------------------------------------------------===//
/// getFloatTypeSemantics - Return the APFloat 'semantics' for the specified
/// scalar floating point type.
const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const {
const BuiltinType *BT = T->getAsBuiltinType();
assert(BT && "Not a floating point type!");
switch (BT->getKind()) {
default: assert(0 && "Not a floating point type!");
case BuiltinType::Float: return Target.getFloatFormat();
case BuiltinType::Double: return Target.getDoubleFormat();
case BuiltinType::LongDouble: return Target.getLongDoubleFormat();
}
}
/// getTypeSize - Return the size of the specified type, in bits. This method
/// does not work on incomplete types.
std::pair<uint64_t, unsigned>
ASTContext::getTypeInfo(QualType T) {
Chris Lattner
committed
T = getCanonicalType(T);
uint64_t Width;
unsigned Align;
switch (T->getTypeClass()) {
Chris Lattner
committed
case Type::TypeName: assert(0 && "Not a canonical type!");
case Type::FunctionNoProto:
case Type::FunctionProto:
assert(0 && "Incomplete types have no size!");
case Type::VariableArray:
assert(0 && "VLAs not implemented yet!");
case Type::ConstantArray: {
ConstantArrayType *CAT = cast<ConstantArrayType>(T);
Chris Lattner
committed
std::pair<uint64_t, unsigned> EltInfo = getTypeInfo(CAT->getElementType());
Width = EltInfo.first*CAT->getSize().getZExtValue();
Chris Lattner
committed
Align = EltInfo.second;
break;
Nate Begeman
committed
case Type::ExtVector:
Chris Lattner
committed
case Type::Vector: {
std::pair<uint64_t, unsigned> EltInfo =
getTypeInfo(cast<VectorType>(T)->getElementType());
Width = EltInfo.first*cast<VectorType>(T)->getNumElements();
// FIXME: This isn't right for unusual vectors
Align = Width;
Chris Lattner
committed
break;
}
case Type::Builtin:
switch (cast<BuiltinType>(T)->getKind()) {
default: assert(0 && "Unknown builtin type!");
case BuiltinType::Void:
assert(0 && "Incomplete types have no size!");
Width = Target.getBoolWidth();
Align = Target.getBoolAlign();
case BuiltinType::Char_S:
case BuiltinType::Char_U:
case BuiltinType::UChar:
Width = Target.getCharWidth();
Align = Target.getCharAlign();
case BuiltinType::WChar:
Width = Target.getWCharWidth();
Align = Target.getWCharAlign();
break;
case BuiltinType::UShort:
Width = Target.getShortWidth();
Align = Target.getShortAlign();
case BuiltinType::UInt:
Width = Target.getIntWidth();
Align = Target.getIntAlign();
case BuiltinType::ULong:
Width = Target.getLongWidth();
Align = Target.getLongAlign();
case BuiltinType::ULongLong:
Width = Target.getLongLongWidth();
Align = Target.getLongLongAlign();
Width = Target.getFloatWidth();
Align = Target.getFloatAlign();
Width = Target.getDoubleWidth();
Align = Target.getDoubleAlign();
Width = Target.getLongDoubleWidth();
Align = Target.getLongDoubleAlign();
}
break;
Christopher Lamb
committed
case Type::ASQual:
// FIXME: Pointers into different addr spaces could have different sizes and
// alignment requirements: getPointerInfo should take an AddrSpace.
return getTypeInfo(QualType(cast<ASQualType>(T)->getBaseType(), 0));
case Type::ObjCQualifiedId:
Align = Target.getPointerAlign(0);
case Type::Pointer: {
unsigned AS = cast<PointerType>(T)->getPointeeType().getAddressSpace();
Align = Target.getPointerAlign(AS);
break;
}
case Type::Reference:
// "When applied to a reference or a reference type, the result is the size
// of the referenced type." C++98 5.3.3p2: expr.sizeof.
// FIXME: This is wrong for struct layout: a reference in a struct has
// pointer size.
Chris Lattner
committed
return getTypeInfo(cast<ReferenceType>(T)->getPointeeType());
case Type::Complex: {
// Complex types have the same alignment as their elements, but twice the
// size.
std::pair<uint64_t, unsigned> EltInfo =
getTypeInfo(cast<ComplexType>(T)->getElementType());
Width = EltInfo.first*2;
Align = EltInfo.second;
break;
}
case Type::ObjCInterface: {
ObjCInterfaceType *ObjCI = cast<ObjCInterfaceType>(T);
const ASTRecordLayout &Layout = getASTObjCInterfaceLayout(ObjCI->getDecl());
Width = Layout.getSize();
Align = Layout.getAlignment();
break;
}
case Type::Tagged: {
if (cast<TagType>(T)->getDecl()->isInvalidDecl()) {
Width = 1;
Align = 1;
break;
}
if (EnumType *ET = dyn_cast<EnumType>(cast<TagType>(T)))
return getTypeInfo(ET->getDecl()->getIntegerType());
RecordType *RT = cast<RecordType>(T);
const ASTRecordLayout &Layout = getASTRecordLayout(RT->getDecl());
Width = Layout.getSize();
Align = Layout.getAlignment();
}
assert(Align && (Align & (Align-1)) == 0 && "Alignment must be power of 2");
return std::make_pair(Width, Align);
}
/// LayoutField - Field layout.
void ASTRecordLayout::LayoutField(const FieldDecl *FD, unsigned FieldNo,
bool IsUnion, bool StructIsPacked,
ASTContext &Context) {
bool FieldIsPacked = StructIsPacked || FD->getAttr<PackedAttr>();
uint64_t FieldOffset = IsUnion ? 0 : Size;
uint64_t FieldSize;
unsigned FieldAlign;
if (const Expr *BitWidthExpr = FD->getBitWidth()) {
// TODO: Need to check this algorithm on other targets!
// (tested on Linux-X86)
FieldSize =
BitWidthExpr->getIntegerConstantExprValue(Context).getZExtValue();
std::pair<uint64_t, unsigned> FieldInfo =
Context.getTypeInfo(FD->getType());
uint64_t TypeSize = FieldInfo.first;
FieldAlign = FieldInfo.second;
if (FieldIsPacked)
FieldAlign = 1;
if (const AlignedAttr *AA = FD->getAttr<AlignedAttr>())
FieldAlign = std::max(FieldAlign, AA->getAlignment());
// Check if we need to add padding to give the field the correct
// alignment.
if (FieldSize == 0 || (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize)
FieldOffset = (FieldOffset + (FieldAlign-1)) & ~(FieldAlign-1);
// Padding members don't affect overall alignment
if (!FD->getIdentifier())
FieldAlign = 1;
} else {
if (FD->getType()->isIncompleteArrayType()) {
// This is a flexible array member; we can't directly
// query getTypeInfo about these, so we figure it out here.
// Flexible array members don't have any size, but they
// have to be aligned appropriately for their element type.
FieldSize = 0;
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
FieldAlign = Context.getTypeAlign(ATy->getElementType());
} else {
std::pair<uint64_t, unsigned> FieldInfo =
Context.getTypeInfo(FD->getType());
FieldSize = FieldInfo.first;
FieldAlign = FieldInfo.second;
}
if (FieldIsPacked)
FieldAlign = 8;
if (const AlignedAttr *AA = FD->getAttr<AlignedAttr>())
FieldAlign = std::max(FieldAlign, AA->getAlignment());
// Round up the current record size to the field's alignment boundary.
FieldOffset = (FieldOffset + (FieldAlign-1)) & ~(FieldAlign-1);
}
// Place this field at the current location.
FieldOffsets[FieldNo] = FieldOffset;
// Reserve space for this field.
if (IsUnion) {
Size = std::max(Size, FieldSize);
} else {
Size = FieldOffset + FieldSize;
}
// Remember max struct/class alignment.
Alignment = std::max(Alignment, FieldAlign);
}
/// getASTObjcInterfaceLayout - Get or compute information about the layout of the
/// specified Objective C, which indicates its size and ivar
/// position information.
const ASTRecordLayout &
ASTContext::getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D) {
// Look up this layout, if already laid out, return what we have.
const ASTRecordLayout *&Entry = ASTObjCInterfaces[D];
if (Entry) return *Entry;
// Allocate and assign into ASTRecordLayouts here. The "Entry" reference can
// be invalidated (dangle) if the ASTRecordLayouts hashtable is inserted into.
ASTRecordLayout *NewEntry = NULL;
unsigned FieldCount = D->ivar_size();
if (ObjCInterfaceDecl *SD = D->getSuperClass()) {
FieldCount++;
const ASTRecordLayout &SL = getASTObjCInterfaceLayout(SD);
unsigned Alignment = SL.getAlignment();
uint64_t Size = SL.getSize();
NewEntry = new ASTRecordLayout(Size, Alignment);
NewEntry->InitializeLayout(FieldCount);
NewEntry->SetFieldOffset(0, 0); // Super class is at the beginning of the layout.
} else {
NewEntry = new ASTRecordLayout();
NewEntry->InitializeLayout(FieldCount);
}
Entry = NewEntry;
bool IsPacked = D->getAttr<PackedAttr>();
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
NewEntry->SetAlignment(std::max(NewEntry->getAlignment(),
AA->getAlignment()));
// Layout each ivar sequentially.
unsigned i = 0;
for (ObjCInterfaceDecl::ivar_iterator IVI = D->ivar_begin(),
IVE = D->ivar_end(); IVI != IVE; ++IVI) {
const ObjCIvarDecl* Ivar = (*IVI);
NewEntry->LayoutField(Ivar, i++, false, IsPacked, *this);
}
// Finally, round the size of the total struct up to the alignment of the
// struct itself.
NewEntry->FinalizeLayout();
return *NewEntry;
}
/// getASTRecordLayout - Get or compute information about the layout of the
/// specified record (struct/union/class), which indicates its size and field
/// position information.
const ASTRecordLayout &ASTContext::getASTRecordLayout(const RecordDecl *D) {
assert(D->isDefinition() && "Cannot get layout of forward declarations!");
// Look up this layout, if already laid out, return what we have.
const ASTRecordLayout *&Entry = ASTRecordLayouts[D];
if (Entry) return *Entry;
// Allocate and assign into ASTRecordLayouts here. The "Entry" reference can
// be invalidated (dangle) if the ASTRecordLayouts hashtable is inserted into.
ASTRecordLayout *NewEntry = new ASTRecordLayout();
Entry = NewEntry;
bool StructIsPacked = D->getAttr<PackedAttr>();
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
NewEntry->SetAlignment(std::max(NewEntry->getAlignment(),
AA->getAlignment()));
// Layout each field, for now, just sequentially, respecting alignment. In
// the future, this will need to be tweakable by targets.
for (unsigned i = 0, e = D->getNumMembers(); i != e; ++i) {
const FieldDecl *FD = D->getMember(i);
NewEntry->LayoutField(FD, i, IsUnion, StructIsPacked, *this);
// Finally, round the size of the total struct up to the alignment of the
// struct itself.
return *NewEntry;
}
//===----------------------------------------------------------------------===//
// Type creation/memoization methods
//===----------------------------------------------------------------------===//
Christopher Lamb
committed
QualType ASTContext::getASQualType(QualType T, unsigned AddressSpace) {
Chris Lattner
committed
QualType CanT = getCanonicalType(T);
if (CanT.getAddressSpace() == AddressSpace)
return T;
// Type's cannot have multiple ASQuals, therefore we know we only have to deal
// with CVR qualifiers from here on out.
Chris Lattner
committed
assert(CanT.getAddressSpace() == 0 &&
"Type is already address space qualified");
// Check if we've already instantiated an address space qual'd type of this
// type.
Christopher Lamb
committed
llvm::FoldingSetNodeID ID;
ASQualType::Profile(ID, T.getTypePtr(), AddressSpace);
Christopher Lamb
committed
void *InsertPos = 0;
if (ASQualType *ASQy = ASQualTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(ASQy, 0);
// If the base type isn't canonical, this won't be a canonical type either,
// so fill in the canonical type field.
QualType Canonical;
if (!T->isCanonical()) {
Chris Lattner
committed
Canonical = getASQualType(CanT, AddressSpace);
Christopher Lamb
committed
// Get the new insert position for the node we care about.
ASQualType *NewIP = ASQualTypes.FindNodeOrInsertPos(ID, InsertPos);
assert(NewIP == 0 && "Shouldn't be in the map!");
}
ASQualType *New = new ASQualType(T.getTypePtr(), Canonical, AddressSpace);
Christopher Lamb
committed
ASQualTypes.InsertNode(New, InsertPos);
Types.push_back(New);
return QualType(New, T.getCVRQualifiers());
Christopher Lamb
committed
}
Chris Lattner
committed
/// getComplexType - Return the uniqued reference to the type for a complex
/// number with the specified element type.
QualType ASTContext::getComplexType(QualType T) {
// Unique pointers, to guarantee there is only one pointer of a particular
// structure.
llvm::FoldingSetNodeID ID;
ComplexType::Profile(ID, T);
void *InsertPos = 0;
if (ComplexType *CT = ComplexTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(CT, 0);
// If the pointee type isn't canonical, this won't be a canonical type either,
// so fill in the canonical type field.
QualType Canonical;
if (!T->isCanonical()) {
Chris Lattner
committed
Canonical = getComplexType(getCanonicalType(T));
Chris Lattner
committed
// Get the new insert position for the node we care about.
ComplexType *NewIP = ComplexTypes.FindNodeOrInsertPos(ID, InsertPos);
assert(NewIP == 0 && "Shouldn't be in the map!");
}
ComplexType *New = new ComplexType(T, Canonical);
Types.push_back(New);
ComplexTypes.InsertNode(New, InsertPos);
return QualType(New, 0);
}
/// getPointerType - Return the uniqued reference to the type for a pointer to
/// the specified type.
// Unique pointers, to guarantee there is only one pointer of a particular
// structure.
Chris Lattner
committed
llvm::FoldingSetNodeID ID;
PointerType::Profile(ID, T);
void *InsertPos = 0;
if (PointerType *PT = PointerTypes.FindNodeOrInsertPos(ID, InsertPos))
Chris Lattner
committed
// If the pointee type isn't canonical, this won't be a canonical type either,
// so fill in the canonical type field.
if (!T->isCanonical()) {
Chris Lattner
committed
Canonical = getPointerType(getCanonicalType(T));
// Get the new insert position for the node we care about.
PointerType *NewIP = PointerTypes.FindNodeOrInsertPos(ID, InsertPos);
assert(NewIP == 0 && "Shouldn't be in the map!");
}
PointerType *New = new PointerType(T, Canonical);
Types.push_back(New);
PointerTypes.InsertNode(New, InsertPos);
/// getBlockPointerType - Return the uniqued reference to the type for
/// a pointer to the specified block.
QualType ASTContext::getBlockPointerType(QualType T) {
assert(T->isFunctionType() && "block of function types only");
// Unique pointers, to guarantee there is only one block of a particular
// structure.
llvm::FoldingSetNodeID ID;
BlockPointerType::Profile(ID, T);
void *InsertPos = 0;
if (BlockPointerType *PT =
BlockPointerTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(PT, 0);
// If the block pointee type isn't canonical, this won't be a canonical
// type either so fill in the canonical type field.
QualType Canonical;
if (!T->isCanonical()) {
Canonical = getBlockPointerType(getCanonicalType(T));
// Get the new insert position for the node we care about.
BlockPointerType *NewIP =
BlockPointerTypes.FindNodeOrInsertPos(ID, InsertPos);
assert(NewIP == 0 && "Shouldn't be in the map!");
}
BlockPointerType *New = new BlockPointerType(T, Canonical);
Types.push_back(New);
BlockPointerTypes.InsertNode(New, InsertPos);
return QualType(New, 0);
}
/// getReferenceType - Return the uniqued reference to the type for a reference
/// to the specified type.
QualType ASTContext::getReferenceType(QualType T) {
// Unique pointers, to guarantee there is only one pointer of a particular
// structure.
Chris Lattner
committed
llvm::FoldingSetNodeID ID;
ReferenceType::Profile(ID, T);
void *InsertPos = 0;
if (ReferenceType *RT = ReferenceTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(RT, 0);
// If the referencee type isn't canonical, this won't be a canonical type
// either, so fill in the canonical type field.
QualType Canonical;
if (!T->isCanonical()) {
Chris Lattner
committed
Canonical = getReferenceType(getCanonicalType(T));
// Get the new insert position for the node we care about.
ReferenceType *NewIP = ReferenceTypes.FindNodeOrInsertPos(ID, InsertPos);
assert(NewIP == 0 && "Shouldn't be in the map!");
}
ReferenceType *New = new ReferenceType(T, Canonical);
Types.push_back(New);
ReferenceTypes.InsertNode(New, InsertPos);
return QualType(New, 0);
}
/// getConstantArrayType - Return the unique reference to the type for an
/// array of the specified element type.
QualType ASTContext::getConstantArrayType(QualType EltTy,
Steve Naroff
committed
const llvm::APInt &ArySize,
ArrayType::ArraySizeModifier ASM,
unsigned EltTypeQuals) {
Chris Lattner
committed
llvm::FoldingSetNodeID ID;
void *InsertPos = 0;
if (ConstantArrayType *ATP =
ConstantArrayTypes.FindNodeOrInsertPos(ID, InsertPos))
Chris Lattner
committed
// If the element type isn't canonical, this won't be a canonical type either,
// so fill in the canonical type field.
if (!EltTy->isCanonical()) {
Chris Lattner
committed
Canonical = getConstantArrayType(getCanonicalType(EltTy), ArySize,
Steve Naroff
committed
ASM, EltTypeQuals);
// Get the new insert position for the node we care about.
ConstantArrayType *NewIP =
ConstantArrayTypes.FindNodeOrInsertPos(ID, InsertPos);
assert(NewIP == 0 && "Shouldn't be in the map!");
}
Chris Lattner
committed
Steve Naroff
committed
ConstantArrayType *New = new ConstantArrayType(EltTy, Canonical, ArySize,
ASM, EltTypeQuals);
ConstantArrayTypes.InsertNode(New, InsertPos);
Types.push_back(New);
Chris Lattner
committed
}
/// getVariableArrayType - Returns a non-unique reference to the type for a
/// variable array of the specified element type.
Steve Naroff
committed
QualType ASTContext::getVariableArrayType(QualType EltTy, Expr *NumElts,
ArrayType::ArraySizeModifier ASM,
unsigned EltTypeQuals) {
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
// Since we don't unique expressions, it isn't possible to unique VLA's
// that have an expression provided for their size.
VariableArrayType *New = new VariableArrayType(EltTy, QualType(), NumElts,
ASM, EltTypeQuals);
VariableArrayTypes.push_back(New);
Types.push_back(New);
return QualType(New, 0);
}
QualType ASTContext::getIncompleteArrayType(QualType EltTy,
ArrayType::ArraySizeModifier ASM,
unsigned EltTypeQuals) {
llvm::FoldingSetNodeID ID;
IncompleteArrayType::Profile(ID, EltTy);
void *InsertPos = 0;
if (IncompleteArrayType *ATP =
IncompleteArrayTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(ATP, 0);
// If the element type isn't canonical, this won't be a canonical type
// either, so fill in the canonical type field.
QualType Canonical;
if (!EltTy->isCanonical()) {
Chris Lattner
committed
Canonical = getIncompleteArrayType(getCanonicalType(EltTy),
ASM, EltTypeQuals);
// Get the new insert position for the node we care about.
IncompleteArrayType *NewIP =
IncompleteArrayTypes.FindNodeOrInsertPos(ID, InsertPos);
assert(NewIP == 0 && "Shouldn't be in the map!");
IncompleteArrayType *New = new IncompleteArrayType(EltTy, Canonical,
ASM, EltTypeQuals);
IncompleteArrayTypes.InsertNode(New, InsertPos);
Types.push_back(New);
return QualType(New, 0);
/// getVectorType - Return the unique reference to a vector type of
/// the specified element type and size. VectorType must be a built-in type.
QualType ASTContext::getVectorType(QualType vecType, unsigned NumElts) {
Chris Lattner
committed
baseType = dyn_cast<BuiltinType>(getCanonicalType(vecType).getTypePtr());
// Check if we've already instantiated a vector of this type.
llvm::FoldingSetNodeID ID;
void *InsertPos = 0;
if (VectorType *VTP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(VTP, 0);
// If the element type isn't canonical, this won't be a canonical type either,
// so fill in the canonical type field.
QualType Canonical;
if (!vecType->isCanonical()) {
Chris Lattner
committed
Canonical = getVectorType(getCanonicalType(vecType), NumElts);
// Get the new insert position for the node we care about.
VectorType *NewIP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos);
assert(NewIP == 0 && "Shouldn't be in the map!");
}
VectorType *New = new VectorType(vecType, NumElts, Canonical);
VectorTypes.InsertNode(New, InsertPos);
Types.push_back(New);
return QualType(New, 0);
}
Nate Begeman
committed
/// getExtVectorType - Return the unique reference to an extended vector type of
/// the specified element type and size. VectorType must be a built-in type.
Nate Begeman
committed
QualType ASTContext::getExtVectorType(QualType vecType, unsigned NumElts) {
Chris Lattner
committed
baseType = dyn_cast<BuiltinType>(getCanonicalType(vecType).getTypePtr());
Nate Begeman
committed
assert(baseType != 0 && "getExtVectorType(): Expecting a built-in type");
// Check if we've already instantiated a vector of this type.
llvm::FoldingSetNodeID ID;
Nate Begeman
committed
VectorType::Profile(ID, vecType, NumElts, Type::ExtVector);
void *InsertPos = 0;
if (VectorType *VTP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(VTP, 0);
// If the element type isn't canonical, this won't be a canonical type either,
// so fill in the canonical type field.
QualType Canonical;
if (!vecType->isCanonical()) {
Nate Begeman
committed
Canonical = getExtVectorType(getCanonicalType(vecType), NumElts);
// Get the new insert position for the node we care about.
VectorType *NewIP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos);
assert(NewIP == 0 && "Shouldn't be in the map!");
}
Nate Begeman
committed
ExtVectorType *New = new ExtVectorType(vecType, NumElts, Canonical);
VectorTypes.InsertNode(New, InsertPos);
Types.push_back(New);
return QualType(New, 0);
}
Chris Lattner
committed
/// getFunctionTypeNoProto - Return a K&R style C function type like 'int()'.
///
Chris Lattner
committed
// Unique functions, to guarantee there is only one function of a particular
// structure.
Chris Lattner
committed
llvm::FoldingSetNodeID ID;
Chris Lattner
committed
FunctionTypeNoProto::Profile(ID, ResultTy);
void *InsertPos = 0;
if (FunctionTypeNoProto *FT =
FunctionTypeNoProtos.FindNodeOrInsertPos(ID, InsertPos))
Chris Lattner
committed
Chris Lattner
committed
if (!ResultTy->isCanonical()) {
Chris Lattner
committed
Canonical = getFunctionTypeNoProto(getCanonicalType(ResultTy));
Chris Lattner
committed
// Get the new insert position for the node we care about.
FunctionTypeNoProto *NewIP =
FunctionTypeNoProtos.FindNodeOrInsertPos(ID, InsertPos);
assert(NewIP == 0 && "Shouldn't be in the map!");
}
Chris Lattner
committed
Chris Lattner
committed
FunctionTypeNoProto *New = new FunctionTypeNoProto(ResultTy, Canonical);
Types.push_back(New);
FunctionTypeNoProtos.InsertNode(New, InsertPos);
Chris Lattner
committed
}
/// getFunctionType - Return a normal function type with a typed argument
/// list. isVariadic indicates whether the argument list includes '...'.
QualType ASTContext::getFunctionType(QualType ResultTy, const QualType *ArgArray,
Chris Lattner
committed
// Unique functions, to guarantee there is only one function of a particular
// structure.
Chris Lattner
committed
llvm::FoldingSetNodeID ID;
FunctionTypeProto::Profile(ID, ResultTy, ArgArray, NumArgs, isVariadic);
void *InsertPos = 0;
if (FunctionTypeProto *FTP =
FunctionTypeProtos.FindNodeOrInsertPos(ID, InsertPos))
Chris Lattner
committed
// Determine whether the type being created is already canonical or not.
bool isCanonical = ResultTy->isCanonical();
for (unsigned i = 0; i != NumArgs && isCanonical; ++i)
if (!ArgArray[i]->isCanonical())
isCanonical = false;
// If this type isn't canonical, get the canonical version of it.
Chris Lattner
committed
if (!isCanonical) {
Chris Lattner
committed
llvm::SmallVector<QualType, 16> CanonicalArgs;
Chris Lattner
committed
CanonicalArgs.reserve(NumArgs);
for (unsigned i = 0; i != NumArgs; ++i)
Chris Lattner
committed
CanonicalArgs.push_back(getCanonicalType(ArgArray[i]));
Chris Lattner
committed
Chris Lattner
committed
Canonical = getFunctionType(getCanonicalType(ResultTy),
Chris Lattner
committed
&CanonicalArgs[0], NumArgs,
// Get the new insert position for the node we care about.
FunctionTypeProto *NewIP =
FunctionTypeProtos.FindNodeOrInsertPos(ID, InsertPos);
assert(NewIP == 0 && "Shouldn't be in the map!");
Chris Lattner
committed
}
// FunctionTypeProto objects are not allocated with new because they have a
// variable size array (for parameter types) at the end of them.
FunctionTypeProto *FTP =
(FunctionTypeProto*)malloc(sizeof(FunctionTypeProto) +
NumArgs*sizeof(QualType));
Chris Lattner
committed
new (FTP) FunctionTypeProto(ResultTy, ArgArray, NumArgs, isVariadic,
Canonical);
Types.push_back(FTP);
FunctionTypeProtos.InsertNode(FTP, InsertPos);
Chris Lattner
committed
}
Douglas Gregor
committed
/// getTypeDeclType - Return the unique reference to the type for the
/// specified type declaration.
QualType ASTContext::getTypeDeclType(TypeDecl *Decl) {
if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0);
if (TypedefDecl *Typedef = dyn_cast_or_null<TypedefDecl>(Decl))
return getTypedefType(Typedef);
else if (ObjCInterfaceDecl *ObjCInterface
= dyn_cast_or_null<ObjCInterfaceDecl>(Decl))
return getObjCInterfaceType(ObjCInterface);
if (CXXRecordDecl *CXXRecord = dyn_cast_or_null<CXXRecordDecl>(Decl))
Decl->TypeForDecl = new CXXRecordType(CXXRecord);
else if (RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Decl))
Douglas Gregor
committed
Decl->TypeForDecl = new RecordType(Record);
else if (EnumDecl *Enum = dyn_cast_or_null<EnumDecl>(Decl))
Douglas Gregor
committed
Decl->TypeForDecl = new EnumType(Enum);
Douglas Gregor
committed
assert(false && "TypeDecl without a type?");
Types.push_back(Decl->TypeForDecl);
return QualType(Decl->TypeForDecl, 0);
Douglas Gregor
committed
}
/// getTypedefType - Return the unique reference to the type for the
/// specified typename decl.
QualType ASTContext::getTypedefType(TypedefDecl *Decl) {
if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0);
Chris Lattner
committed
QualType Canonical = getCanonicalType(Decl->getUnderlyingType());
Fariborz Jahanian
committed
Decl->TypeForDecl = new TypedefType(Type::TypeName, Decl, Canonical);
Types.push_back(Decl->TypeForDecl);
}
/// getObjCInterfaceType - Return the unique reference to the type for the
QualType ASTContext::getObjCInterfaceType(ObjCInterfaceDecl *Decl) {
Decl->TypeForDecl = new ObjCInterfaceType(Type::ObjCInterface, Decl);
Types.push_back(Decl->TypeForDecl);
return QualType(Decl->TypeForDecl, 0);
}
/// CmpProtocolNames - Comparison predicate for sorting protocols
/// alphabetically.
static bool CmpProtocolNames(const ObjCProtocolDecl *LHS,
const ObjCProtocolDecl *RHS) {
return strcmp(LHS->getName(), RHS->getName()) < 0;
}
static void SortAndUniqueProtocols(ObjCProtocolDecl **&Protocols,
unsigned &NumProtocols) {
ObjCProtocolDecl **ProtocolsEnd = Protocols+NumProtocols;
// Sort protocols, keyed by name.
std::sort(Protocols, Protocols+NumProtocols, CmpProtocolNames);
// Remove duplicates.
ProtocolsEnd = std::unique(Protocols, ProtocolsEnd);
NumProtocols = ProtocolsEnd-Protocols;
}
/// getObjCQualifiedInterfaceType - Return a ObjCQualifiedInterfaceType type for
/// the given interface decl and the conforming protocol list.
QualType ASTContext::getObjCQualifiedInterfaceType(ObjCInterfaceDecl *Decl,
ObjCProtocolDecl **Protocols, unsigned NumProtocols) {
// Sort the protocol list alphabetically to canonicalize it.
SortAndUniqueProtocols(Protocols, NumProtocols);
llvm::FoldingSetNodeID ID;
ObjCQualifiedInterfaceType::Profile(ID, Decl, Protocols, NumProtocols);
void *InsertPos = 0;
if (ObjCQualifiedInterfaceType *QT =
ObjCQualifiedInterfaceTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(QT, 0);
// No Match;
ObjCQualifiedInterfaceType *QType =
new ObjCQualifiedInterfaceType(Decl, Protocols, NumProtocols);
Types.push_back(QType);
ObjCQualifiedInterfaceTypes.InsertNode(QType, InsertPos);
return QualType(QType, 0);
}
/// getObjCQualifiedIdType - Return an ObjCQualifiedIdType for the 'id' decl
/// and the conforming protocol list.
Chris Lattner
committed
QualType ASTContext::getObjCQualifiedIdType(ObjCProtocolDecl **Protocols,
Fariborz Jahanian
committed
unsigned NumProtocols) {
// Sort the protocol list alphabetically to canonicalize it.
SortAndUniqueProtocols(Protocols, NumProtocols);
Fariborz Jahanian
committed
llvm::FoldingSetNodeID ID;
ObjCQualifiedIdType::Profile(ID, Protocols, NumProtocols);
Fariborz Jahanian
committed
void *InsertPos = 0;
if (ObjCQualifiedIdType *QT =
Chris Lattner
committed
ObjCQualifiedIdTypes.FindNodeOrInsertPos(ID, InsertPos))
Fariborz Jahanian
committed
return QualType(QT, 0);