forked from OSchip/llvm-project
Add experimental support for address space qualified types. Address space
qualifiers use the __attribute__((address_space(id))) syntax. llvm-svn: 46691
This commit is contained in:
parent
e5b8b7db4a
commit
025b5fb883
|
@ -256,6 +256,8 @@ ASTContext::getTypeInfo(QualType T, SourceLocation L) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case Type::ASQual:
|
||||||
|
return getTypeInfo(cast<ASQualType>(T)->getBaseType(), L);
|
||||||
case Type::ObjCQualifiedId:
|
case Type::ObjCQualifiedId:
|
||||||
Target.getPointerInfo(Size, Align, getFullLoc(L));
|
Target.getPointerInfo(Size, Align, getFullLoc(L));
|
||||||
break;
|
break;
|
||||||
|
@ -368,6 +370,30 @@ const ASTRecordLayout &ASTContext::getASTRecordLayout(const RecordDecl *D,
|
||||||
// Type creation/memoization methods
|
// Type creation/memoization methods
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
QualType ASTContext::getASQualType(QualType T, unsigned AddressSpace) {
|
||||||
|
// Check if we've already instantiated an address space qual'd type of this type.
|
||||||
|
llvm::FoldingSetNodeID ID;
|
||||||
|
ASQualType::Profile(ID, T, AddressSpace);
|
||||||
|
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, Canonical, AddressSpace);
|
||||||
|
ASQualTypes.InsertNode(New, InsertPos);
|
||||||
|
Types.push_back(New);
|
||||||
|
return QualType(New, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// getComplexType - Return the uniqued reference to the type for a complex
|
/// getComplexType - Return the uniqued reference to the type for a complex
|
||||||
/// number with the specified element type.
|
/// number with the specified element type.
|
||||||
|
@ -817,7 +843,7 @@ static int getIntegerRank(QualType t) {
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
const BuiltinType *BT = cast<BuiltinType>(t.getCanonicalType());
|
const BuiltinType *BT = t.getCanonicalType()->getAsBuiltinType();
|
||||||
switch (BT->getKind()) {
|
switch (BT->getKind()) {
|
||||||
default:
|
default:
|
||||||
assert(0 && "getIntegerRank(): not a built-in integer");
|
assert(0 && "getIntegerRank(): not a built-in integer");
|
||||||
|
@ -847,10 +873,10 @@ static int getIntegerRank(QualType t) {
|
||||||
/// This routine will assert if passed a built-in type that isn't a float.
|
/// This routine will assert if passed a built-in type that isn't a float.
|
||||||
static int getFloatingRank(QualType T) {
|
static int getFloatingRank(QualType T) {
|
||||||
T = T.getCanonicalType();
|
T = T.getCanonicalType();
|
||||||
if (ComplexType *CT = dyn_cast<ComplexType>(T))
|
if (const ComplexType *CT = T->getAsComplexType())
|
||||||
return getFloatingRank(CT->getElementType());
|
return getFloatingRank(CT->getElementType());
|
||||||
|
|
||||||
switch (cast<BuiltinType>(T)->getKind()) {
|
switch (T->getAsBuiltinType()->getKind()) {
|
||||||
default: assert(0 && "getFloatingRank(): not a floating type");
|
default: assert(0 && "getFloatingRank(): not a floating type");
|
||||||
case BuiltinType::Float: return FloatRank;
|
case BuiltinType::Float: return FloatRank;
|
||||||
case BuiltinType::Double: return DoubleRank;
|
case BuiltinType::Double: return DoubleRank;
|
||||||
|
|
|
@ -125,8 +125,12 @@ const BuiltinType *Type::getAsBuiltinType() const {
|
||||||
return BTy;
|
return BTy;
|
||||||
|
|
||||||
// If the canonical form of this type isn't a builtin type, reject it.
|
// If the canonical form of this type isn't a builtin type, reject it.
|
||||||
if (!isa<BuiltinType>(CanonicalType))
|
if (!isa<BuiltinType>(CanonicalType)) {
|
||||||
|
// Look through type qualifiers
|
||||||
|
if (isa<BuiltinType>(CanonicalType.getUnqualifiedType()))
|
||||||
|
return CanonicalType.getUnqualifiedType()->getAsBuiltinType();
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// If this is a typedef for a builtin type, strip the typedef off without
|
// If this is a typedef for a builtin type, strip the typedef off without
|
||||||
// losing all typedef information.
|
// losing all typedef information.
|
||||||
|
@ -137,10 +141,14 @@ const FunctionType *Type::getAsFunctionType() const {
|
||||||
// If this is directly a function type, return it.
|
// If this is directly a function type, return it.
|
||||||
if (const FunctionType *FTy = dyn_cast<FunctionType>(this))
|
if (const FunctionType *FTy = dyn_cast<FunctionType>(this))
|
||||||
return FTy;
|
return FTy;
|
||||||
|
|
||||||
// If the canonical form of this type isn't the right kind, reject it.
|
// If the canonical form of this type isn't the right kind, reject it.
|
||||||
if (!isa<FunctionType>(CanonicalType))
|
if (!isa<FunctionType>(CanonicalType)) {
|
||||||
|
// Look through type qualifiers
|
||||||
|
if (isa<FunctionType>(CanonicalType.getUnqualifiedType()))
|
||||||
|
return CanonicalType.getUnqualifiedType()->getAsFunctionType();
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// If this is a typedef for a function type, strip the typedef off without
|
// If this is a typedef for a function type, strip the typedef off without
|
||||||
// losing all typedef information.
|
// losing all typedef information.
|
||||||
|
@ -153,8 +161,12 @@ const PointerType *Type::getAsPointerType() const {
|
||||||
return PTy;
|
return PTy;
|
||||||
|
|
||||||
// If the canonical form of this type isn't the right kind, reject it.
|
// If the canonical form of this type isn't the right kind, reject it.
|
||||||
if (!isa<PointerType>(CanonicalType))
|
if (!isa<PointerType>(CanonicalType)) {
|
||||||
|
// Look through type qualifiers
|
||||||
|
if (isa<PointerType>(CanonicalType.getUnqualifiedType()))
|
||||||
|
return CanonicalType.getUnqualifiedType()->getAsPointerType();
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// If this is a typedef for a pointer type, strip the typedef off without
|
// If this is a typedef for a pointer type, strip the typedef off without
|
||||||
// losing all typedef information.
|
// losing all typedef information.
|
||||||
|
@ -167,8 +179,12 @@ const ReferenceType *Type::getAsReferenceType() const {
|
||||||
return RTy;
|
return RTy;
|
||||||
|
|
||||||
// If the canonical form of this type isn't the right kind, reject it.
|
// If the canonical form of this type isn't the right kind, reject it.
|
||||||
if (!isa<ReferenceType>(CanonicalType))
|
if (!isa<ReferenceType>(CanonicalType)) {
|
||||||
|
// Look through type qualifiers
|
||||||
|
if (isa<ReferenceType>(CanonicalType.getUnqualifiedType()))
|
||||||
|
return CanonicalType.getUnqualifiedType()->getAsReferenceType();
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// If this is a typedef for a reference type, strip the typedef off without
|
// If this is a typedef for a reference type, strip the typedef off without
|
||||||
// losing all typedef information.
|
// losing all typedef information.
|
||||||
|
@ -181,8 +197,12 @@ const ArrayType *Type::getAsArrayType() const {
|
||||||
return ATy;
|
return ATy;
|
||||||
|
|
||||||
// If the canonical form of this type isn't the right kind, reject it.
|
// If the canonical form of this type isn't the right kind, reject it.
|
||||||
if (!isa<ArrayType>(CanonicalType))
|
if (!isa<ArrayType>(CanonicalType)) {
|
||||||
|
// Look through type qualifiers
|
||||||
|
if (isa<ArrayType>(CanonicalType.getUnqualifiedType()))
|
||||||
|
return CanonicalType.getUnqualifiedType()->getAsArrayType();
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// If this is a typedef for an array type, strip the typedef off without
|
// If this is a typedef for an array type, strip the typedef off without
|
||||||
// losing all typedef information.
|
// losing all typedef information.
|
||||||
|
@ -193,10 +213,14 @@ const ConstantArrayType *Type::getAsConstantArrayType() const {
|
||||||
// If this is directly a constant array type, return it.
|
// If this is directly a constant array type, return it.
|
||||||
if (const ConstantArrayType *ATy = dyn_cast<ConstantArrayType>(this))
|
if (const ConstantArrayType *ATy = dyn_cast<ConstantArrayType>(this))
|
||||||
return ATy;
|
return ATy;
|
||||||
|
|
||||||
// If the canonical form of this type isn't the right kind, reject it.
|
// If the canonical form of this type isn't the right kind, reject it.
|
||||||
if (!isa<ConstantArrayType>(CanonicalType))
|
if (!isa<ConstantArrayType>(CanonicalType)) {
|
||||||
|
// Look through type qualifiers
|
||||||
|
if (isa<ConstantArrayType>(CanonicalType.getUnqualifiedType()))
|
||||||
|
return CanonicalType.getUnqualifiedType()->getAsConstantArrayType();
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// If this is a typedef for a constant array type, strip the typedef off
|
// If this is a typedef for a constant array type, strip the typedef off
|
||||||
// without losing all typedef information.
|
// without losing all typedef information.
|
||||||
|
@ -209,8 +233,12 @@ const VariableArrayType *Type::getAsVariableArrayType() const {
|
||||||
return ATy;
|
return ATy;
|
||||||
|
|
||||||
// If the canonical form of this type isn't the right kind, reject it.
|
// If the canonical form of this type isn't the right kind, reject it.
|
||||||
if (!isa<VariableArrayType>(CanonicalType))
|
if (!isa<VariableArrayType>(CanonicalType)) {
|
||||||
|
// Look through type qualifiers
|
||||||
|
if (isa<VariableArrayType>(CanonicalType.getUnqualifiedType()))
|
||||||
|
return CanonicalType.getUnqualifiedType()->getAsVariableArrayType();
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// If this is a typedef for a variable array type, strip the typedef off
|
// If this is a typedef for a variable array type, strip the typedef off
|
||||||
// without losing all typedef information.
|
// without losing all typedef information.
|
||||||
|
@ -257,8 +285,12 @@ const RecordType *Type::getAsRecordType() const {
|
||||||
return RTy;
|
return RTy;
|
||||||
|
|
||||||
// If the canonical form of this type isn't the right kind, reject it.
|
// If the canonical form of this type isn't the right kind, reject it.
|
||||||
if (!isa<RecordType>(CanonicalType))
|
if (!isa<RecordType>(CanonicalType)) {
|
||||||
|
// Look through type qualifiers
|
||||||
|
if (isa<RecordType>(CanonicalType.getUnqualifiedType()))
|
||||||
|
return CanonicalType.getUnqualifiedType()->getAsRecordType();
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// If this is a typedef for a record type, strip the typedef off without
|
// If this is a typedef for a record type, strip the typedef off without
|
||||||
// losing all typedef information.
|
// losing all typedef information.
|
||||||
|
@ -281,6 +313,9 @@ const RecordType *Type::getAsStructureType() const {
|
||||||
// losing all typedef information.
|
// losing all typedef information.
|
||||||
return getDesugaredType()->getAsStructureType();
|
return getDesugaredType()->getAsStructureType();
|
||||||
}
|
}
|
||||||
|
// Look through type qualifiers
|
||||||
|
if (isa<RecordType>(CanonicalType.getUnqualifiedType()))
|
||||||
|
return CanonicalType.getUnqualifiedType()->getAsStructureType();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,6 +325,7 @@ const RecordType *Type::getAsUnionType() const {
|
||||||
if (RT->getDecl()->getKind() == Decl::Union)
|
if (RT->getDecl()->getKind() == Decl::Union)
|
||||||
return RT;
|
return RT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the canonical form of this type isn't the right kind, reject it.
|
// If the canonical form of this type isn't the right kind, reject it.
|
||||||
if (const RecordType *RT = dyn_cast<RecordType>(CanonicalType)) {
|
if (const RecordType *RT = dyn_cast<RecordType>(CanonicalType)) {
|
||||||
if (RT->getDecl()->getKind() != Decl::Union)
|
if (RT->getDecl()->getKind() != Decl::Union)
|
||||||
|
@ -299,6 +335,10 @@ const RecordType *Type::getAsUnionType() const {
|
||||||
// losing all typedef information.
|
// losing all typedef information.
|
||||||
return getDesugaredType()->getAsUnionType();
|
return getDesugaredType()->getAsUnionType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Look through type qualifiers
|
||||||
|
if (isa<RecordType>(CanonicalType.getUnqualifiedType()))
|
||||||
|
return CanonicalType.getUnqualifiedType()->getAsUnionType();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,8 +348,12 @@ const ComplexType *Type::getAsComplexType() const {
|
||||||
return CTy;
|
return CTy;
|
||||||
|
|
||||||
// If the canonical form of this type isn't the right kind, reject it.
|
// If the canonical form of this type isn't the right kind, reject it.
|
||||||
if (!isa<ComplexType>(CanonicalType))
|
if (!isa<ComplexType>(CanonicalType)) {
|
||||||
|
// Look through type qualifiers
|
||||||
|
if (isa<ComplexType>(CanonicalType.getUnqualifiedType()))
|
||||||
|
return CanonicalType.getUnqualifiedType()->getAsComplexType();
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// If this is a typedef for a complex type, strip the typedef off without
|
// If this is a typedef for a complex type, strip the typedef off without
|
||||||
// losing all typedef information.
|
// losing all typedef information.
|
||||||
|
@ -322,8 +366,12 @@ const VectorType *Type::getAsVectorType() const {
|
||||||
return VTy;
|
return VTy;
|
||||||
|
|
||||||
// If the canonical form of this type isn't the right kind, reject it.
|
// If the canonical form of this type isn't the right kind, reject it.
|
||||||
if (!isa<VectorType>(CanonicalType))
|
if (!isa<VectorType>(CanonicalType)) {
|
||||||
|
// Look through type qualifiers
|
||||||
|
if (isa<VectorType>(CanonicalType.getUnqualifiedType()))
|
||||||
|
return CanonicalType.getUnqualifiedType()->getAsVectorType();
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// If this is a typedef for a vector type, strip the typedef off without
|
// If this is a typedef for a vector type, strip the typedef off without
|
||||||
// losing all typedef information.
|
// losing all typedef information.
|
||||||
|
@ -336,8 +384,12 @@ const OCUVectorType *Type::getAsOCUVectorType() const {
|
||||||
return VTy;
|
return VTy;
|
||||||
|
|
||||||
// If the canonical form of this type isn't the right kind, reject it.
|
// If the canonical form of this type isn't the right kind, reject it.
|
||||||
if (!isa<OCUVectorType>(CanonicalType))
|
if (!isa<OCUVectorType>(CanonicalType)) {
|
||||||
|
// Look through type qualifiers
|
||||||
|
if (isa<OCUVectorType>(CanonicalType.getUnqualifiedType()))
|
||||||
|
return CanonicalType.getUnqualifiedType()->getAsOCUVectorType();
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// If this is a typedef for an ocuvector type, strip the typedef off without
|
// If this is a typedef for an ocuvector type, strip the typedef off without
|
||||||
// losing all typedef information.
|
// losing all typedef information.
|
||||||
|
@ -353,6 +405,8 @@ bool Type::isIntegerType() const {
|
||||||
return true;
|
return true;
|
||||||
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
|
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
|
||||||
return VT->getElementType()->isIntegerType();
|
return VT->getElementType()->isIntegerType();
|
||||||
|
if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
|
||||||
|
return ASQT->getBaseType()->isIntegerType();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,18 +417,24 @@ bool Type::isIntegralType() const {
|
||||||
if (const TagType *TT = dyn_cast<TagType>(CanonicalType))
|
if (const TagType *TT = dyn_cast<TagType>(CanonicalType))
|
||||||
if (TT->getDecl()->getKind() == Decl::Enum)
|
if (TT->getDecl()->getKind() == Decl::Enum)
|
||||||
return true;
|
return true;
|
||||||
|
if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
|
||||||
|
return ASQT->getBaseType()->isIntegralType();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Type::isEnumeralType() const {
|
bool Type::isEnumeralType() const {
|
||||||
if (const TagType *TT = dyn_cast<TagType>(CanonicalType))
|
if (const TagType *TT = dyn_cast<TagType>(CanonicalType))
|
||||||
return TT->getDecl()->getKind() == Decl::Enum;
|
return TT->getDecl()->getKind() == Decl::Enum;
|
||||||
|
if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
|
||||||
|
return ASQT->getBaseType()->isEnumeralType();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Type::isBooleanType() const {
|
bool Type::isBooleanType() const {
|
||||||
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
|
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
|
||||||
return BT->getKind() == BuiltinType::Bool;
|
return BT->getKind() == BuiltinType::Bool;
|
||||||
|
if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
|
||||||
|
return ASQT->getBaseType()->isBooleanType();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -384,6 +444,8 @@ bool Type::isCharType() const {
|
||||||
BT->getKind() == BuiltinType::UChar ||
|
BT->getKind() == BuiltinType::UChar ||
|
||||||
BT->getKind() == BuiltinType::Char_S ||
|
BT->getKind() == BuiltinType::Char_S ||
|
||||||
BT->getKind() == BuiltinType::SChar;
|
BT->getKind() == BuiltinType::SChar;
|
||||||
|
if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
|
||||||
|
return ASQT->getBaseType()->isCharType();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,6 +465,8 @@ bool Type::isSignedIntegerType() const {
|
||||||
|
|
||||||
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
|
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
|
||||||
return VT->getElementType()->isSignedIntegerType();
|
return VT->getElementType()->isSignedIntegerType();
|
||||||
|
if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
|
||||||
|
return ASQT->getBaseType()->isSignedIntegerType();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -422,6 +486,8 @@ bool Type::isUnsignedIntegerType() const {
|
||||||
|
|
||||||
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
|
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
|
||||||
return VT->getElementType()->isUnsignedIntegerType();
|
return VT->getElementType()->isUnsignedIntegerType();
|
||||||
|
if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
|
||||||
|
return ASQT->getBaseType()->isUnsignedIntegerType();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -433,6 +499,8 @@ bool Type::isFloatingType() const {
|
||||||
return CT->getElementType()->isFloatingType();
|
return CT->getElementType()->isFloatingType();
|
||||||
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
|
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
|
||||||
return VT->getElementType()->isFloatingType();
|
return VT->getElementType()->isFloatingType();
|
||||||
|
if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
|
||||||
|
return ASQT->getBaseType()->isFloatingType();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -442,6 +510,8 @@ bool Type::isRealFloatingType() const {
|
||||||
BT->getKind() <= BuiltinType::LongDouble;
|
BT->getKind() <= BuiltinType::LongDouble;
|
||||||
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
|
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
|
||||||
return VT->getElementType()->isRealFloatingType();
|
return VT->getElementType()->isRealFloatingType();
|
||||||
|
if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
|
||||||
|
return ASQT->getBaseType()->isRealFloatingType();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -453,6 +523,8 @@ bool Type::isRealType() const {
|
||||||
return TT->getDecl()->getKind() == Decl::Enum;
|
return TT->getDecl()->getKind() == Decl::Enum;
|
||||||
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
|
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
|
||||||
return VT->getElementType()->isRealType();
|
return VT->getElementType()->isRealType();
|
||||||
|
if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
|
||||||
|
return ASQT->getBaseType()->isRealType();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -464,6 +536,8 @@ bool Type::isArithmeticType() const {
|
||||||
// GCC allows forward declaration of enum types (forbid by C99 6.7.2.3p2).
|
// GCC allows forward declaration of enum types (forbid by C99 6.7.2.3p2).
|
||||||
// If a body isn't seen by the time we get here, return false.
|
// If a body isn't seen by the time we get here, return false.
|
||||||
return ED->isDefinition();
|
return ED->isDefinition();
|
||||||
|
if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
|
||||||
|
return ASQT->getBaseType()->isArithmeticType();
|
||||||
return isa<ComplexType>(CanonicalType) || isa<VectorType>(CanonicalType);
|
return isa<ComplexType>(CanonicalType) || isa<VectorType>(CanonicalType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,6 +549,8 @@ bool Type::isScalarType() const {
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
|
||||||
|
return ASQT->getBaseType()->isScalarType();
|
||||||
return isa<PointerType>(CanonicalType) || isa<ComplexType>(CanonicalType) ||
|
return isa<PointerType>(CanonicalType) || isa<ComplexType>(CanonicalType) ||
|
||||||
isa<ObjCQualifiedIdType>(CanonicalType);
|
isa<ObjCQualifiedIdType>(CanonicalType);
|
||||||
}
|
}
|
||||||
|
@ -485,6 +561,8 @@ bool Type::isAggregateType() const {
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
|
||||||
|
return ASQT->getBaseType()->isAggregateType();
|
||||||
return CanonicalType->getTypeClass() == ConstantArray ||
|
return CanonicalType->getTypeClass() == ConstantArray ||
|
||||||
CanonicalType->getTypeClass() == VariableArray;
|
CanonicalType->getTypeClass() == VariableArray;
|
||||||
}
|
}
|
||||||
|
@ -493,6 +571,8 @@ bool Type::isAggregateType() const {
|
||||||
/// according to the rules of C99 6.7.5p3. It is not legal to call this on
|
/// according to the rules of C99 6.7.5p3. It is not legal to call this on
|
||||||
/// incomplete types.
|
/// incomplete types.
|
||||||
bool Type::isConstantSizeType(ASTContext &Ctx) const {
|
bool Type::isConstantSizeType(ASTContext &Ctx) const {
|
||||||
|
if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
|
||||||
|
return ASQT->getBaseType()->isConstantSizeType(Ctx);
|
||||||
assert(!isIncompleteType() && "This doesn't make sense for incomplete types");
|
assert(!isIncompleteType() && "This doesn't make sense for incomplete types");
|
||||||
// The VAT must have a size, as it is known to be complete.
|
// The VAT must have a size, as it is known to be complete.
|
||||||
return !isa<VariableArrayType>(CanonicalType);
|
return !isa<VariableArrayType>(CanonicalType);
|
||||||
|
@ -504,6 +584,8 @@ bool Type::isConstantSizeType(ASTContext &Ctx) const {
|
||||||
bool Type::isIncompleteType() const {
|
bool Type::isIncompleteType() const {
|
||||||
switch (CanonicalType->getTypeClass()) {
|
switch (CanonicalType->getTypeClass()) {
|
||||||
default: return false;
|
default: return false;
|
||||||
|
case ASQual:
|
||||||
|
return cast<ASQualType>(CanonicalType)->getBaseType()->isIncompleteType();
|
||||||
case Builtin:
|
case Builtin:
|
||||||
// Void is the only incomplete builtin type. Per C99 6.2.5p19, it can never
|
// Void is the only incomplete builtin type. Per C99 6.2.5p19, it can never
|
||||||
// be completed.
|
// be completed.
|
||||||
|
@ -519,6 +601,8 @@ bool Type::isIncompleteType() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Type::isPromotableIntegerType() const {
|
bool Type::isPromotableIntegerType() const {
|
||||||
|
if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
|
||||||
|
return ASQT->getBaseType()->isPromotableIntegerType();
|
||||||
const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType);
|
const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType);
|
||||||
if (!BT) return false;
|
if (!BT) return false;
|
||||||
switch (BT->getKind()) {
|
switch (BT->getKind()) {
|
||||||
|
@ -685,6 +769,11 @@ void ComplexType::getAsStringInternal(std::string &S) const {
|
||||||
S = "_Complex " + S;
|
S = "_Complex " + S;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ASQualType::getAsStringInternal(std::string &S) const {
|
||||||
|
S = "__attribute__((address_space("+llvm::utostr_32(AddressSpace)+")))" + S;
|
||||||
|
BaseType->getAsStringInternal(S);
|
||||||
|
}
|
||||||
|
|
||||||
void PointerType::getAsStringInternal(std::string &S) const {
|
void PointerType::getAsStringInternal(std::string &S) const {
|
||||||
S = '*' + S;
|
S = '*' + S;
|
||||||
|
|
||||||
|
|
|
@ -71,6 +71,10 @@ void Type::Create(ASTContext& Context, unsigned i, Deserializer& D) {
|
||||||
D.RegisterPtr(PtrID,Context.getTypes()[i]);
|
D.RegisterPtr(PtrID,Context.getTypes()[i]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Type::ASQual:
|
||||||
|
D.RegisterPtr(PtrID,ASQualType::CreateImpl(Context,D));
|
||||||
|
break;
|
||||||
|
|
||||||
case Type::Complex:
|
case Type::Complex:
|
||||||
D.RegisterPtr(PtrID,ComplexType::CreateImpl(Context,D));
|
D.RegisterPtr(PtrID,ComplexType::CreateImpl(Context,D));
|
||||||
break;
|
break;
|
||||||
|
@ -105,6 +109,21 @@ void Type::Create(ASTContext& Context, unsigned i, Deserializer& D) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// ASQualType
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
void ASQualType::EmitImpl(Serializer& S) const {
|
||||||
|
S.Emit(getBaseType());
|
||||||
|
S.EmitInt(getAddressSpace());
|
||||||
|
}
|
||||||
|
|
||||||
|
Type* ASQualType::CreateImpl(ASTContext& Context, Deserializer& D) {
|
||||||
|
QualType BaseTy = QualType::ReadVal(D);
|
||||||
|
unsigned AddressSpace = D.ReadInt();
|
||||||
|
return Context.getASQualType(BaseTy, AddressSpace).getTypePtr();
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// ComplexType
|
// ComplexType
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
|
@ -84,7 +84,8 @@ void CodeGenFunction::EmitStaticBlockVarDecl(const BlockVarDecl &D) {
|
||||||
DMEntry =
|
DMEntry =
|
||||||
new llvm::GlobalVariable(LTy, false,
|
new llvm::GlobalVariable(LTy, false,
|
||||||
llvm::GlobalValue::InternalLinkage,
|
llvm::GlobalValue::InternalLinkage,
|
||||||
Init, D.getName(), &CGM.getModule());
|
Init, D.getName(), &CGM.getModule(), 0,
|
||||||
|
Ty.getAddressSpace());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -131,7 +131,8 @@ llvm::Constant *CodeGenModule::GetAddrOfGlobalVar(const VarDecl *D,
|
||||||
llvm::Constant *&Entry = GlobalDeclMap[D];
|
llvm::Constant *&Entry = GlobalDeclMap[D];
|
||||||
if (Entry) return Entry;
|
if (Entry) return Entry;
|
||||||
|
|
||||||
const llvm::Type *Ty = getTypes().ConvertTypeForMem(D->getType());
|
QualType ASTTy = D->getType();
|
||||||
|
const llvm::Type *Ty = getTypes().ConvertTypeForMem(ASTTy);
|
||||||
|
|
||||||
// Check to see if the global already exists.
|
// Check to see if the global already exists.
|
||||||
llvm::GlobalVariable *GV = getModule().getGlobalVariable(D->getName(), true);
|
llvm::GlobalVariable *GV = getModule().getGlobalVariable(D->getName(), true);
|
||||||
|
@ -140,7 +141,8 @@ llvm::Constant *CodeGenModule::GetAddrOfGlobalVar(const VarDecl *D,
|
||||||
if (GV == 0) {
|
if (GV == 0) {
|
||||||
return Entry = new llvm::GlobalVariable(Ty, false,
|
return Entry = new llvm::GlobalVariable(Ty, false,
|
||||||
llvm::GlobalValue::ExternalLinkage,
|
llvm::GlobalValue::ExternalLinkage,
|
||||||
0, D->getName(), &getModule());
|
0, D->getName(), &getModule(), 0,
|
||||||
|
ASTTy.getAddressSpace());
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the pointer type matches, just return it.
|
// If the pointer type matches, just return it.
|
||||||
|
@ -162,7 +164,8 @@ llvm::Constant *CodeGenModule::GetAddrOfGlobalVar(const VarDecl *D,
|
||||||
// making a new global of the correct type, RAUW, then steal the name.
|
// making a new global of the correct type, RAUW, then steal the name.
|
||||||
llvm::GlobalVariable *NewGV =
|
llvm::GlobalVariable *NewGV =
|
||||||
new llvm::GlobalVariable(Ty, false, llvm::GlobalValue::ExternalLinkage,
|
new llvm::GlobalVariable(Ty, false, llvm::GlobalValue::ExternalLinkage,
|
||||||
0, D->getName(), &getModule());
|
0, D->getName(), &getModule(), 0,
|
||||||
|
ASTTy.getAddressSpace());
|
||||||
NewGV->takeName(GV);
|
NewGV->takeName(GV);
|
||||||
|
|
||||||
// Replace uses of GV with the globalvalue we will endow with a body.
|
// Replace uses of GV with the globalvalue we will endow with a body.
|
||||||
|
|
|
@ -199,7 +199,8 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
|
||||||
}
|
}
|
||||||
case Type::Pointer: {
|
case Type::Pointer: {
|
||||||
const PointerType &P = cast<PointerType>(Ty);
|
const PointerType &P = cast<PointerType>(Ty);
|
||||||
return llvm::PointerType::getUnqual(ConvertType(P.getPointeeType()));
|
QualType ETy = P.getPointeeType();
|
||||||
|
return llvm::PointerType::get(ConvertType(ETy), ETy.getAddressSpace());
|
||||||
}
|
}
|
||||||
case Type::Reference: {
|
case Type::Reference: {
|
||||||
const ReferenceType &R = cast<ReferenceType>(Ty);
|
const ReferenceType &R = cast<ReferenceType>(Ty);
|
||||||
|
@ -245,7 +246,8 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
|
||||||
|
|
||||||
// Struct return passes the struct byref.
|
// Struct return passes the struct byref.
|
||||||
if (!ResultType->isFirstClassType() && ResultType != llvm::Type::VoidTy) {
|
if (!ResultType->isFirstClassType() && ResultType != llvm::Type::VoidTy) {
|
||||||
const llvm::Type *RType = llvm::PointerType::getUnqual(ResultType);
|
const llvm::Type *RType = llvm::PointerType::get(ResultType,
|
||||||
|
FP.getResultType().getAddressSpace());
|
||||||
QualType RTy = Context.getPointerType(FP.getResultType());
|
QualType RTy = Context.getPointerType(FP.getResultType());
|
||||||
TypeHolderMap.insert(std::make_pair(RTy.getTypePtr(),
|
TypeHolderMap.insert(std::make_pair(RTy.getTypePtr(),
|
||||||
llvm::PATypeHolder(RType)));
|
llvm::PATypeHolder(RType)));
|
||||||
|
@ -263,6 +265,10 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
|
||||||
|
|
||||||
return llvm::FunctionType::get(ResultType, ArgTys, isVarArg);
|
return llvm::FunctionType::get(ResultType, ArgTys, isVarArg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Type::ASQual:
|
||||||
|
return ConvertType(cast<ASQualType>(Ty).getBaseType());
|
||||||
|
break;
|
||||||
|
|
||||||
case Type::ObjCInterface:
|
case Type::ObjCInterface:
|
||||||
assert(0 && "FIXME: add missing functionality here");
|
assert(0 && "FIXME: add missing functionality here");
|
||||||
|
@ -386,8 +392,10 @@ void CodeGenTypes::DecodeArgumentTypes(const FunctionTypeProto &FTP,
|
||||||
if (Ty->isFirstClassType())
|
if (Ty->isFirstClassType())
|
||||||
ArgTys.push_back(Ty);
|
ArgTys.push_back(Ty);
|
||||||
else {
|
else {
|
||||||
QualType PTy = Context.getPointerType(FTP.getArgType(i));
|
QualType ATy = FTP.getArgType(i);
|
||||||
const llvm::Type *PtrTy = llvm::PointerType::getUnqual(Ty);
|
QualType PTy = Context.getPointerType(ATy);
|
||||||
|
unsigned AS = ATy.getAddressSpace();
|
||||||
|
const llvm::Type *PtrTy = llvm::PointerType::get(Ty, AS);
|
||||||
TypeHolderMap.insert(std::make_pair(PTy.getTypePtr(),
|
TypeHolderMap.insert(std::make_pair(PTy.getTypePtr(),
|
||||||
llvm::PATypeHolder(PtrTy)));
|
llvm::PATypeHolder(PtrTy)));
|
||||||
|
|
||||||
|
|
|
@ -245,7 +245,14 @@ private:
|
||||||
void HandleDeclAttributes(Decl *New, AttributeList *declspec_prefix,
|
void HandleDeclAttributes(Decl *New, AttributeList *declspec_prefix,
|
||||||
AttributeList *declarator_postfix);
|
AttributeList *declarator_postfix);
|
||||||
void HandleDeclAttribute(Decl *New, AttributeList *rawAttr);
|
void HandleDeclAttribute(Decl *New, AttributeList *rawAttr);
|
||||||
|
|
||||||
|
/// HandleAddressSpaceTypeAttribute - this attribute is only applicable to
|
||||||
|
/// objects without automatic storage duration.
|
||||||
|
/// The raw attribute contains 1 argument, the id of the address space
|
||||||
|
/// for the type.
|
||||||
|
QualType HandleAddressSpaceTypeAttribute(QualType curType,
|
||||||
|
AttributeList *rawAttr);
|
||||||
|
|
||||||
// HandleVectorTypeAttribute - this attribute is only applicable to
|
// HandleVectorTypeAttribute - this attribute is only applicable to
|
||||||
// integral and float scalars, although arrays, pointers, and function
|
// integral and float scalars, although arrays, pointers, and function
|
||||||
// return values are allowed in conjunction with this construct. Aggregates
|
// return values are allowed in conjunction with this construct. Aggregates
|
||||||
|
|
|
@ -1760,6 +1760,19 @@ void Sema::HandleDeclAttribute(Decl *New, AttributeList *rawAttr) {
|
||||||
else
|
else
|
||||||
Diag(rawAttr->getAttributeLoc(),
|
Diag(rawAttr->getAttributeLoc(),
|
||||||
diag::err_typecheck_ocu_vector_not_typedef);
|
diag::err_typecheck_ocu_vector_not_typedef);
|
||||||
|
} else if (attrLen == 13 && !memcmp(attrName, "address_space", 13)) {
|
||||||
|
if (TypedefDecl *tDecl = dyn_cast<TypedefDecl>(New)) {
|
||||||
|
QualType newType = HandleAddressSpaceTypeAttribute(
|
||||||
|
tDecl->getUnderlyingType(),
|
||||||
|
rawAttr);
|
||||||
|
if (!newType.isNull()) // install the new addr spaced type into the decl
|
||||||
|
tDecl->setUnderlyingType(newType);
|
||||||
|
} else if (ValueDecl *vDecl = dyn_cast<ValueDecl>(New)) {
|
||||||
|
QualType newType = HandleAddressSpaceTypeAttribute(vDecl->getType(),
|
||||||
|
rawAttr);
|
||||||
|
if (!newType.isNull()) // install the new addr spaced type into the decl
|
||||||
|
vDecl->setType(newType);
|
||||||
|
}
|
||||||
} else if (attrLen == 7 && !memcmp(attrName, "aligned", 7)) {
|
} else if (attrLen == 7 && !memcmp(attrName, "aligned", 7)) {
|
||||||
HandleAlignedAttribute(New, rawAttr);
|
HandleAlignedAttribute(New, rawAttr);
|
||||||
}
|
}
|
||||||
|
@ -1779,6 +1792,34 @@ void Sema::HandleDeclAttributes(Decl *New, AttributeList *declspec_prefix,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QualType Sema::HandleAddressSpaceTypeAttribute(QualType curType,
|
||||||
|
AttributeList *rawAttr) {
|
||||||
|
// check the attribute arugments.
|
||||||
|
if (rawAttr->getNumArgs() != 1) {
|
||||||
|
Diag(rawAttr->getAttributeLoc(), diag::err_attribute_wrong_number_arguments,
|
||||||
|
std::string("1"));
|
||||||
|
return QualType();
|
||||||
|
}
|
||||||
|
Expr *addrSpaceExpr = static_cast<Expr *>(rawAttr->getArg(0));
|
||||||
|
llvm::APSInt addrSpace(32);
|
||||||
|
if (!addrSpaceExpr->isIntegerConstantExpr(addrSpace, Context)) {
|
||||||
|
Diag(rawAttr->getAttributeLoc(), diag::err_attribute_address_space_not_int,
|
||||||
|
addrSpaceExpr->getSourceRange());
|
||||||
|
return QualType();
|
||||||
|
}
|
||||||
|
unsigned addressSpace = static_cast<unsigned>(addrSpace.getZExtValue());
|
||||||
|
|
||||||
|
// Zero is the default memory space, so no qualification is needed
|
||||||
|
if (addressSpace == 0)
|
||||||
|
return curType;
|
||||||
|
|
||||||
|
// TODO: Should we convert contained types of address space
|
||||||
|
// qualified types here or or where they directly participate in conversions
|
||||||
|
// (i.e. elsewhere)
|
||||||
|
|
||||||
|
return Context.getASQualType(curType, addressSpace);
|
||||||
|
}
|
||||||
|
|
||||||
void Sema::HandleOCUVectorTypeAttribute(TypedefDecl *tDecl,
|
void Sema::HandleOCUVectorTypeAttribute(TypedefDecl *tDecl,
|
||||||
AttributeList *rawAttr) {
|
AttributeList *rawAttr) {
|
||||||
QualType curType = tDecl->getUnderlyingType();
|
QualType curType = tDecl->getUnderlyingType();
|
||||||
|
|
|
@ -32,6 +32,7 @@ namespace clang {
|
||||||
/// decls) that can be referred to throughout the semantic analysis of a file.
|
/// decls) that can be referred to throughout the semantic analysis of a file.
|
||||||
class ASTContext {
|
class ASTContext {
|
||||||
std::vector<Type*> Types;
|
std::vector<Type*> Types;
|
||||||
|
llvm::FoldingSet<ASQualType> ASQualTypes;
|
||||||
llvm::FoldingSet<ComplexType> ComplexTypes;
|
llvm::FoldingSet<ComplexType> ComplexTypes;
|
||||||
llvm::FoldingSet<PointerType> PointerTypes;
|
llvm::FoldingSet<PointerType> PointerTypes;
|
||||||
llvm::FoldingSet<ReferenceType> ReferenceTypes;
|
llvm::FoldingSet<ReferenceType> ReferenceTypes;
|
||||||
|
@ -120,6 +121,10 @@ public:
|
||||||
// Type Constructors
|
// Type Constructors
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
/// getAddrSpaceQualType - Return the uniqued reference to the type for an
|
||||||
|
/// address space qualified type with the specified type and address space.
|
||||||
|
QualType getASQualType(QualType T, unsigned AddressSpace);
|
||||||
|
|
||||||
/// getComplexType - Return the uniqued reference to the type for a complex
|
/// getComplexType - Return the uniqued reference to the type for a complex
|
||||||
/// number with the specified element type.
|
/// number with the specified element type.
|
||||||
QualType getComplexType(QualType T);
|
QualType getComplexType(QualType T);
|
||||||
|
|
|
@ -50,6 +50,7 @@ namespace clang {
|
||||||
class FunctionType;
|
class FunctionType;
|
||||||
class OCUVectorType;
|
class OCUVectorType;
|
||||||
class BuiltinType;
|
class BuiltinType;
|
||||||
|
class ASQualType;
|
||||||
class ObjCQualifiedInterfaceType;
|
class ObjCQualifiedInterfaceType;
|
||||||
class StmtIteratorBase;
|
class StmtIteratorBase;
|
||||||
|
|
||||||
|
@ -132,9 +133,7 @@ public:
|
||||||
return QualType(getTypePtr(), TQs);
|
return QualType(getTypePtr(), TQs);
|
||||||
}
|
}
|
||||||
|
|
||||||
QualType getUnqualifiedType() const {
|
inline QualType getUnqualifiedType() const;
|
||||||
return QualType(getTypePtr(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// operator==/!= - Indicate whether the specified types and qualifiers are
|
/// operator==/!= - Indicate whether the specified types and qualifiers are
|
||||||
/// identical.
|
/// identical.
|
||||||
|
@ -157,6 +156,9 @@ public:
|
||||||
/// appropriate type qualifiers on it.
|
/// appropriate type qualifiers on it.
|
||||||
inline QualType getCanonicalType() const;
|
inline QualType getCanonicalType() const;
|
||||||
|
|
||||||
|
/// getAddressSpace - Return the address space of this type.
|
||||||
|
inline unsigned getAddressSpace() const;
|
||||||
|
|
||||||
/// Emit - Serialize a QualType to Bitcode.
|
/// Emit - Serialize a QualType to Bitcode.
|
||||||
void Emit(llvm::Serializer& S) const;
|
void Emit(llvm::Serializer& S) const;
|
||||||
|
|
||||||
|
@ -218,7 +220,7 @@ public:
|
||||||
ConstantArray, VariableArray,
|
ConstantArray, VariableArray,
|
||||||
Vector, OCUVector,
|
Vector, OCUVector,
|
||||||
FunctionNoProto, FunctionProto,
|
FunctionNoProto, FunctionProto,
|
||||||
TypeName, Tagged,
|
TypeName, Tagged, ASQual,
|
||||||
ObjCInterface, ObjCQualifiedInterface,
|
ObjCInterface, ObjCQualifiedInterface,
|
||||||
ObjCQualifiedId,
|
ObjCQualifiedId,
|
||||||
TypeOfExp, TypeOfTyp // GNU typeof extension.
|
TypeOfExp, TypeOfTyp // GNU typeof extension.
|
||||||
|
@ -229,7 +231,7 @@ private:
|
||||||
/// TypeClass bitfield - Enum that specifies what subclass this belongs to.
|
/// TypeClass bitfield - Enum that specifies what subclass this belongs to.
|
||||||
/// Note that this should stay at the end of the ivars for Type so that
|
/// Note that this should stay at the end of the ivars for Type so that
|
||||||
/// subclasses can pack their bitfields into the same word.
|
/// subclasses can pack their bitfields into the same word.
|
||||||
unsigned TC : 4;
|
unsigned TC : 5;
|
||||||
protected:
|
protected:
|
||||||
// silence VC++ warning C4355: 'this' : used in base member initializer list
|
// silence VC++ warning C4355: 'this' : used in base member initializer list
|
||||||
Type *this_() { return this; }
|
Type *this_() { return this; }
|
||||||
|
@ -268,7 +270,7 @@ public:
|
||||||
bool isIncompleteArrayType() const;
|
bool isIncompleteArrayType() const;
|
||||||
|
|
||||||
/// Helper methods to distinguish type categories. All type predicates
|
/// Helper methods to distinguish type categories. All type predicates
|
||||||
/// operate on the canonical type, ignoring typedefs.
|
/// operate on the canonical type, ignoring typedefs and qualifiers.
|
||||||
|
|
||||||
/// isIntegerType() does *not* include complex integers (a GCC extension).
|
/// isIntegerType() does *not* include complex integers (a GCC extension).
|
||||||
/// isComplexIntegerType() can be used to test for complex integers.
|
/// isComplexIntegerType() can be used to test for complex integers.
|
||||||
|
@ -292,7 +294,7 @@ public:
|
||||||
bool isAggregateType() const; // C99 6.2.5p21 (arrays, structures)
|
bool isAggregateType() const; // C99 6.2.5p21 (arrays, structures)
|
||||||
|
|
||||||
// Type Predicates: Check to see if this type is structurally the specified
|
// Type Predicates: Check to see if this type is structurally the specified
|
||||||
// type, ignoring typedefs.
|
// type, ignoring typedefs and qualifiers.
|
||||||
bool isFunctionType() const;
|
bool isFunctionType() const;
|
||||||
bool isPointerType() const;
|
bool isPointerType() const;
|
||||||
bool isFunctionPointerType() const;
|
bool isFunctionPointerType() const;
|
||||||
|
@ -308,7 +310,7 @@ public:
|
||||||
bool isObjCQualifiedIdType() const; // id includes conforming protocol type
|
bool isObjCQualifiedIdType() const; // id includes conforming protocol type
|
||||||
|
|
||||||
// Type Checking Functions: Check to see if this type is structurally the
|
// Type Checking Functions: Check to see if this type is structurally the
|
||||||
// specified type, ignoring typedefs, and return a pointer to the best type
|
// specified type, ignoring typedefs and qualifiers, and return a pointer to the best type
|
||||||
// we can.
|
// we can.
|
||||||
const BuiltinType *getAsBuiltinType() const;
|
const BuiltinType *getAsBuiltinType() const;
|
||||||
const FunctionType *getAsFunctionType() const;
|
const FunctionType *getAsFunctionType() const;
|
||||||
|
@ -373,6 +375,42 @@ protected:
|
||||||
virtual void EmitImpl(llvm::Serializer& S) const;
|
virtual void EmitImpl(llvm::Serializer& S) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// ASQualType - TR18037 (C embedded extensions) 6.2.5p26
|
||||||
|
/// This supports address space qualified types.
|
||||||
|
///
|
||||||
|
class ASQualType : public Type, public llvm::FoldingSetNode {
|
||||||
|
QualType BaseType;
|
||||||
|
/// Address Space ID - The address space ID this type is qualified with.
|
||||||
|
unsigned AddressSpace;
|
||||||
|
ASQualType(QualType Base, QualType CanonicalPtr, unsigned AddrSpace) :
|
||||||
|
Type(ASQual, CanonicalPtr), BaseType(Base), AddressSpace(AddrSpace) {
|
||||||
|
}
|
||||||
|
friend class ASTContext; // ASTContext creates these.
|
||||||
|
public:
|
||||||
|
QualType getBaseType() const { return BaseType; }
|
||||||
|
unsigned getAddressSpace() const { return AddressSpace; }
|
||||||
|
|
||||||
|
virtual void getAsStringInternal(std::string &InnerString) const;
|
||||||
|
|
||||||
|
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||||
|
Profile(ID, getBaseType(), AddressSpace);
|
||||||
|
}
|
||||||
|
static void Profile(llvm::FoldingSetNodeID &ID, QualType Base,
|
||||||
|
unsigned AddrSpace) {
|
||||||
|
ID.AddPointer(Base.getAsOpaquePtr());
|
||||||
|
ID.AddInteger(AddrSpace);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool classof(const Type *T) { return T->getTypeClass() == ASQual; }
|
||||||
|
static bool classof(const ASQualType *) { return true; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void EmitImpl(llvm::Serializer& S) const;
|
||||||
|
static Type* CreateImpl(ASTContext& Context,llvm::Deserializer& D);
|
||||||
|
friend class Type;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/// BuiltinType - This class is used for builtin types like 'int'. Builtin
|
/// BuiltinType - This class is used for builtin types like 'int'. Builtin
|
||||||
/// types are always canonical and have a literal name field.
|
/// types are always canonical and have a literal name field.
|
||||||
class BuiltinType : public Type {
|
class BuiltinType : public Type {
|
||||||
|
@ -1036,12 +1074,25 @@ inline QualType QualType::getCanonicalType() const {
|
||||||
getTypePtr()->getCanonicalTypeInternal().getQualifiers());
|
getTypePtr()->getCanonicalTypeInternal().getQualifiers());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// getUnqualifiedType - Return the type without any qualifiers.
|
||||||
|
inline QualType QualType::getUnqualifiedType() const {
|
||||||
|
if (const ASQualType *ASQT = dyn_cast<ASQualType>(getTypePtr()))
|
||||||
|
return ASQT->getBaseType().getUnqualifiedType();
|
||||||
|
return QualType(getTypePtr(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// getAddressSpace - Return the address space of this type.
|
||||||
|
inline unsigned QualType::getAddressSpace() const {
|
||||||
|
if (const ASQualType *ASQT = dyn_cast<ASQualType>(getTypePtr()))
|
||||||
|
return ASQT->getAddressSpace();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool Type::isFunctionType() const {
|
inline bool Type::isFunctionType() const {
|
||||||
return isa<FunctionType>(CanonicalType);
|
return isa<FunctionType>(CanonicalType.getUnqualifiedType());
|
||||||
}
|
}
|
||||||
inline bool Type::isPointerType() const {
|
inline bool Type::isPointerType() const {
|
||||||
return isa<PointerType>(CanonicalType);
|
return isa<PointerType>(CanonicalType.getUnqualifiedType());
|
||||||
}
|
}
|
||||||
inline bool Type::isFunctionPointerType() const {
|
inline bool Type::isFunctionPointerType() const {
|
||||||
if (const PointerType* T = getAsPointerType())
|
if (const PointerType* T = getAsPointerType())
|
||||||
|
@ -1050,19 +1101,19 @@ inline bool Type::isFunctionPointerType() const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
inline bool Type::isReferenceType() const {
|
inline bool Type::isReferenceType() const {
|
||||||
return isa<ReferenceType>(CanonicalType);
|
return isa<ReferenceType>(CanonicalType.getUnqualifiedType());
|
||||||
}
|
}
|
||||||
inline bool Type::isArrayType() const {
|
inline bool Type::isArrayType() const {
|
||||||
return isa<ArrayType>(CanonicalType);
|
return isa<ArrayType>(CanonicalType.getUnqualifiedType());
|
||||||
}
|
}
|
||||||
inline bool Type::isRecordType() const {
|
inline bool Type::isRecordType() const {
|
||||||
return isa<RecordType>(CanonicalType);
|
return isa<RecordType>(CanonicalType.getUnqualifiedType());
|
||||||
}
|
}
|
||||||
inline bool Type::isVectorType() const {
|
inline bool Type::isVectorType() const {
|
||||||
return isa<VectorType>(CanonicalType);
|
return isa<VectorType>(CanonicalType.getUnqualifiedType());
|
||||||
}
|
}
|
||||||
inline bool Type::isOCUVectorType() const {
|
inline bool Type::isOCUVectorType() const {
|
||||||
return isa<OCUVectorType>(CanonicalType);
|
return isa<OCUVectorType>(CanonicalType.getUnqualifiedType());
|
||||||
}
|
}
|
||||||
inline bool Type::isObjCInterfaceType() const {
|
inline bool Type::isObjCInterfaceType() const {
|
||||||
return isa<ObjCInterfaceType>(CanonicalType)
|
return isa<ObjCInterfaceType>(CanonicalType)
|
||||||
|
|
|
@ -575,6 +575,8 @@ DIAG(err_ocuvector_component_name_illegal, ERROR,
|
||||||
"illegal vector component name '%0'")
|
"illegal vector component name '%0'")
|
||||||
DIAG(err_ocuvector_component_access, ERROR,
|
DIAG(err_ocuvector_component_access, ERROR,
|
||||||
"vector component access limited to variables")
|
"vector component access limited to variables")
|
||||||
|
DIAG(err_attribute_address_space_not_int, ERROR,
|
||||||
|
"address space attribute requires an integer constant")
|
||||||
|
|
||||||
// Function Parameter Semantic Analysis.
|
// Function Parameter Semantic Analysis.
|
||||||
DIAG(err_param_with_void_type, ERROR,
|
DIAG(err_param_with_void_type, ERROR,
|
||||||
|
@ -953,5 +955,4 @@ DIAG(ext_return_has_expr, EXTENSION,
|
||||||
"void function '%0' should not return a value")
|
"void function '%0' should not return a value")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#undef DIAG
|
#undef DIAG
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
// RUN: clang -emit-llvm < %s 2>&1 | grep 'addrspace(1)' | count 5
|
||||||
|
int foo __attribute__((address_space(1)));
|
||||||
|
int ban[10] __attribute__((address_space(1)));
|
||||||
|
|
||||||
|
int bar() { return foo; }
|
||||||
|
|
||||||
|
int baz(int i) { return ban[i]; }
|
Loading…
Reference in New Issue