}
break;
}
+ case Type::ASQual:
+ return getTypeInfo(cast<ASQualType>(T)->getBaseType(), L);
case Type::ObjCQualifiedId:
Target.getPointerInfo(Size, Align, getFullLoc(L));
break;
// 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
/// number with the specified element type.
return 4;
}
- const BuiltinType *BT = cast<BuiltinType>(t.getCanonicalType());
+ const BuiltinType *BT = t.getCanonicalType()->getAsBuiltinType();
switch (BT->getKind()) {
default:
assert(0 && "getIntegerRank(): not a built-in integer");
/// This routine will assert if passed a built-in type that isn't a float.
static int getFloatingRank(QualType T) {
T = T.getCanonicalType();
- if (ComplexType *CT = dyn_cast<ComplexType>(T))
+ if (const ComplexType *CT = T->getAsComplexType())
return getFloatingRank(CT->getElementType());
- switch (cast<BuiltinType>(T)->getKind()) {
+ switch (T->getAsBuiltinType()->getKind()) {
default: assert(0 && "getFloatingRank(): not a floating type");
case BuiltinType::Float: return FloatRank;
case BuiltinType::Double: return DoubleRank;
return BTy;
// 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;
+ }
// If this is a typedef for a builtin type, strip the typedef off without
// losing all typedef information.
// If this is directly a function type, return it.
if (const FunctionType *FTy = dyn_cast<FunctionType>(this))
return FTy;
-
+
// 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;
+ }
// If this is a typedef for a function type, strip the typedef off without
// losing all typedef information.
return PTy;
// 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;
+ }
// If this is a typedef for a pointer type, strip the typedef off without
// losing all typedef information.
return RTy;
// 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;
+ }
// If this is a typedef for a reference type, strip the typedef off without
// losing all typedef information.
return ATy;
// 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;
+ }
// If this is a typedef for an array type, strip the typedef off without
// losing all typedef information.
// If this is directly a constant array type, return it.
if (const ConstantArrayType *ATy = dyn_cast<ConstantArrayType>(this))
return ATy;
-
+
// 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;
+ }
// If this is a typedef for a constant array type, strip the typedef off
// without losing all typedef information.
return ATy;
// 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;
+ }
// If this is a typedef for a variable array type, strip the typedef off
// without losing all typedef information.
return RTy;
// 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;
+ }
// If this is a typedef for a record type, strip the typedef off without
// losing all typedef information.
// losing all typedef information.
return getDesugaredType()->getAsStructureType();
}
+ // Look through type qualifiers
+ if (isa<RecordType>(CanonicalType.getUnqualifiedType()))
+ return CanonicalType.getUnqualifiedType()->getAsStructureType();
return 0;
}
if (RT->getDecl()->getKind() == Decl::Union)
return RT;
}
+
// If the canonical form of this type isn't the right kind, reject it.
if (const RecordType *RT = dyn_cast<RecordType>(CanonicalType)) {
if (RT->getDecl()->getKind() != Decl::Union)
// losing all typedef information.
return getDesugaredType()->getAsUnionType();
}
+
+ // Look through type qualifiers
+ if (isa<RecordType>(CanonicalType.getUnqualifiedType()))
+ return CanonicalType.getUnqualifiedType()->getAsUnionType();
return 0;
}
return CTy;
// 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;
+ }
// If this is a typedef for a complex type, strip the typedef off without
// losing all typedef information.
return VTy;
// 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;
+ }
// If this is a typedef for a vector type, strip the typedef off without
// losing all typedef information.
return VTy;
// 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;
+ }
// If this is a typedef for an ocuvector type, strip the typedef off without
// losing all typedef information.
return true;
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isIntegerType();
+ if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+ return ASQT->getBaseType()->isIntegerType();
return false;
}
if (const TagType *TT = dyn_cast<TagType>(CanonicalType))
if (TT->getDecl()->getKind() == Decl::Enum)
return true;
+ if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+ return ASQT->getBaseType()->isIntegralType();
return false;
}
bool Type::isEnumeralType() const {
if (const TagType *TT = dyn_cast<TagType>(CanonicalType))
return TT->getDecl()->getKind() == Decl::Enum;
+ if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+ return ASQT->getBaseType()->isEnumeralType();
return false;
}
bool Type::isBooleanType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() == BuiltinType::Bool;
+ if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+ return ASQT->getBaseType()->isBooleanType();
return false;
}
BT->getKind() == BuiltinType::UChar ||
BT->getKind() == BuiltinType::Char_S ||
BT->getKind() == BuiltinType::SChar;
+ if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+ return ASQT->getBaseType()->isCharType();
return false;
}
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isSignedIntegerType();
+ if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+ return ASQT->getBaseType()->isSignedIntegerType();
return false;
}
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isUnsignedIntegerType();
+ if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+ return ASQT->getBaseType()->isUnsignedIntegerType();
return false;
}
return CT->getElementType()->isFloatingType();
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isFloatingType();
+ if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+ return ASQT->getBaseType()->isFloatingType();
return false;
}
BT->getKind() <= BuiltinType::LongDouble;
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isRealFloatingType();
+ if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+ return ASQT->getBaseType()->isRealFloatingType();
return false;
}
return TT->getDecl()->getKind() == Decl::Enum;
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isRealType();
+ if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+ return ASQT->getBaseType()->isRealType();
return false;
}
// 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.
return ED->isDefinition();
+ if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+ return ASQT->getBaseType()->isArithmeticType();
return isa<ComplexType>(CanonicalType) || isa<VectorType>(CanonicalType);
}
return true;
return false;
}
+ if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+ return ASQT->getBaseType()->isScalarType();
return isa<PointerType>(CanonicalType) || isa<ComplexType>(CanonicalType) ||
isa<ObjCQualifiedIdType>(CanonicalType);
}
return true;
return false;
}
+ if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+ return ASQT->getBaseType()->isAggregateType();
return CanonicalType->getTypeClass() == ConstantArray ||
CanonicalType->getTypeClass() == VariableArray;
}
/// according to the rules of C99 6.7.5p3. It is not legal to call this on
/// incomplete types.
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");
// The VAT must have a size, as it is known to be complete.
return !isa<VariableArrayType>(CanonicalType);
bool Type::isIncompleteType() const {
switch (CanonicalType->getTypeClass()) {
default: return false;
+ case ASQual:
+ return cast<ASQualType>(CanonicalType)->getBaseType()->isIncompleteType();
case Builtin:
// Void is the only incomplete builtin type. Per C99 6.2.5p19, it can never
// be completed.
}
bool Type::isPromotableIntegerType() const {
+ if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+ return ASQT->getBaseType()->isPromotableIntegerType();
const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType);
if (!BT) return false;
switch (BT->getKind()) {
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 {
S = '*' + S;
D.RegisterPtr(PtrID,Context.getTypes()[i]);
break;
+ case Type::ASQual:
+ D.RegisterPtr(PtrID,ASQualType::CreateImpl(Context,D));
+ break;
+
case Type::Complex:
D.RegisterPtr(PtrID,ComplexType::CreateImpl(Context,D));
break;
}
}
+//===----------------------------------------------------------------------===//
+// 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
//===----------------------------------------------------------------------===//
DMEntry =
new llvm::GlobalVariable(LTy, false,
llvm::GlobalValue::InternalLinkage,
- Init, D.getName(), &CGM.getModule());
+ Init, D.getName(), &CGM.getModule(), 0,
+ Ty.getAddressSpace());
}
llvm::Constant *&Entry = GlobalDeclMap[D];
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.
llvm::GlobalVariable *GV = getModule().getGlobalVariable(D->getName(), true);
if (GV == 0) {
return Entry = new llvm::GlobalVariable(Ty, false,
llvm::GlobalValue::ExternalLinkage,
- 0, D->getName(), &getModule());
+ 0, D->getName(), &getModule(), 0,
+ ASTTy.getAddressSpace());
}
// If the pointer type matches, just return it.
// making a new global of the correct type, RAUW, then steal the name.
llvm::GlobalVariable *NewGV =
new llvm::GlobalVariable(Ty, false, llvm::GlobalValue::ExternalLinkage,
- 0, D->getName(), &getModule());
+ 0, D->getName(), &getModule(), 0,
+ ASTTy.getAddressSpace());
NewGV->takeName(GV);
// Replace uses of GV with the globalvalue we will endow with a body.
}
case Type::Pointer: {
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: {
const ReferenceType &R = cast<ReferenceType>(Ty);
// Struct return passes the struct byref.
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());
TypeHolderMap.insert(std::make_pair(RTy.getTypePtr(),
llvm::PATypeHolder(RType)));
return llvm::FunctionType::get(ResultType, ArgTys, isVarArg);
}
+
+ case Type::ASQual:
+ return ConvertType(cast<ASQualType>(Ty).getBaseType());
+ break;
case Type::ObjCInterface:
assert(0 && "FIXME: add missing functionality here");
if (Ty->isFirstClassType())
ArgTys.push_back(Ty);
else {
- QualType PTy = Context.getPointerType(FTP.getArgType(i));
- const llvm::Type *PtrTy = llvm::PointerType::getUnqual(Ty);
+ QualType ATy = FTP.getArgType(i);
+ 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(),
llvm::PATypeHolder(PtrTy)));
void HandleDeclAttributes(Decl *New, AttributeList *declspec_prefix,
AttributeList *declarator_postfix);
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
// integral and float scalars, although arrays, pointers, and function
// return values are allowed in conjunction with this construct. Aggregates
else
Diag(rawAttr->getAttributeLoc(),
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)) {
HandleAlignedAttribute(New, rawAttr);
}
}
}
+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,
AttributeList *rawAttr) {
QualType curType = tDecl->getUnderlyingType();
/// decls) that can be referred to throughout the semantic analysis of a file.
class ASTContext {
std::vector<Type*> Types;
+ llvm::FoldingSet<ASQualType> ASQualTypes;
llvm::FoldingSet<ComplexType> ComplexTypes;
llvm::FoldingSet<PointerType> PointerTypes;
llvm::FoldingSet<ReferenceType> ReferenceTypes;
// 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
/// number with the specified element type.
QualType getComplexType(QualType T);
class FunctionType;
class OCUVectorType;
class BuiltinType;
+ class ASQualType;
class ObjCQualifiedInterfaceType;
class StmtIteratorBase;
return QualType(getTypePtr(), TQs);
}
- QualType getUnqualifiedType() const {
- return QualType(getTypePtr(), 0);
- }
+ inline QualType getUnqualifiedType() const;
/// operator==/!= - Indicate whether the specified types and qualifiers are
/// identical.
/// appropriate type qualifiers on it.
inline QualType getCanonicalType() const;
+ /// getAddressSpace - Return the address space of this type.
+ inline unsigned getAddressSpace() const;
+
/// Emit - Serialize a QualType to Bitcode.
void Emit(llvm::Serializer& S) const;
ConstantArray, VariableArray,
Vector, OCUVector,
FunctionNoProto, FunctionProto,
- TypeName, Tagged,
+ TypeName, Tagged, ASQual,
ObjCInterface, ObjCQualifiedInterface,
ObjCQualifiedId,
TypeOfExp, TypeOfTyp // GNU typeof extension.
/// 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
/// subclasses can pack their bitfields into the same word.
- unsigned TC : 4;
+ unsigned TC : 5;
protected:
// silence VC++ warning C4355: 'this' : used in base member initializer list
Type *this_() { return this; }
bool isIncompleteArrayType() const;
/// 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).
/// isComplexIntegerType() can be used to test for complex integers.
bool isAggregateType() const; // C99 6.2.5p21 (arrays, structures)
// Type Predicates: Check to see if this type is structurally the specified
- // type, ignoring typedefs.
+ // type, ignoring typedefs and qualifiers.
bool isFunctionType() const;
bool isPointerType() const;
bool isFunctionPointerType() const;
bool isObjCQualifiedIdType() const; // id includes conforming protocol type
// 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.
const BuiltinType *getAsBuiltinType() const;
const FunctionType *getAsFunctionType() 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
/// types are always canonical and have a literal name field.
class BuiltinType : public Type {
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 {
- return isa<FunctionType>(CanonicalType);
+ return isa<FunctionType>(CanonicalType.getUnqualifiedType());
}
inline bool Type::isPointerType() const {
- return isa<PointerType>(CanonicalType);
+ return isa<PointerType>(CanonicalType.getUnqualifiedType());
}
inline bool Type::isFunctionPointerType() const {
if (const PointerType* T = getAsPointerType())
return false;
}
inline bool Type::isReferenceType() const {
- return isa<ReferenceType>(CanonicalType);
+ return isa<ReferenceType>(CanonicalType.getUnqualifiedType());
}
inline bool Type::isArrayType() const {
- return isa<ArrayType>(CanonicalType);
+ return isa<ArrayType>(CanonicalType.getUnqualifiedType());
}
inline bool Type::isRecordType() const {
- return isa<RecordType>(CanonicalType);
+ return isa<RecordType>(CanonicalType.getUnqualifiedType());
}
inline bool Type::isVectorType() const {
- return isa<VectorType>(CanonicalType);
+ return isa<VectorType>(CanonicalType.getUnqualifiedType());
}
inline bool Type::isOCUVectorType() const {
- return isa<OCUVectorType>(CanonicalType);
+ return isa<OCUVectorType>(CanonicalType.getUnqualifiedType());
}
inline bool Type::isObjCInterfaceType() const {
return isa<ObjCInterfaceType>(CanonicalType)
"illegal vector component name '%0'")
DIAG(err_ocuvector_component_access, ERROR,
"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.
DIAG(err_param_with_void_type, ERROR,
"void function '%0' should not return a value")
-
#undef DIAG
--- /dev/null
+// 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]; }
\ No newline at end of file