Index: include/clang/AST/ASTContext.h =================================================================== --- include/clang/AST/ASTContext.h +++ include/clang/AST/ASTContext.h @@ -143,6 +143,8 @@ mutable llvm::FoldingSet DependentSizedArrayTypes; mutable llvm::FoldingSet DependentSizedExtVectorTypes; + mutable llvm::FoldingSet + DependentExtAddressSpaceTypes; mutable llvm::FoldingSet VectorTypes; mutable llvm::FoldingSet FunctionNoProtoTypes; mutable llvm::ContextualFoldingSet @@ -1069,6 +1071,13 @@ /// replaced. QualType getAddrSpaceQualType(QualType T, unsigned AddressSpace) const; + /// \brief Remove any existing address space on the type and returns the type + /// with qualifiers intact. + /// + /// The return type should be T with all prior qualifiers minus the address + /// space. + QualType removeAddrSpaceQualType(QualType T) const; + /// \brief Apply Objective-C protocol qualifiers to the given type. /// \param allowOnPointerType specifies if we can apply protocol /// qualifiers on ObjCObjectPointerType. It can be set to true when @@ -1269,6 +1278,10 @@ Expr *SizeExpr, SourceLocation AttrLoc) const; + QualType getDependentExtAddressSpaceType(QualType PointerType, + Expr *AddrSpaceExpr, + SourceLocation AttrLoc) const; + /// \brief Return a K&R style C function type like 'int()'. QualType getFunctionNoProtoType(QualType ResultTy, const FunctionType::ExtInfo &Info) const; Index: include/clang/AST/RecursiveASTVisitor.h =================================================================== --- include/clang/AST/RecursiveASTVisitor.h +++ include/clang/AST/RecursiveASTVisitor.h @@ -968,6 +968,12 @@ TRY_TO(TraverseStmt(T->getSizeExpr())); }) +DEF_TRAVERSE_TYPE(DependentExtAddressSpaceType, { + if (T->getAddrSpaceExpr()) + TRY_TO(TraverseStmt(T->getAddrSpaceExpr())); + TRY_TO(TraverseType(T->getPointerType())); +}) + DEF_TRAVERSE_TYPE(DependentSizedExtVectorType, { if (T->getSizeExpr()) TRY_TO(TraverseStmt(T->getSizeExpr())); @@ -1174,6 +1180,14 @@ return TraverseArrayTypeLocHelper(TL); }) +// Based on DependentSizedExtVectorType, so any fixes it requires should +// be considered here as well +DEF_TRAVERSE_TYPELOC(DependentExtAddressSpaceType, { + if (TL.getTypePtr()->getAddrSpaceExpr()) + TRY_TO(TraverseStmt(TL.getTypePtr()->getAddrSpaceExpr())); + TRY_TO(TraverseType(TL.getTypePtr()->getPointerType())); +}) + // FIXME: order? why not size expr first? // FIXME: base VectorTypeLoc is unfinished DEF_TRAVERSE_TYPELOC(DependentSizedExtVectorType, { Index: include/clang/AST/Type.h =================================================================== --- include/clang/AST/Type.h +++ include/clang/AST/Type.h @@ -1708,6 +1708,8 @@ bool isComplexIntegerType() const; // GCC _Complex integer type. bool isVectorType() const; // GCC vector type. bool isExtVectorType() const; // Extended vector type. + bool isDependentExtAddressSpaceType() + const; // type for Extended Address Spaces, allowing dependent AS index. bool isObjCObjectPointerType() const; // pointer to ObjC object bool isObjCRetainableType() const; // ObjC object or block pointer bool isObjCLifetimeType() const; // (array of)* retainable type @@ -2744,6 +2746,49 @@ unsigned TypeQuals, Expr *E); }; +/// Represents an extended address space qualifier where the input address space +/// value is dependent. This in essence is a wrapper class that is thrown away for +/// the underlying type when the real value can be substituted in. +/// +/// For example: +/// \code +/// template +/// class AddressSpace { +/// typedef T __attribute__((ext_address_space(AddrSpace))) type; +/// } +/// \endcode +class DependentExtAddressSpaceType : public Type, public llvm::FoldingSetNode { + const ASTContext &Context; + Expr *AddrSpaceExpr; + QualType PointerType; + SourceLocation loc; + + DependentExtAddressSpaceType(const ASTContext &Context, QualType PointerType, + QualType can, Expr *AddrSpaceExpr, + SourceLocation loc); + + friend class ASTContext; + +public: + Expr *getAddrSpaceExpr() const { return AddrSpaceExpr; } + QualType getPointerType() const { return PointerType; } + SourceLocation getAttributeLoc() const { return loc; } + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + static bool classof(const Type *T) { + return T->getTypeClass() == DependentExtAddressSpace; + } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, Context, getPointerType(), getAddrSpaceExpr()); + } + + static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, + QualType PointerType, Expr *AddrSpaceExpr); +}; + /// Represents an extended vector type where either the type or size is /// dependent. /// @@ -5778,6 +5823,9 @@ inline bool Type::isExtVectorType() const { return isa(CanonicalType); } +inline bool Type::isDependentExtAddressSpaceType() const { + return isa(CanonicalType); +} inline bool Type::isObjCObjectPointerType() const { return isa(CanonicalType); } Index: include/clang/AST/TypeLoc.h =================================================================== --- include/clang/AST/TypeLoc.h +++ include/clang/AST/TypeLoc.h @@ -1685,10 +1685,19 @@ // FIXME: attribute locations. // For some reason, this isn't a subtype of VectorType. -class DependentSizedExtVectorTypeLoc : - public InheritingConcreteTypeLoc { +class DependentSizedExtVectorTypeLoc + : public InheritingConcreteTypeLoc { +}; + +// FIXME: This should recieve an address space expression +// and attribute location, similar to the ExtVectorTypeLoc's +// which it's based on. +class DependentExtAddressSpaceTypeLoc + : public InheritingConcreteTypeLoc { }; // FIXME: location of the '_Complex' keyword. Index: include/clang/AST/TypeNodes.def =================================================================== --- include/clang/AST/TypeNodes.def +++ include/clang/AST/TypeNodes.def @@ -73,6 +73,7 @@ TYPE(VariableArray, ArrayType) DEPENDENT_TYPE(DependentSizedArray, ArrayType) DEPENDENT_TYPE(DependentSizedExtVector, Type) +DEPENDENT_TYPE(DependentExtAddressSpace, Type) TYPE(Vector, Type) TYPE(ExtVector, VectorType) ABSTRACT_TYPE(Function, Type) Index: include/clang/Basic/Attr.td =================================================================== --- include/clang/Basic/Attr.td +++ include/clang/Basic/Attr.td @@ -502,6 +502,13 @@ let Documentation = [Undocumented]; } +def ExtAddressSpace : Attr { + let Spellings = [GNU<"ext_address_space">]; + let Args = [ExprArgument<"AddressSpace">]; + let ASTNode = 0; + let Documentation = [Undocumented]; +} + def Alias : Attr { let Spellings = [GCC<"alias">]; let Args = [StringArgument<"Aliasee">]; Index: include/clang/Sema/ExternalSemaSource.h =================================================================== --- include/clang/Sema/ExternalSemaSource.h +++ include/clang/Sema/ExternalSemaSource.h @@ -136,6 +136,15 @@ /// introduce the same declarations repeatedly. virtual void ReadExtVectorDecls(SmallVectorImpl &Decls) {} + /// \brief Read the set of ext_address_space type declarations known to the + /// external Sema source. + /// + /// The external source should append its own ext_address_space type + /// declarations to the given vector of declarations. Note that this + /// routine may be invoked multiple times; the external source should + /// take care not to introduce the same declarations repeatedly. + virtual void ReadExtAddressSpaceDecls(SmallVectorImpl &Decls) {} + /// \brief Read the set of potentially unused typedefs known to the source. /// /// The external source should append its own potentially unused local Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -495,6 +495,16 @@ /// This is only necessary for issuing pretty diagnostics. ExtVectorDeclsType ExtVectorDecls; + typedef LazyVector + ExtAddressSpaceDeclsType; + + /// ExtAddressSpaceDecls - This is a list all the extended address space + /// types. This allows us to associate a type with one of the + /// ext_address_space type names. This is only necessary for issuing + /// pretty diagnostics. + ExtAddressSpaceDeclsType ExtAddressSpaceDecls; + /// FieldCollector - Collects CXXFieldDecls during parsing of C++ classes. std::unique_ptr FieldCollector; @@ -1307,6 +1317,8 @@ SourceRange Brackets, DeclarationName Entity); QualType BuildExtVectorType(QualType T, Expr *ArraySize, SourceLocation AttrLoc); + QualType BuildExtAddressSpaceAttr(QualType &T, Expr *AddrSpace, + SourceLocation AttrLoc); bool CheckFunctionReturnType(QualType T, SourceLocation Loc); Index: include/clang/Serialization/ASTBitCodes.h =================================================================== --- include/clang/Serialization/ASTBitCodes.h +++ include/clang/Serialization/ASTBitCodes.h @@ -844,95 +844,97 @@ /// AST. Note that DeclCode values share this code space. enum TypeCode { /// \brief An ExtQualType record. - TYPE_EXT_QUAL = 1, + TYPE_EXT_QUAL = 1, /// \brief A ComplexType record. - TYPE_COMPLEX = 3, + TYPE_COMPLEX = 3, /// \brief A PointerType record. - TYPE_POINTER = 4, + TYPE_POINTER = 4, /// \brief A BlockPointerType record. - TYPE_BLOCK_POINTER = 5, + TYPE_BLOCK_POINTER = 5, /// \brief An LValueReferenceType record. - TYPE_LVALUE_REFERENCE = 6, + TYPE_LVALUE_REFERENCE = 6, /// \brief An RValueReferenceType record. - TYPE_RVALUE_REFERENCE = 7, + TYPE_RVALUE_REFERENCE = 7, /// \brief A MemberPointerType record. - TYPE_MEMBER_POINTER = 8, + TYPE_MEMBER_POINTER = 8, /// \brief A ConstantArrayType record. - TYPE_CONSTANT_ARRAY = 9, + TYPE_CONSTANT_ARRAY = 9, /// \brief An IncompleteArrayType record. - TYPE_INCOMPLETE_ARRAY = 10, + TYPE_INCOMPLETE_ARRAY = 10, /// \brief A VariableArrayType record. - TYPE_VARIABLE_ARRAY = 11, + TYPE_VARIABLE_ARRAY = 11, /// \brief A VectorType record. - TYPE_VECTOR = 12, + TYPE_VECTOR = 12, /// \brief An ExtVectorType record. - TYPE_EXT_VECTOR = 13, + TYPE_EXT_VECTOR = 13, /// \brief A FunctionNoProtoType record. - TYPE_FUNCTION_NO_PROTO = 14, + TYPE_FUNCTION_NO_PROTO = 14, /// \brief A FunctionProtoType record. - TYPE_FUNCTION_PROTO = 15, + TYPE_FUNCTION_PROTO = 15, /// \brief A TypedefType record. - TYPE_TYPEDEF = 16, + TYPE_TYPEDEF = 16, /// \brief A TypeOfExprType record. - TYPE_TYPEOF_EXPR = 17, + TYPE_TYPEOF_EXPR = 17, /// \brief A TypeOfType record. - TYPE_TYPEOF = 18, + TYPE_TYPEOF = 18, /// \brief A RecordType record. - TYPE_RECORD = 19, + TYPE_RECORD = 19, /// \brief An EnumType record. - TYPE_ENUM = 20, + TYPE_ENUM = 20, /// \brief An ObjCInterfaceType record. - TYPE_OBJC_INTERFACE = 21, + TYPE_OBJC_INTERFACE = 21, /// \brief An ObjCObjectPointerType record. - TYPE_OBJC_OBJECT_POINTER = 22, + TYPE_OBJC_OBJECT_POINTER = 22, /// \brief a DecltypeType record. - TYPE_DECLTYPE = 23, + TYPE_DECLTYPE = 23, /// \brief An ElaboratedType record. - TYPE_ELABORATED = 24, + TYPE_ELABORATED = 24, /// \brief A SubstTemplateTypeParmType record. TYPE_SUBST_TEMPLATE_TYPE_PARM = 25, /// \brief An UnresolvedUsingType record. - TYPE_UNRESOLVED_USING = 26, + TYPE_UNRESOLVED_USING = 26, /// \brief An InjectedClassNameType record. - TYPE_INJECTED_CLASS_NAME = 27, + TYPE_INJECTED_CLASS_NAME = 27, /// \brief An ObjCObjectType record. - TYPE_OBJC_OBJECT = 28, + TYPE_OBJC_OBJECT = 28, /// \brief An TemplateTypeParmType record. - TYPE_TEMPLATE_TYPE_PARM = 29, + TYPE_TEMPLATE_TYPE_PARM = 29, /// \brief An TemplateSpecializationType record. - TYPE_TEMPLATE_SPECIALIZATION = 30, + TYPE_TEMPLATE_SPECIALIZATION = 30, /// \brief A DependentNameType record. - TYPE_DEPENDENT_NAME = 31, + TYPE_DEPENDENT_NAME = 31, /// \brief A DependentTemplateSpecializationType record. TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION = 32, /// \brief A DependentSizedArrayType record. - TYPE_DEPENDENT_SIZED_ARRAY = 33, + TYPE_DEPENDENT_SIZED_ARRAY = 33, /// \brief A ParenType record. - TYPE_PAREN = 34, + TYPE_PAREN = 34, /// \brief A PackExpansionType record. - TYPE_PACK_EXPANSION = 35, + TYPE_PACK_EXPANSION = 35, /// \brief An AttributedType record. - TYPE_ATTRIBUTED = 36, + TYPE_ATTRIBUTED = 36, /// \brief A SubstTemplateTypeParmPackType record. TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK = 37, /// \brief A AutoType record. - TYPE_AUTO = 38, + TYPE_AUTO = 38, /// \brief A UnaryTransformType record. - TYPE_UNARY_TRANSFORM = 39, + TYPE_UNARY_TRANSFORM = 39, /// \brief An AtomicType record. - TYPE_ATOMIC = 40, + TYPE_ATOMIC = 40, /// \brief A DecayedType record. - TYPE_DECAYED = 41, + TYPE_DECAYED = 41, /// \brief An AdjustedType record. - TYPE_ADJUSTED = 42, + TYPE_ADJUSTED = 42, /// \brief A PipeType record. - TYPE_PIPE = 43, + TYPE_PIPE = 43, /// \brief An ObjCTypeParamType record. - TYPE_OBJC_TYPE_PARAM = 44, + TYPE_OBJC_TYPE_PARAM = 44, /// \brief A DeducedTemplateSpecializationType record. TYPE_DEDUCED_TEMPLATE_SPECIALIZATION = 45, /// \brief A DependentSizedExtVectorType record. - TYPE_DEPENDENT_SIZED_EXT_VECTOR = 46 + TYPE_DEPENDENT_SIZED_EXT_VECTOR = 46, + /// \brief A DependentExtAddressSpaceType record. + TYPE_DEPENDENT_EXT_ADDRESS_SPACE = 47 }; /// \brief The type IDs for special types constructed by semantic Index: lib/AST/ASTContext.cpp =================================================================== --- lib/AST/ASTContext.cpp +++ lib/AST/ASTContext.cpp @@ -2301,6 +2301,30 @@ return getExtQualType(TypeNode, Quals); } +QualType ASTContext::removeAddrSpaceQualType(QualType T) const { + // If we are composing extended qualifiers together, merge together + // into one ExtQuals node. + QualifierCollector Quals; + const Type *TypeNode = Quals.strip(T); + + // if the qualifier doesn't have an address space just return it + if (!Quals.hasAddressSpace()) + return T; + + // The idea is just to remove the address space, if removeAddrSpaceQualType + // removes any other qualifiers then the implementation is incorrect and + // requires fixing. + Quals.removeAddressSpace(); + + // removal of the address space can mean there are no longer any + // non-fast qualifiers, so creating an ExtQualType isn't possible (asserts) + // or required. + if (Quals.hasNonFastQualifiers()) + return getExtQualType(TypeNode, Quals); + + return QualType(TypeNode, Quals.getFastQualifiers()); +} + QualType ASTContext::getObjCGCQualType(QualType T, Qualifiers::GC GCAttr) const { QualType CanT = getCanonicalType(T); @@ -2751,6 +2775,7 @@ case Type::Vector: case Type::ExtVector: case Type::DependentSizedExtVector: + case Type::DependentExtAddressSpace: case Type::ObjCObject: case Type::ObjCInterface: case Type::ObjCObjectPointer: @@ -3050,6 +3075,7 @@ VectorType *NewIP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos); assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } + ExtVectorType *New = new (*this, TypeAlignment) ExtVectorType(vecType, NumElts, Canonical); VectorTypes.InsertNode(New, InsertPos); @@ -3099,6 +3125,45 @@ return QualType(New, 0); } +QualType ASTContext::getDependentExtAddressSpaceType( + QualType PointerType, Expr *AddrSpaceExpr, SourceLocation AttrLoc) const { + llvm::FoldingSetNodeID ID; + DependentExtAddressSpaceType::Profile( + ID, *this, getCanonicalType(PointerType), AddrSpaceExpr); + + void *InsertPos = nullptr; + DependentExtAddressSpaceType *Canon = + DependentExtAddressSpaceTypes.FindNodeOrInsertPos(ID, InsertPos); + DependentExtAddressSpaceType *New; + if (Canon) { + // We already have a canonical version of this type; use it as + // the canonical type for a newly-built type. + New = new (*this, TypeAlignment) DependentExtAddressSpaceType( + *this, PointerType, QualType(Canon, 0), AddrSpaceExpr, AttrLoc); + } else { + QualType CanonASTy = getCanonicalType(PointerType); + if (CanonASTy == PointerType) { + New = new (*this, TypeAlignment) DependentExtAddressSpaceType( + *this, PointerType, QualType(), AddrSpaceExpr, AttrLoc); + + DependentExtAddressSpaceType *CanonCheck = + DependentExtAddressSpaceTypes.FindNodeOrInsertPos(ID, InsertPos); + assert(!CanonCheck && + "Dependent-sized ext_address_space canonical type broken"); + (void)CanonCheck; + DependentExtAddressSpaceTypes.InsertNode(New, InsertPos); + } else { + QualType Canon = getDependentExtAddressSpaceType(CanonASTy, AddrSpaceExpr, + SourceLocation()); + New = new (*this, TypeAlignment) DependentExtAddressSpaceType( + *this, PointerType, Canon, AddrSpaceExpr, AttrLoc); + } + } + + Types.push_back(New); + return QualType(New, 0); +} + /// \brief Determine whether \p T is canonical as the result type of a function. static bool isCanonicalResultType(QualType T) { return T.isCanonical() && Index: lib/AST/ASTStructuralEquivalence.cpp =================================================================== --- lib/AST/ASTStructuralEquivalence.cpp +++ lib/AST/ASTStructuralEquivalence.cpp @@ -365,6 +365,21 @@ break; } + case Type::DependentExtAddressSpace: { + const DependentExtAddressSpaceType *DepAddressSpace1 = + cast(T1); + const DependentExtAddressSpaceType *DepAddressSpace2 = + cast(T2); + if (!IsStructurallyEquivalent(Context, DepAddressSpace1->getAddrSpaceExpr(), + DepAddressSpace2->getAddrSpaceExpr())) + return false; + if (!IsStructurallyEquivalent(Context, DepAddressSpace1->getPointerType(), + DepAddressSpace2->getPointerType())) + return false; + + break; + } + case Type::DependentSizedExtVector: { const DependentSizedExtVectorType *Vec1 = cast(T1); Index: lib/AST/ItaniumMangle.cpp =================================================================== --- lib/AST/ItaniumMangle.cpp +++ lib/AST/ItaniumMangle.cpp @@ -1868,6 +1868,7 @@ case Type::IncompleteArray: case Type::VariableArray: case Type::DependentSizedArray: + case Type::DependentExtAddressSpace: case Type::DependentSizedExtVector: case Type::Vector: case Type::ExtVector: @@ -2971,6 +2972,13 @@ mangleType(T->getElementType()); } +void CXXNameMangler::mangleType(const DependentExtAddressSpaceType *T) { + Out << "DEas"; + mangleExpression(T->getAddrSpaceExpr()); + Out << '_'; + mangleType(T->getPointerType()); +} + void CXXNameMangler::mangleType(const PackExpansionType *T) { // ::= Dp # pack expansion (C++0x) Out << "Dp"; Index: lib/AST/MicrosoftMangle.cpp =================================================================== --- lib/AST/MicrosoftMangle.cpp +++ lib/AST/MicrosoftMangle.cpp @@ -2370,6 +2370,15 @@ << Range; } +void MicrosoftCXXNameMangler::mangleType(const DependentExtAddressSpaceType *T, + Qualifiers, SourceRange Range) { + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID( + DiagnosticsEngine::Error, + "cannot mangle this dependent extended address space type yet"); + Diags.Report(Range.getBegin(), DiagID) << Range; +} + void MicrosoftCXXNameMangler::mangleType(const ObjCInterfaceType *T, Qualifiers, SourceRange) { // ObjC interfaces have structs underlying them. Index: lib/AST/Type.cpp =================================================================== --- lib/AST/Type.cpp +++ lib/AST/Type.cpp @@ -168,6 +168,26 @@ SizeExpr->Profile(ID, Context, true); } +DependentExtAddressSpaceType::DependentExtAddressSpaceType( + const ASTContext &Context, QualType PointerType, QualType can, + Expr *AddrSpaceExpr, SourceLocation loc) + : Type(DependentExtAddressSpace, can, /*Dependent=*/true, + /*InstantiationDependent=*/true, + PointerType->isVariablyModifiedType(), + (PointerType->containsUnexpandedParameterPack() || + (AddrSpaceExpr && + AddrSpaceExpr->containsUnexpandedParameterPack()))), + Context(Context), AddrSpaceExpr(AddrSpaceExpr), PointerType(PointerType), + loc(loc) {} + +void DependentExtAddressSpaceType::Profile(llvm::FoldingSetNodeID &ID, + const ASTContext &Context, + QualType PointerType, + Expr *AddrSpaceExpr) { + ID.AddPointer(PointerType.getAsOpaquePtr()); + AddrSpaceExpr->Profile(ID, Context, true); +} + VectorType::VectorType(QualType vecType, unsigned nElements, QualType canonType, VectorKind vecKind) : VectorType(Vector, vecType, nElements, canonType, vecKind) {} @@ -3626,6 +3646,7 @@ case Type::DependentSizedExtVector: case Type::Vector: case Type::ExtVector: + case Type::DependentExtAddressSpace: case Type::FunctionProto: case Type::FunctionNoProto: case Type::Record: Index: lib/AST/TypePrinter.cpp =================================================================== --- lib/AST/TypePrinter.cpp +++ lib/AST/TypePrinter.cpp @@ -221,6 +221,7 @@ case Type::LValueReference: case Type::RValueReference: case Type::MemberPointer: + case Type::DependentExtAddressSpace: case Type::DependentSizedExtVector: case Type::Vector: case Type::ExtVector: @@ -526,6 +527,19 @@ printAfter(T->getElementType(), OS); } +void TypePrinter::printDependentExtAddressSpaceBefore( + const DependentExtAddressSpaceType *T, raw_ostream &OS) { + printBefore(T->getPointerType(), OS); +} +void TypePrinter::printDependentExtAddressSpaceAfter( + const DependentExtAddressSpaceType *T, raw_ostream &OS) { + OS << " __attribute__((ext_address_space("; + if (T->getAddrSpaceExpr()) + T->getAddrSpaceExpr()->printPretty(OS, nullptr, Policy); + OS << ")))"; + printAfter(T->getPointerType(), OS); +} + void TypePrinter::printDependentSizedExtVectorBefore( const DependentSizedExtVectorType *T, raw_ostream &OS) { Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -14155,7 +14156,11 @@ } // TR 18037 does not allow fields to be declared with address spaces. - if (T.getQualifiers().hasAddressSpace()) { + if (T.getQualifiers().hasAddressSpace() || + T->isDependentExtAddressSpaceType() || + T.getCanonicalType()->isDependentExtAddressSpaceType() || + (T->isArrayType() && + T->getPointeeOrArrayElementType()->isDependentExtAddressSpaceType())) { Diag(Loc, diag::err_field_with_address_space); D.setInvalidType(); } Index: lib/Sema/SemaDeclAttr.cpp =================================================================== --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -1298,6 +1298,12 @@ S.ExtVectorDecls.push_back(cast(D)); } +static void handleExtAddressSpaceAttr(Sema &S, Scope *scope, Decl *D, + const AttributeList &Attr) { + // Remember this typedef decl, we will need it later for diagnostics. + S.ExtAddressSpaceDecls.push_back(cast(D)); +} + static void handlePackedAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (TagDecl *TD = dyn_cast(D)) TD->addAttr(::new (S.Context) PackedAttr(Attr.getRange(), S.Context, @@ -6031,6 +6037,9 @@ case AttributeList::AT_ExternalSourceSymbol: handleExternalSourceSymbolAttr(S, D, Attr); break; + case AttributeList::AT_ExtAddressSpace: + handleExtAddressSpaceAttr(S, scope, D, Attr); + break; case AttributeList::AT_MinSize: handleMinSizeAttr(S, D, Attr); break; Index: lib/Sema/SemaTemplate.cpp =================================================================== --- lib/Sema/SemaTemplate.cpp +++ lib/Sema/SemaTemplate.cpp @@ -4986,6 +4986,11 @@ return Visit(T->getElementType()); } +bool UnnamedLocalNoLinkageFinder::VisitDependentExtAddressSpaceType( + const DependentExtAddressSpaceType *T) { + return Visit(T->getPointerType()); +} + bool UnnamedLocalNoLinkageFinder::VisitVectorType(const VectorType* T) { return Visit(T->getElementType()); } Index: lib/Sema/SemaTemplateDeduction.cpp =================================================================== --- lib/Sema/SemaTemplateDeduction.cpp +++ lib/Sema/SemaTemplateDeduction.cpp @@ -1799,6 +1799,60 @@ return Sema::TDK_NonDeducedMismatch; } + // (clang extension) + // + // T __attribute__(((ext_address_space(N)))) + case Type::DependentExtAddressSpace: { + const DependentExtAddressSpaceType *AddressSpaceParam = + cast(Param); + + if (const DependentExtAddressSpaceType *AddressSpaceArg = + dyn_cast(Arg)) { + // Perform deduction on the pointer type. + if (Sema::TemplateDeductionResult Result = + DeduceTemplateArgumentsByTypeMatch( + S, TemplateParams, AddressSpaceParam->getPointerType(), + AddressSpaceArg->getPointerType(), Info, Deduced, TDF)) + return Result; + + // Perform deduction on the address space, if we can. + NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr( + Info, AddressSpaceParam->getAddrSpaceExpr()); + if (!NTTP) + return Sema::TDK_Success; + + return DeduceNonTypeTemplateArgument( + S, TemplateParams, NTTP, AddressSpaceArg->getAddrSpaceExpr(), Info, + Deduced); + } + + if (Arg.getAddressSpace() > (0 + LangAS::FirstTargetAddressSpace)) { + llvm::APSInt ArgAddressSpace(S.Context.getTypeSize(S.Context.IntTy), + false); + ArgAddressSpace = + (Arg.getAddressSpace() - LangAS::FirstTargetAddressSpace); + + // Perform deduction on the pointer types. + if (Sema::TemplateDeductionResult Result = + DeduceTemplateArgumentsByTypeMatch( + S, TemplateParams, AddressSpaceParam->getPointerType(), + S.Context.removeAddrSpaceQualType(Arg), Info, Deduced, TDF)) + return Result; + + // Perform deduction on the address space, if we can. + NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr( + Info, AddressSpaceParam->getAddrSpaceExpr()); + if (!NTTP) + return Sema::TDK_Success; + + return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP, + ArgAddressSpace, S.Context.IntTy, + true, Info, Deduced); + } + + return Sema::TDK_NonDeducedMismatch; + } + case Type::TypeOfExpr: case Type::TypeOf: case Type::DependentName: @@ -5118,6 +5172,17 @@ break; } + case Type::DependentExtAddressSpace: { + const DependentExtAddressSpaceType *DependentAddressSpaceType = + cast(T); + MarkUsedTemplateParameters(Ctx, DependentAddressSpaceType->getPointerType(), + OnlyDeduced, Depth, Used); + MarkUsedTemplateParameters(Ctx, + DependentAddressSpaceType->getAddrSpaceExpr(), + OnlyDeduced, Depth, Used); + break; + } + case Type::FunctionProto: { const FunctionProtoType *Proto = cast(T); MarkUsedTemplateParameters(Ctx, Proto->getReturnType(), OnlyDeduced, Depth, Index: lib/Sema/SemaType.cpp =================================================================== --- lib/Sema/SemaType.cpp +++ lib/Sema/SemaType.cpp @@ -5385,6 +5384,16 @@ } for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) { + + if (isa(CurrTL.getType())) { + if (const DependentExtAddressSpaceType *EAST = + CurrTL.getType()->getAs()) { + TypeSourceInfo *InternalTInfo = + Context.CreateTypeSourceInfo(EAST->getPointerType()); + CurrTL = InternalTInfo->getTypeLoc().getUnqualifiedLoc(); + } + } + // An AtomicTypeLoc might be produced by an atomic qualifier in this // declarator chunk. if (AtomicTypeLoc ATL = CurrTL.getAs()) { @@ -5477,6 +5486,116 @@ // Type Attribute Processing //===----------------------------------------------------------------------===// +/// \brief Process the ext_address_space attribute when it occurs on +/// a type. +static void HandleExtAddressSpaceAttr(QualType &CurType, + const AttributeList &Attr, Sema &S) { + // check the attribute arguments. + if (Attr.getNumArgs() != 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) + << Attr.getName() << 1; + return; + } + + // ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "A function type shall not be + // qualified by an address-space qualifier." + if (CurType->isFunctionType()) { + S.Diag(Attr.getLoc(), diag::err_attribute_address_function_type); + Attr.setInvalid(); + return; + } + + Expr *ASArgExpr; + + // Special case where the argument is a template id. + if (Attr.isArgIdent(0)) { + CXXScopeSpec SS; + SourceLocation TemplateKWLoc; + UnqualifiedId id; + id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc()); + + ExprResult AddrSpace = S.ActOnIdExpression(S.getCurScope(), SS, + TemplateKWLoc, id, false, false); + if (AddrSpace.isInvalid()) + return; + + ASArgExpr = AddrSpace.get(); + } else { + ASArgExpr = Attr.getArgAsExpr(0); + } + + // Create the DependentExtAddressSpaceType or append an address space onto the + // type. + QualType T = S.BuildExtAddressSpaceAttr(CurType, ASArgExpr, Attr.getLoc()); + if (!T.isNull()) + CurType = T; + else + Attr.setInvalid(); +} + +/// BuildExtAddressSpaceAttr - Similar to how the +/// AT_AddressSpaces are handled within HandleAddressSpaceTypeAttribute +/// minus the fact that it won't complain about Type Dependency, +/// AT_ExtAddressSpace is based a fair bit on AT_ExtVectorType. +QualType Sema::BuildExtAddressSpaceAttr(QualType &T, Expr *AddrSpace, + SourceLocation AttrLoc) { + if (!AddrSpace->isTypeDependent() && !AddrSpace->isValueDependent()) { + + // If this type is already address space qualified, reject it. + // ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "No type shall be qualified + // by + // qualifiers for two or more different address spaces." + if (T.getAddressSpace()) { + Diag(AttrLoc, diag::err_attribute_address_multiple_qualifiers); + return QualType(); + } + + llvm::APSInt addrSpace(32); + if (!AddrSpace->isIntegerConstantExpr(addrSpace, Context)) { + Diag(AttrLoc, diag::err_attribute_argument_type) + << "'ext_address_space'" << AANT_ArgumentIntegerConstant + << AddrSpace->getSourceRange(); + return QualType(); + } + + // Bounds checking. + if (addrSpace.isSigned()) { + if (addrSpace.isNegative()) { + Diag(AttrLoc, diag::err_attribute_address_space_negative) + << AddrSpace->getSourceRange(); + return QualType(); + } + addrSpace.setIsSigned(false); + } + + llvm::APSInt max(addrSpace.getBitWidth()); + max = Qualifiers::MaxAddressSpace - LangAS::FirstTargetAddressSpace; + if (addrSpace > max) { + Diag(AttrLoc, diag::err_attribute_address_space_too_high) + << (unsigned)max.getZExtValue() << AddrSpace->getSourceRange(); + return QualType(); + } + + unsigned ASIdx = static_cast(addrSpace.getZExtValue()) + + LangAS::FirstTargetAddressSpace; + + return Context.getAddrSpaceQualType(T, ASIdx); + } + + // A check with similar intentions as checking if a type already has an + // address space + // except for on a dependent types, basically if the current type is already a + // DependentExtAddressSpaceType + // then its already lined up to have another address space on it and we can't + // have + // multiple address spaces on the one pointer indirection + if (isa(T)) { + Diag(AttrLoc, diag::err_attribute_address_multiple_qualifiers); + return QualType(); + } + + return Context.getDependentExtAddressSpaceType(T, AddrSpace, AttrLoc); +} /// HandleAddressSpaceTypeAttribute - Process an address_space attribute on the /// specified type. The attribute contains 1 argument, the id of the address /// space for the type. @@ -6853,6 +6972,11 @@ distributeObjCPointerTypeAttr(state, attr, type); attr.setUsedAsTypeAttr(); break; + case AttributeList::AT_ExtAddressSpace: + HandleExtAddressSpaceAttr(type, attr, state.getSema()); + attr.setUsedAsTypeAttr(); + hasOpenCLAddressSpace = true; + break; case AttributeList::AT_VectorSize: HandleVectorSizeAttr(type, attr, state.getSema()); attr.setUsedAsTypeAttr(); Index: lib/Sema/TreeTransform.h =================================================================== --- lib/Sema/TreeTransform.h +++ lib/Sema/TreeTransform.h @@ -835,6 +835,18 @@ Expr *SizeExpr, SourceLocation AttributeLoc); + /// \brief Build a new DependentExtAddressSpaceType or return the pointer + /// type variable with the correct address space (retrieved from + /// AddrSpaceExpr) applied to it. The former will be returned in cases + /// where the address space remains dependent. + /// + /// By default, performs semantic analysis when building the type with address + /// space applied. Subclasses may override this routine to provide different + /// behavior. + QualType RebuildDependentExtAddressSpaceType(QualType PointerType, + Expr *AddrSpaceExpr, + SourceLocation AttributeLoc); + /// \brief Build a new function type. /// /// By default, performs semantic analysis when building the function type. @@ -4754,7 +4766,49 @@ return Result; } -template +template +QualType TreeTransform::TransformDependentExtAddressSpaceType( + TypeLocBuilder &TLB, DependentExtAddressSpaceTypeLoc TL) { + const DependentExtAddressSpaceType *T = TL.getTypePtr(); + + QualType pointerType = getDerived().TransformType(T->getPointerType()); + + if (pointerType.isNull()) + return QualType(); + + // Address spaces are constant expressions. + EnterExpressionEvaluationContext Unevaluated( + SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated); + + ExprResult AddrSpace = getDerived().TransformExpr(T->getAddrSpaceExpr()); + AddrSpace = SemaRef.ActOnConstantExpression(AddrSpace); + if (AddrSpace.isInvalid()) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || pointerType != T->getPointerType() || + AddrSpace.get() != T->getAddrSpaceExpr()) { + Result = getDerived().RebuildDependentExtAddressSpaceType( + pointerType, AddrSpace.get(), T->getAttributeLoc()); + if (Result.isNull()) + return QualType(); + } + + // Result might be dependent or not. + if (isa(Result)) { + DependentExtAddressSpaceTypeLoc NewTL = + TLB.push(Result); + NewTL.setNameLoc(TL.getNameLoc()); + } else { + TypeSourceInfo *DI = getSema().Context.getTrivialTypeSourceInfo( + Result, getDerived().getBaseLocation()); + TransformType(TLB, DI->getTypeLoc()); + } + + return Result; +} + +template QualType TreeTransform::TransformVectorType(TypeLocBuilder &TLB, VectorTypeLoc TL) { const VectorType *T = TL.getTypePtr(); @@ -12178,10 +12232,18 @@ IndexTypeQuals, BracketsRange); } -template -QualType TreeTransform::RebuildVectorType(QualType ElementType, - unsigned NumElements, - VectorType::VectorKind VecKind) { +template +QualType TreeTransform::RebuildDependentExtAddressSpaceType( + QualType PointerType, Expr *AddrSpaceExpr, SourceLocation AttributeLoc) { + return SemaRef.BuildExtAddressSpaceAttr(PointerType, AddrSpaceExpr, + AttributeLoc); +} + +template +QualType +TreeTransform::RebuildVectorType(QualType ElementType, + unsigned NumElements, + VectorType::VectorKind VecKind) { // FIXME: semantic checking! return SemaRef.Context.getVectorType(ElementType, NumElements, VecKind); } Index: lib/Serialization/ASTReader.cpp =================================================================== --- lib/Serialization/ASTReader.cpp +++ lib/Serialization/ASTReader.cpp @@ -6168,6 +6168,18 @@ return Context.getDependentSizedExtVectorType(ElementType, SizeExpr, AttrLoc); } + + case TYPE_DEPENDENT_EXT_ADDRESS_SPACE: { + unsigned Idx = 0; + + // DependentExtAddressSpaceType + QualType PointerType = readType(*Loc.F, Record, Idx); + Expr *AddrSpaceExpr = ReadExpr(*Loc.F); + SourceLocation AttrLoc = ReadSourceLocation(*Loc.F, Record, Idx); + + return Context.getDependentExtAddressSpaceType(PointerType, AddrSpaceExpr, + AttrLoc); + } } llvm_unreachable("Invalid TypeCode!"); } @@ -6301,6 +6313,11 @@ VisitArrayTypeLoc(TL); } +void TypeLocReader::VisitDependentExtAddressSpaceTypeLoc( + DependentExtAddressSpaceTypeLoc TL) { + TL.setNameLoc(ReadSourceLocation()); +} + void TypeLocReader::VisitDependentSizedExtVectorTypeLoc( DependentSizedExtVectorTypeLoc TL) { TL.setNameLoc(ReadSourceLocation()); Index: lib/Serialization/ASTWriter.cpp =================================================================== --- lib/Serialization/ASTWriter.cpp +++ lib/Serialization/ASTWriter.cpp @@ -433,8 +433,15 @@ Code = TYPE_DEPENDENT_SIZED_EXT_VECTOR; } -void -ASTTypeWriter::VisitTemplateTypeParmType(const TemplateTypeParmType *T) { +void ASTTypeWriter::VisitDependentExtAddressSpaceType( + const DependentExtAddressSpaceType *T) { + Record.AddTypeRef(T->getPointerType()); + Record.AddStmt(T->getAddrSpaceExpr()); + Record.AddSourceLocation(T->getAttributeLoc()); + Code = TYPE_DEPENDENT_EXT_ADDRESS_SPACE; +} + +void ASTTypeWriter::VisitTemplateTypeParmType(const TemplateTypeParmType *T) { Record.push_back(T->getDepth()); Record.push_back(T->getIndex()); Record.push_back(T->isParameterPack()); @@ -627,6 +634,11 @@ VisitArrayTypeLoc(TL); } +void TypeLocWriter::VisitDependentExtAddressSpaceTypeLoc( + DependentExtAddressSpaceTypeLoc TL) { + Record.AddSourceLocation(TL.getNameLoc()); +} + void TypeLocWriter::VisitDependentSizedExtVectorTypeLoc( DependentSizedExtVectorTypeLoc TL) { Record.AddSourceLocation(TL.getNameLoc()); Index: test/Sema/ext_address_space-dependent.cpp =================================================================== --- /dev/null +++ test/Sema/ext_address_space-dependent.cpp @@ -0,0 +1,102 @@ +// RUN: %clang_cc1 -x c++ -std=c++14 -fsyntax-only -verify %s + +template +void car() { + int __attribute__((ext_address_space(I))) __attribute__((ext_address_space(J))) * Y; // expected-error {{multiple address spaces specified for type}} + int *__attribute__((ext_address_space(I))) __attribute__((ext_address_space(J))) * Z; // expected-error {{multiple address spaces specified for type}} + + __attribute__((ext_address_space(I))) int local; // expected-error {{automatic variable qualified with an address space}} + __attribute__((ext_address_space(J))) int array[5]; // expected-error {{automatic variable qualified with an address space}} + __attribute__((ext_address_space(I))) int arrarr[5][5]; // expected-error {{automatic variable qualified with an address space}} + + __attribute__((ext_address_space(J))) * x; // expected-error {{C++ requires a type specifier for all declarations}} + + __attribute__((ext_address_space(I))) float *B; + + typedef __attribute__((ext_address_space(J))) int AS2Int; + struct HasASFields { + AS2Int typedef_as_field; // expected-error {{field may not be qualified with an address space}} + }; + + struct _st { + int x, y; + } s __attribute((ext_address_space(I))) = {1, 1}; +} + +template +struct HasASTemplateFields { + __attribute__((ext_address_space(I))) int as_field; // expected-error {{field may not be qualified with an address space}} +}; + +template +void foo(__attribute__((ext_address_space(I))) float *a, // expected-note {{candidate template ignored: substitution failure [with I = 1, J = 2]: parameter may not be qualified with an address space}} + __attribute__((ext_address_space(J))) float b) { + *a = 5.0f + b; +} + +template void foo<1, 2>(float *, float); // expected-error {{explicit instantiation of 'foo' does not refer to a function template, variable template, member function, member class, or static data member}} + +template +void neg() { + __attribute__((ext_address_space(I))) int *bounds; // expected-error {{address space is negative}} +} + +template +void toBig() { + __attribute__((ext_address_space(I))) int *bounds; // expected-error {{address space is larger than the maximum supported (8388599)}} +} + +template +void correct() { + __attribute__((ext_address_space(I))) int *bounds; +} + +template +char *cmp(__attribute__((ext_address_space(I))) char *x, __attribute__((ext_address_space(J))) char *y) { + return x < y ? x : y; // expected-error {{comparison of distinct pointer types ('__attribute__((address_space(1))) char *' and '__attribute__((address_space(2))) char *')}} +} + +typedef void ft(void); + +template +struct fooFunction { + __attribute__((ext_address_space(I))) void **const base = 0; + + void *get_0(void) { + return base[0]; // expected-error {{cannot initialize return object of type 'void *' with an lvalue of type '__attribute__((address_space(1))) void *}} + } + + __attribute__((ext_address_space(I))) ft qf; // expected-error {{function type may not be qualified with an address space}} + __attribute__((ext_address_space(I))) char *test3_val; + + void test3(void) { + extern void test3_helper(char *p); // expected-note {{passing argument to parameter 'p' here}} + test3_helper(test3_val); // expected-error {{cannot initialize a parameter of type 'char *' with an lvalue of type '__attribute__((address_space(1))) char *'}} + } +}; + +template +int GetAddressSpaceValue(T __attribute__((ext_address_space(N))) * p) { + return N; +} + +int main() { + int __attribute__((ext_address_space(1))) * p1; + int p = GetAddressSpaceValue(p1); + + car<1, 2, 3>(); // expected-note {{in instantiation of function template specialization 'car<1, 2, 3>' requested here}} + HasASTemplateFields<1> HASTF; + neg<-1>(); // expected-note {{in instantiation of function template specialization 'neg<-1>' requested here}} + correct<0x7FFFF7>(); + toBig<4294967500>(); // expected-note {{in instantiation of function template specialization 'toBig<4294967500>' requested here}} + + __attribute__((ext_address_space(1))) char *x; + __attribute__((ext_address_space(2))) char *y; + cmp<1, 2>(x, y); // expected-note {{in instantiation of function template specialization 'cmp<1, 2>' requested here}} + + fooFunction<1> ff; + ff.get_0(); // expected-note {{in instantiation of member function 'fooFunction<1>::get_0' requested here}} + ff.qf(); + ff.test3(); // expected-note {{in instantiation of member function 'fooFunction<1>::test3' requested here}} + return 0; +} Index: test/Sema/ext_address_space-nondependent.cpp =================================================================== --- /dev/null +++ test/Sema/ext_address_space-nondependent.cpp @@ -0,0 +1,67 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++14 %s + +// replication of address space tests, as ext_address_space should output identical or close to identical errors in these scenarios. +#define _AS1 __attribute__((ext_address_space(1))) +#define _AS2 __attribute__((ext_address_space(2))) +#define _AS3 __attribute__((ext_address_space(3))) + +void bar(_AS2 int a); // expected-error {{parameter may not be qualified with an address space}} + +void foo(_AS3 float *a, + _AS1 float b) // expected-error {{parameter may not be qualified with an address space}} +{ + _AS2 *x; // expected-error {{C++ requires a type specifier for all declarations}} + _AS1 float *_AS2 *B; + + int _AS1 _AS2 *Y; // expected-error {{multiple address spaces specified for type}} + int *_AS1 _AS2 *Z; // expected-error {{multiple address spaces specified for type}} + + _AS1 int local; // expected-error {{automatic variable qualified with an address space}} + _AS1 int array[5]; // expected-error {{automatic variable qualified with an address space}} + _AS1 int arrarr[5][5]; // expected-error {{automatic variable qualified with an address space}} + + __attribute__((ext_address_space(-1))) int *_boundsA; // expected-error {{address space is negative}} + __attribute__((ext_address_space(0x7FFFF7))) int *_boundsB; + __attribute__((ext_address_space(0x1000000))) int *_boundsC; // expected-error {{address space is larger than the maximum supported}} + __attribute__((ext_address_space(4294967500))) int *_boundsD; // expected-error {{address space is larger than the maximum supported}} + + *a = 5.0f + b; +} + +struct _st { + int x, y; +} s __attribute((ext_address_space(1))) = {1, 1}; + +__attribute__((ext_address_space(256))) void **const base = 0; +void *get_0(void) { + return base[0]; // expected-error {{cannot initialize return object of type 'void *' with an lvalue of type '__attribute__((address_space(256))) void *'}} +} + +__attribute__((ext_address_space(1))) char test3_array[10]; +void test3(void) { + extern void test3_helper(char *p); // expected-note {{passing argument to parameter 'p' here}} + test3_helper(test3_array); // expected-error {{cannot initialize a parameter of type 'char *' with an lvalue of type '__attribute__((address_space(1))) char [10]'}} +} + +typedef void ft(void); +_AS1 ft qf; // expected-error {{function type may not be qualified with an address space}} +typedef _AS1 ft qft; // expected-error {{function type may not be qualified with an address space}} + +typedef _AS2 int AS2Int; + +struct HasASFields { + _AS2 int as_field; // expected-error {{field may not be qualified with an address space}} + AS2Int typedef_as_field; // expected-error {{field may not be qualified with an address space}} +}; + +void access_as_field() { + struct HasASFields x; + (void)bar.as_field; +} + +typedef int PR4997 __attribute__((ext_address_space(Foobar))); // expected-error {{use of undeclared identifier 'Foobar'}} +__attribute__((ext_address_space("12"))) int *i; // expected-error {{'ext_address_space' attribute requires an integer constant}} + +char *cmp(_AS1 char *x, _AS2 char *y) { + return x < y ? x : y; // expected-error {{comparison of distinct pointer types ('__attribute__((address_space(1))) char *' and '__attribute__((address_space(2))) char *'}} +} Index: tools/libclang/CIndex.cpp =================================================================== --- tools/libclang/CIndex.cpp +++ tools/libclang/CIndex.cpp @@ -1742,6 +1742,7 @@ DEFAULT_TYPELOC_IMPL(IncompleteArray, ArrayType) DEFAULT_TYPELOC_IMPL(VariableArray, ArrayType) DEFAULT_TYPELOC_IMPL(DependentSizedArray, ArrayType) +DEFAULT_TYPELOC_IMPL(DependentExtAddressSpace, Type) DEFAULT_TYPELOC_IMPL(DependentSizedExtVector, Type) DEFAULT_TYPELOC_IMPL(Vector, Type) DEFAULT_TYPELOC_IMPL(ExtVector, VectorType)