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/Decl.h"
#include "clang/Basic/TargetInfo.h"
Chris Lattner
committed
#include "llvm/ADT/SmallVector.h"
#include "llvm/Bitcode/Serialize.h"
#include "llvm/Bitcode/Deserialize.h"
using namespace clang;
enum FloatingRank {
FloatRank, DoubleRank, LongDoubleRank
};
ASTContext::~ASTContext() {
// Deallocate all the types.
while (!Types.empty()) {
Chris Lattner
committed
if (FunctionTypeProto *FT = dyn_cast<FunctionTypeProto>(Types.back())) {
// Destroy the object, but don't call delete. These are malloc'd.
FT->~FunctionTypeProto();
free(FT);
} else {
delete Types.back();
}
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;
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;
switch (TT->getDecl()->getKind()) {
default: assert(0 && "Unknown tagged type!");
case Decl::Struct: ++NumTagStruct; break;
case Decl::Union: ++NumTagUnion; break;
case Decl::Class: ++NumTagClass; break;
case Decl::Enum: ++NumTagEnum; break;
}
} else if (isa<ObjCInterfaceType>(T))
++NumObjCInterfaces;
else if (isa<ObjCQualifiedInterfaceType>(T))
++NumObjCQualifiedInterfaces;
else if (isa<ObjCQualifiedIdType>(T))
++NumObjCQualifiedIds;
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, "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)));
}
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);
// 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
//===----------------------------------------------------------------------===//
/// 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) {
T = T.getCanonicalType();
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;
}
case Type::OCUVector:
Chris Lattner
committed
case Type::Vector: {
std::pair<uint64_t, unsigned> EltInfo =
getTypeInfo(cast<VectorType>(T)->getElementType());
Width = EltInfo.first*cast<VectorType>(T)->getNumElements();
Chris Lattner
committed
// FIXME: Vector alignment is not the alignment of its elements.
Align = EltInfo.second;
break;
}
case Type::Builtin:
// FIXME: need to use TargetInfo to derive the target specific sizes. This
// implementation will suffice for play with vector support.
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::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:
Width = Target.getPointerWidth(0);
Align = Target.getPointerAlign(0);
case Type::Pointer: {
unsigned AS = cast<PointerType>(T)->getPointeeType().getAddressSpace();
Width = Target.getPointerWidth(AS);
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.
return getTypeInfo(cast<ReferenceType>(T)->getReferenceeType());
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::Tagged:
TagType *TT = cast<TagType>(T);
if (RecordType *RT = dyn_cast<RecordType>(TT)) {
const ASTRecordLayout &Layout = getASTRecordLayout(RT->getDecl());
Width = Layout.getSize();
Align = Layout.getAlignment();
} else if (EnumDecl *ED = dyn_cast<EnumDecl>(TT->getDecl())) {
return getTypeInfo(ED->getIntegerType());
assert(0 && "Unimplemented type sizes!");
}
assert(Align && (Align & (Align-1)) == 0 && "Alignment must be power of 2");
return std::make_pair(Width, Align);
}
/// 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;
uint64_t *FieldOffsets = new uint64_t[D->getNumMembers()];
uint64_t RecordSize = 0;
unsigned RecordAlign = 8; // Default alignment = 1 byte = 8 bits.
if (D->getKind() != Decl::Union) {
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
RecordAlign = std::max(RecordAlign, AA->getAlignment());
bool StructIsPacked = D->getAttr<PackedAttr>();
// 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);
bool FieldIsPacked = StructIsPacked || FD->getAttr<PackedAttr>();
uint64_t FieldSize;
unsigned FieldAlign;
if (const Expr *BitWidthExpr = FD->getBitWidth()) {
llvm::APSInt I(32);
bool BitWidthIsICE =
BitWidthExpr->isIntegerConstantExpr(I, *this);
assert (BitWidthIsICE && "Invalid BitField size expression");
FieldSize = I.getZExtValue();
std::pair<uint64_t, unsigned> TypeInfo = getTypeInfo(FD->getType());
if (const AlignedAttr *AA = FD->getAttr<AlignedAttr>())
FieldAlign = AA->getAlignment();
else if (FieldIsPacked)
FieldAlign = 8;
else {
// FIXME: This is X86 specific, use 32-bit alignment for long long.
if (FD->getType()->isIntegerType() && TypeInfo.second > 32)
FieldAlign = 32;
else
FieldAlign = TypeInfo.second;
// Check if we need to add padding to give the field the correct
// alignment.
if (RecordSize % FieldAlign + FieldSize > TypeSize)
RecordSize = (RecordSize+FieldAlign-1) & ~(FieldAlign-1);
if (FD->getType()->isIncompleteType()) {
// This must be 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.
if (const AlignedAttr *AA = FD->getAttr<AlignedAttr>())
FieldAlign = AA->getAlignment();
else if (FieldIsPacked)
FieldAlign = 8;
else {
const ArrayType* ATy = FD->getType()->getAsArrayType();
FieldAlign = getTypeAlign(ATy->getElementType());
std::pair<uint64_t, unsigned> FieldInfo = getTypeInfo(FD->getType());
FieldSize = FieldInfo.first;
if (const AlignedAttr *AA = FD->getAttr<AlignedAttr>())
FieldAlign = AA->getAlignment();
else if (FieldIsPacked)
FieldAlign = 8;
else
FieldAlign = FieldInfo.second;
}
// Round up the current record size to the field's alignment boundary.
RecordSize = (RecordSize+FieldAlign-1) & ~(FieldAlign-1);
}
// Place this field at the current location.
FieldOffsets[i] = RecordSize;
// Reserve space for this field.
RecordSize += FieldSize;
// Remember max struct/class alignment.
RecordAlign = std::max(RecordAlign, FieldAlign);
}
// Finally, round the size of the total struct up to the alignment of the
// struct itself.
RecordSize = (RecordSize+RecordAlign-1) & ~(RecordAlign-1);
} else {
// Union layout just puts each member at the start of the record.
for (unsigned i = 0, e = D->getNumMembers(); i != e; ++i) {
const FieldDecl *FD = D->getMember(i);
std::pair<uint64_t, unsigned> FieldInfo = getTypeInfo(FD->getType());
uint64_t FieldSize = FieldInfo.first;
unsigned FieldAlign = FieldInfo.second;
// FIXME: This is X86 specific, use 32-bit alignment for long long.
if (FD->getType()->isIntegerType() && FieldAlign > 32)
FieldAlign = 32;
// Round up the current record size to the field's alignment boundary.
RecordSize = std::max(RecordSize, FieldSize);
// Place this field at the start of the record.
FieldOffsets[i] = 0;
// Remember max struct/class alignment.
RecordAlign = std::max(RecordAlign, FieldAlign);
}
}
NewEntry->SetLayout(RecordSize, RecordAlign, FieldOffsets);
return *NewEntry;
}
//===----------------------------------------------------------------------===//
// Type creation/memoization methods
//===----------------------------------------------------------------------===//
Christopher Lamb
committed
QualType ASTContext::getASQualType(QualType T, unsigned AddressSpace) {
if (T.getCanonicalType().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.
assert(T.getCanonicalType().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()) {
Canonical = getASQualType(T.getCanonicalType(), AddressSpace);
// 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
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
/// 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()) {
Canonical = getComplexType(T.getCanonicalType());
// 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()) {
// 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);
/// 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()) {
Canonical = getReferenceType(T.getCanonicalType());
// 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()) {
Steve Naroff
committed
Canonical = getConstantArrayType(EltTy.getCanonicalType(), ArySize,
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) {
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
// 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()) {
Canonical = getIncompleteArrayType(EltTy.getCanonicalType(),
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) {
BuiltinType *baseType;
baseType = dyn_cast<BuiltinType>(vecType.getCanonicalType().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()) {
// 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);
}
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
/// getOCUVectorType - Return the unique reference to an OCU vector type of
/// the specified element type and size. VectorType must be a built-in type.
QualType ASTContext::getOCUVectorType(QualType vecType, unsigned NumElts) {
BuiltinType *baseType;
baseType = dyn_cast<BuiltinType>(vecType.getCanonicalType().getTypePtr());
assert(baseType != 0 && "getOCUVectorType(): Expecting a built-in type");
// Check if we've already instantiated a vector of this type.
llvm::FoldingSetNodeID ID;
VectorType::Profile(ID, vecType, NumElts, Type::OCUVector);
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()) {
Canonical = getOCUVectorType(vecType.getCanonicalType(), 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!");
}
OCUVectorType *New = new OCUVectorType(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
// 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, QualType *ArgArray,
unsigned NumArgs, bool isVariadic) {
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)
CanonicalArgs.push_back(ArgArray[i].getCanonicalType());
Canonical = getFunctionType(ResultTy.getCanonicalType(),
&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
}
/// 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);
QualType Canonical = Decl->getUnderlyingType().getCanonicalType();
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);
}
/// getObjCQualifiedInterfaceType - Return a
/// ObjCQualifiedInterfaceType type for the given interface decl and
/// the conforming protocol list.
QualType ASTContext::getObjCQualifiedInterfaceType(ObjCInterfaceDecl *Decl,
ObjCProtocolDecl **Protocols, unsigned NumProtocols) {
llvm::FoldingSetNodeID ID;
ObjCQualifiedInterfaceType::Profile(ID, 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 a
/// getObjCQualifiedIdType type for the 'id' decl and
Fariborz Jahanian
committed
/// the conforming protocol list.
QualType ASTContext::getObjCQualifiedIdType(QualType idType,
ObjCProtocolDecl **Protocols,
Fariborz Jahanian
committed
unsigned NumProtocols) {
llvm::FoldingSetNodeID ID;
ObjCQualifiedIdType::Profile(ID, Protocols, NumProtocols);
Fariborz Jahanian
committed
void *InsertPos = 0;
if (ObjCQualifiedIdType *QT =
ObjCQualifiedIdTypes.FindNodeOrInsertPos(ID, InsertPos))
Fariborz Jahanian
committed
return QualType(QT, 0);
// No Match;
QualType Canonical;
if (!idType->isCanonical()) {
Canonical = getObjCQualifiedIdType(idType.getCanonicalType(),
Protocols, NumProtocols);
ObjCQualifiedIdType *NewQT =
ObjCQualifiedIdTypes.FindNodeOrInsertPos(ID, InsertPos);
assert(NewQT == 0 && "Shouldn't be in the map!");
}
ObjCQualifiedIdType *QType =
new ObjCQualifiedIdType(Canonical, Protocols, NumProtocols);
Fariborz Jahanian
committed
Types.push_back(QType);
ObjCQualifiedIdTypes.InsertNode(QType, InsertPos);
Fariborz Jahanian
committed
return QualType(QType, 0);
}
/// getTypeOfExpr - Unlike many "get<Type>" functions, we can't unique
/// TypeOfExpr AST's (since expression's are never shared). For example,
/// multiple declarations that refer to "typeof(x)" all contain different
/// DeclRefExpr's. This doesn't effect the type checker, since it operates
/// on canonical type's (which are always unique).
TypeOfExpr *toe = new TypeOfExpr(tofExpr, Canonical);
Types.push_back(toe);
return QualType(toe, 0);
/// getTypeOfType - Unlike many "get<Type>" functions, we don't unique
/// TypeOfType AST's. The only motivation to unique these nodes would be
/// memory savings. Since typeof(t) is fairly uncommon, space shouldn't be
/// an issue. This doesn't effect the type checker, since it operates
/// on canonical type's (which are always unique).
QualType ASTContext::getTypeOfType(QualType tofType) {
QualType Canonical = tofType.getCanonicalType();
TypeOfType *tot = new TypeOfType(tofType, Canonical);
Types.push_back(tot);
return QualType(tot, 0);
/// getTagDeclType - Return the unique reference to the type for the
/// specified TagDecl (struct/union/class/enum) decl.
assert (Decl);
// The decl stores the type cache.
if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0);
Ted Kremenek
committed
TagType* T = new TagType(Decl, QualType());
Types.push_back(T);
Decl->TypeForDecl = T;
Ted Kremenek
committed
return QualType(T, 0);
}
/// getSizeType - Return the unique type for "size_t" (C99 7.17), the result
/// of the sizeof operator (C99 6.5.3.4p4). The value is target dependent and
// On Darwin, size_t is defined as a "long unsigned int".
// FIXME: should derive from "Target".
return UnsignedLongTy;
}
/// getWcharType - Return the unique type for "wchar_t" (C99 7.17), the
/// width of characters in wide strings, The value is target dependent and
/// needs to agree with the definition in <stddef.h>.
QualType ASTContext::getWcharType() const {
// On Darwin, wchar_t is defined as a "int".
// FIXME: should derive from "Target".
return IntTy;
}
/// getPointerDiffType - Return the unique type for "ptrdiff_t" (ref?)
/// defined in <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9).
QualType ASTContext::getPointerDiffType() const {
// On Darwin, ptrdiff_t is defined as a "int". This seems like a bug...
// FIXME: should derive from "Target".
return IntTy;
}
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
//===----------------------------------------------------------------------===//
// Type Operators
//===----------------------------------------------------------------------===//
/// getArrayDecayedType - Return the properly qualified result of decaying the
/// specified array type to a pointer. This operation is non-trivial when
/// handling typedefs etc. The canonical type of "T" must be an array type,
/// this returns a pointer to a properly qualified element of the array.
///
/// See C99 6.7.5.3p7 and C99 6.3.2.1p3.
QualType ASTContext::getArrayDecayedType(QualType Ty) {
// Handle the common case where typedefs are not involved directly.
QualType EltTy;
unsigned ArrayQuals = 0;
unsigned PointerQuals = 0;
if (ArrayType *AT = dyn_cast<ArrayType>(Ty)) {
// Since T "isa" an array type, it could not have had an address space
// qualifier, just CVR qualifiers. The properly qualified element pointer
// gets the union of the CVR qualifiers from the element and the array, and
// keeps any address space qualifier on the element type if present.
EltTy = AT->getElementType();
ArrayQuals = Ty.getCVRQualifiers();
PointerQuals = AT->getIndexTypeQualifier();
} else {
// Otherwise, we have an ASQualType or a typedef, etc. Make sure we don't
// lose qualifiers when dealing with typedefs. Example:
// typedef int arr[10];
// void test2() {
// const arr b;
// b[4] = 1;
// }
//
// The decayed type of b is "const int*" even though the element type of the
// array is "int".
QualType CanTy = Ty.getCanonicalType();
const ArrayType *PrettyArrayType = Ty->getAsArrayType();
assert(PrettyArrayType && "Not an array type!");
// Get the element type with 'getAsArrayType' so that we don't lose any
// typedefs in the element type of the array.
EltTy = PrettyArrayType->getElementType();
// If the array was address-space qualifier, make sure to ASQual the element
// type. We can just grab the address space from the canonical type.
if (unsigned AS = CanTy.getAddressSpace())
EltTy = getASQualType(EltTy, AS);
// To properly handle [multiple levels of] typedefs, typeof's etc, we take
// the CVR qualifiers directly from the canonical type, which is guaranteed
// to have the full set unioned together.
ArrayQuals = CanTy.getCVRQualifiers();
PointerQuals = PrettyArrayType->getIndexTypeQualifier();
}
// Apply any CVR qualifiers from the array type to the element type. This
// implements C99 6.7.3p8: "If the specification of an array type includes
// any type qualifiers, the element type is so qualified, not the array type."
EltTy = EltTy.getQualifiedType(ArrayQuals | EltTy.getCVRQualifiers());
QualType PtrTy = getPointerType(EltTy);
// int x[restrict 4] -> int *restrict
PtrTy = PtrTy.getQualifiedType(PointerQuals);
return PtrTy;
}
/// getIntegerRank - Return an integer conversion rank (C99 6.3.1.1p1). This
/// routine will assert if passed a built-in type that isn't an integer or enum.