[llvm-branch-commits] [clang] a999b9d - Add support for the MS qualifiers __ptr32, __ptr64, __sptr, __uptr.
Amy Huang via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Dec 18 09:02:51 PST 2019
Author: Amy Huang
Date: 2019-12-18T09:01:31-08:00
New Revision: a999b9dc69f88e590a61f78c10ac7db51a3a5d98
URL: https://github.com/llvm/llvm-project/commit/a999b9dc69f88e590a61f78c10ac7db51a3a5d98
DIFF: https://github.com/llvm/llvm-project/commit/a999b9dc69f88e590a61f78c10ac7db51a3a5d98.diff
LOG: Add support for the MS qualifiers __ptr32, __ptr64, __sptr, __uptr.
Summary:
This adds parsing of the qualifiers __ptr32, __ptr64, __sptr, and __uptr and
lowers them to the corresponding address space pointer for 32-bit and 64-bit pointers.
(32/64-bit pointers added in https://reviews.llvm.org/D69639)
A large part of this patch is making these pointers ignore the address space
when doing things like overloading and casting.
https://bugs.llvm.org/show_bug.cgi?id=42359
Reviewers: rnk, rsmith
Subscribers: jholewinski, jvesely, nhaehnle, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D71039
Added:
clang/test/CodeGen/ms-mixed-ptr-sizes.c
clang/test/CodeGenCXX/mangle-ptr-size-address-space.cpp
Modified:
clang/include/clang/AST/Type.h
clang/include/clang/Basic/AddressSpaces.h
clang/lib/AST/ASTContext.cpp
clang/lib/AST/ItaniumMangle.cpp
clang/lib/AST/MicrosoftMangle.cpp
clang/lib/Basic/Targets/AMDGPU.cpp
clang/lib/Basic/Targets/NVPTX.h
clang/lib/Basic/Targets/SPIR.h
clang/lib/Basic/Targets/TCE.h
clang/lib/Basic/Targets/X86.h
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaOverload.cpp
clang/lib/Sema/SemaType.cpp
clang/test/Sema/MicrosoftExtensions.c
clang/test/SemaTemplate/address_space-dependent.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 2968efa9b276..f7cd4945d022 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -477,7 +477,11 @@ class Qualifiers {
return A == B ||
// Otherwise in OpenCLC v2.0 s6.5.5: every address space except
// for __constant can be used as __generic.
- (A == LangAS::opencl_generic && B != LangAS::opencl_constant);
+ (A == LangAS::opencl_generic && B != LangAS::opencl_constant) ||
+ // Consider pointer size address spaces to be equivalent to default.
+ ((isPtrSizeAddressSpace(A) && B == LangAS::Default) ||
+ (isPtrSizeAddressSpace(B) && A == LangAS::Default) ||
+ (isPtrSizeAddressSpace(A) && isPtrSizeAddressSpace(B)));
}
/// Returns true if the address space in these qualifiers is equal to or
diff --git a/clang/include/clang/Basic/AddressSpaces.h b/clang/include/clang/Basic/AddressSpaces.h
index 2cc67474c121..faf7f303aa2d 100644
--- a/clang/include/clang/Basic/AddressSpaces.h
+++ b/clang/include/clang/Basic/AddressSpaces.h
@@ -42,6 +42,11 @@ enum class LangAS : unsigned {
cuda_constant,
cuda_shared,
+ // Pointer size and extension address spaces.
+ ptr32_sptr,
+ ptr32_uptr,
+ ptr64,
+
// This denotes the count of language-specific address spaces and also
// the offset added to the target-specific address spaces, which are usually
// specified by address space attributes __attribute__(address_space(n))).
@@ -68,6 +73,11 @@ inline LangAS getLangASFromTargetAS(unsigned TargetAS) {
(unsigned)LangAS::FirstTargetAddressSpace);
}
+inline bool isPtrSizeAddressSpace(LangAS AS) {
+ return (AS == LangAS::ptr32_sptr || AS == LangAS::ptr32_uptr ||
+ AS == LangAS::ptr64);
+}
+
} // namespace clang
#endif // LLVM_CLANG_BASIC_ADDRESSSPACES_H
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 1046663c7009..42b49be54df2 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -825,15 +825,18 @@ static const LangASMap *getAddressSpaceMap(const TargetInfo &T,
// The fake address space map must have a distinct entry for each
// language-specific address space.
static const unsigned FakeAddrSpaceMap[] = {
- 0, // Default
- 1, // opencl_global
- 3, // opencl_local
- 2, // opencl_constant
- 0, // opencl_private
- 4, // opencl_generic
- 5, // cuda_device
- 6, // cuda_constant
- 7 // cuda_shared
+ 0, // Default
+ 1, // opencl_global
+ 3, // opencl_local
+ 2, // opencl_constant
+ 0, // opencl_private
+ 4, // opencl_generic
+ 5, // cuda_device
+ 6, // cuda_constant
+ 7, // cuda_shared
+ 8, // ptr32_sptr
+ 9, // ptr32_uptr
+ 10 // ptr64
};
return &FakeAddrSpaceMap;
} else {
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 8c87c55c792a..0d567edac521 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -2301,6 +2301,16 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals, const DependentAddressSp
case LangAS::cuda_device: ASString = "CUdevice"; break;
case LangAS::cuda_constant: ASString = "CUconstant"; break;
case LangAS::cuda_shared: ASString = "CUshared"; break;
+ // <ptrsize-addrspace> ::= [ "ptr32_sptr" | "ptr32_uptr" | "ptr64" ]
+ case LangAS::ptr32_sptr:
+ ASString = "ptr32_sptr";
+ break;
+ case LangAS::ptr32_uptr:
+ ASString = "ptr32_uptr";
+ break;
+ case LangAS::ptr64:
+ ASString = "ptr64";
+ break;
}
}
if (!ASString.empty())
diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp
index 9f692d8107cb..71822a7264c3 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -279,8 +279,6 @@ class MicrosoftCXXNameMangler {
ASTContext &getASTContext() const { return Context.getASTContext(); }
- // FIXME: If we add support for __ptr32/64 qualifiers, then we should push
- // this check into mangleQualifiers().
const bool PointersAre64Bit;
public:
@@ -335,6 +333,13 @@ class MicrosoftCXXNameMangler {
return ND == Structor || getStructor(ND) == Structor;
}
+ bool is64BitPointer(Qualifiers Quals) const {
+ LangAS AddrSpace = Quals.getAddressSpace();
+ return AddrSpace == LangAS::ptr64 ||
+ (PointersAre64Bit && !(AddrSpace == LangAS::ptr32_sptr ||
+ AddrSpace == LangAS::ptr32_uptr));
+ }
+
void mangleUnqualifiedName(const NamedDecl *ND) {
mangleUnqualifiedName(ND, ND->getDeclName());
}
@@ -1703,8 +1708,10 @@ MicrosoftCXXNameMangler::mangleRefQualifier(RefQualifierKind RefQualifier) {
void MicrosoftCXXNameMangler::manglePointerExtQualifiers(Qualifiers Quals,
QualType PointeeType) {
- if (PointersAre64Bit &&
- (PointeeType.isNull() || !PointeeType->isFunctionType()))
+ // Check if this is a default 64-bit pointer or has __ptr64 qualifier.
+ bool is64Bit = PointeeType.isNull() ? PointersAre64Bit :
+ is64BitPointer(PointeeType.getQualifiers());
+ if (is64Bit && (PointeeType.isNull() || !PointeeType->isFunctionType()))
Out << 'E';
if (Quals.hasRestrict())
@@ -1864,6 +1871,15 @@ void MicrosoftCXXNameMangler::mangleAddressSpaceType(QualType T,
case LangAS::cuda_shared:
Extra.mangleSourceName("_ASCUshared");
break;
+ case LangAS::ptr32_sptr:
+ Extra.mangleSourceName("_ASPtr32_sptr");
+ break;
+ case LangAS::ptr32_uptr:
+ Extra.mangleSourceName("_ASPtr32_uptr");
+ break;
+ case LangAS::ptr64:
+ Extra.mangleSourceName("_ASPtr64");
+ break;
}
}
@@ -2597,10 +2613,13 @@ void MicrosoftCXXNameMangler::mangleType(const PointerType *T, Qualifiers Quals,
manglePointerCVQualifiers(Quals);
manglePointerExtQualifiers(Quals, PointeeType);
- if (PointeeType.getQualifiers().hasAddressSpace())
- mangleAddressSpaceType(PointeeType, PointeeType.getQualifiers(), Range);
- else
+ // For pointer size address spaces, go down the same type mangling path as
+ // non address space types.
+ LangAS AddrSpace = PointeeType.getQualifiers().getAddressSpace();
+ if (isPtrSizeAddressSpace(AddrSpace) || AddrSpace == LangAS::Default)
mangleType(PointeeType, Range);
+ else
+ mangleAddressSpaceType(PointeeType, PointeeType.getQualifiers(), Range);
}
void MicrosoftCXXNameMangler::mangleType(const ObjCObjectPointerType *T,
diff --git a/clang/lib/Basic/Targets/AMDGPU.cpp b/clang/lib/Basic/Targets/AMDGPU.cpp
index 481630c0fa45..135ad3f97ce1 100644
--- a/clang/lib/Basic/Targets/AMDGPU.cpp
+++ b/clang/lib/Basic/Targets/AMDGPU.cpp
@@ -47,7 +47,10 @@ const LangASMap AMDGPUTargetInfo::AMDGPUDefIsGenMap = {
Generic, // opencl_generic
Global, // cuda_device
Constant, // cuda_constant
- Local // cuda_shared
+ Local, // cuda_shared
+ Generic, // ptr32_sptr
+ Generic, // ptr32_uptr
+ Generic // ptr64
};
const LangASMap AMDGPUTargetInfo::AMDGPUDefIsPrivMap = {
@@ -59,7 +62,11 @@ const LangASMap AMDGPUTargetInfo::AMDGPUDefIsPrivMap = {
Generic, // opencl_generic
Global, // cuda_device
Constant, // cuda_constant
- Local // cuda_shared
+ Local, // cuda_shared
+ Generic, // ptr32_sptr
+ Generic, // ptr32_uptr
+ Generic // ptr64
+
};
} // namespace targets
} // namespace clang
diff --git a/clang/lib/Basic/Targets/NVPTX.h b/clang/lib/Basic/Targets/NVPTX.h
index 2cdd37ca1b07..63780789c474 100644
--- a/clang/lib/Basic/Targets/NVPTX.h
+++ b/clang/lib/Basic/Targets/NVPTX.h
@@ -33,6 +33,9 @@ static const unsigned NVPTXAddrSpaceMap[] = {
1, // cuda_device
4, // cuda_constant
3, // cuda_shared
+ 0, // ptr32_sptr
+ 0, // ptr32_uptr
+ 0 // ptr64
};
/// The DWARF address class. Taken from
diff --git a/clang/lib/Basic/Targets/SPIR.h b/clang/lib/Basic/Targets/SPIR.h
index 802ccf8b671e..279d1866a428 100644
--- a/clang/lib/Basic/Targets/SPIR.h
+++ b/clang/lib/Basic/Targets/SPIR.h
@@ -30,7 +30,10 @@ static const unsigned SPIRAddrSpaceMap[] = {
4, // opencl_generic
0, // cuda_device
0, // cuda_constant
- 0 // cuda_shared
+ 0, // cuda_shared
+ 0, // ptr32_sptr
+ 0, // ptr32_uptr
+ 0 // ptr64
};
class LLVM_LIBRARY_VISIBILITY SPIRTargetInfo : public TargetInfo {
diff --git a/clang/lib/Basic/Targets/TCE.h b/clang/lib/Basic/Targets/TCE.h
index 967ef5c59ee5..9cbf2a3688a2 100644
--- a/clang/lib/Basic/Targets/TCE.h
+++ b/clang/lib/Basic/Targets/TCE.h
@@ -39,7 +39,10 @@ static const unsigned TCEOpenCLAddrSpaceMap[] = {
0, // opencl_generic
0, // cuda_device
0, // cuda_constant
- 0 // cuda_shared
+ 0, // cuda_shared
+ 0, // ptr32_sptr
+ 0, // ptr32_uptr
+ 0, // ptr64
};
class LLVM_LIBRARY_VISIBILITY TCETargetInfo : public TargetInfo {
diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h
index cad869f71230..604198b00472 100644
--- a/clang/lib/Basic/Targets/X86.h
+++ b/clang/lib/Basic/Targets/X86.h
@@ -22,6 +22,21 @@
namespace clang {
namespace targets {
+static const unsigned X86AddrSpaceMap[] = {
+ 0, // Default
+ 0, // opencl_global
+ 0, // opencl_local
+ 0, // opencl_constant
+ 0, // opencl_private
+ 0, // opencl_generic
+ 0, // cuda_device
+ 0, // cuda_constant
+ 0, // cuda_shared
+ 270, // ptr32_sptr
+ 271, // ptr32_uptr
+ 272 // ptr64
+};
+
// X86 target abstract base class; x86-32 and x86-64 are very close, so
// most of the implementation can be shared.
class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo {
@@ -45,6 +60,7 @@ class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo {
AMD3DNowAthlon
} MMX3DNowLevel = NoMMX3DNow;
enum XOPEnum { NoXOP, SSE4A, FMA4, XOP } XOPLevel = NoXOP;
+ enum AddrSpace { ptr32_sptr = 270, ptr32_uptr = 271, ptr64 = 272 };
bool HasAES = false;
bool HasVAES = false;
@@ -130,6 +146,7 @@ class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo {
X86TargetInfo(const llvm::Triple &Triple, const TargetOptions &)
: TargetInfo(Triple) {
LongDoubleFormat = &llvm::APFloat::x87DoubleExtended();
+ AddrSpaceMap = &X86AddrSpaceMap;
}
const char *getLongDoubleMangling() const override {
@@ -328,6 +345,18 @@ class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo {
void setSupportedOpenCLOpts() override {
getSupportedOpenCLOpts().supportAll();
}
+
+ uint64_t getPointerWidthV(unsigned AddrSpace) const override {
+ if (AddrSpace == ptr32_sptr || AddrSpace == ptr32_uptr)
+ return 32;
+ if (AddrSpace == ptr64)
+ return 64;
+ return PointerWidth;
+ }
+
+ uint64_t getPointerAlignV(unsigned AddrSpace) const override {
+ return getPointerWidthV(AddrSpace);
+ }
};
// X86-32 generic target
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index ebc919b52a49..b5c14a582c48 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -3153,6 +3153,64 @@ static void adjustDeclContextForDeclaratorDecl(DeclaratorDecl *NewD,
FixSemaDC(VD->getDescribedVarTemplate());
}
+static QualType RemovePtrSizeAddrSpace(ASTContext &Ctx, QualType T) {
+ if (const PointerType *Ptr = T->getAs<PointerType>()) {
+ QualType Pointee = Ptr->getPointeeType();
+ if (isPtrSizeAddressSpace(Pointee.getAddressSpace())) {
+ return Ctx.getPointerType(Ctx.removeAddrSpaceQualType(Pointee));
+ }
+ }
+ return T;
+}
+
+static bool HasSameFunctionTypeIgnoringPointerSizes(ASTContext &Ctx,
+ QualType Old,
+ QualType New) {
+ if (Ctx.hasSameType(Old, New))
+ return true;
+
+ if (const FunctionProtoType *OldProto = Old->getAs<FunctionProtoType>()) {
+ if (const FunctionProtoType *NewProto = New->getAs<FunctionProtoType>()) {
+ SmallVector<QualType, 16> OArgs(OldProto->param_types());
+ SmallVector<QualType, 16> NArgs(NewProto->param_types());
+ if (OArgs.size() != NArgs.size())
+ return false;
+
+ QualType OldRTy = RemovePtrSizeAddrSpace(Ctx, OldProto->getReturnType());
+ QualType NewRTy = RemovePtrSizeAddrSpace(Ctx, NewProto->getReturnType());
+
+ for (unsigned i = 0, n = OArgs.size(); i != n; ++i) {
+ QualType OArg = OArgs[i];
+ QualType NArg = NArgs[i];
+ if (Ctx.hasSameType(OArg, NArg))
+ continue;
+ OArgs[i] = RemovePtrSizeAddrSpace(Ctx, OArg);
+ NArgs[i] = RemovePtrSizeAddrSpace(Ctx, NArg);
+ }
+
+ QualType OldType =
+ Ctx.getFunctionType(OldRTy, OArgs, OldProto->getExtProtoInfo());
+ QualType NewType =
+ Ctx.getFunctionType(NewRTy, NArgs, NewProto->getExtProtoInfo());
+
+ return Ctx.hasSameType(OldType, NewType);
+ }
+ }
+
+ if (const FunctionNoProtoType *OldF = Old->getAs<FunctionNoProtoType>()) {
+ if (const FunctionNoProtoType *NewF = New->getAs<FunctionNoProtoType>()) {
+ QualType OldRetTy = RemovePtrSizeAddrSpace(Ctx, OldF->getReturnType());
+ QualType NewRetTy = RemovePtrSizeAddrSpace(Ctx, NewF->getReturnType());
+
+ return Ctx.hasSameType(
+ Ctx.getFunctionNoProtoType(OldRetTy, OldF->getExtInfo()),
+ Ctx.getFunctionNoProtoType(NewRetTy, NewF->getExtInfo()));
+ }
+ }
+
+ return false;
+}
+
/// MergeFunctionDecl - We just parsed a function 'New' from
/// declarator D which has the same name and scope as a previous
/// declaration 'Old'. Figure out how to resolve this situation,
@@ -3656,6 +3714,11 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
return MergeCompatibleFunctionDecls(New, Old, S, MergeTypeWithOld);
}
+ // Check if the function types are compatible when pointer size address
+ // spaces are ignored.
+ if (HasSameFunctionTypeIgnoringPointerSizes(Context, OldQType, NewQType))
+ return false;
+
// GNU C permits a K&R definition to follow a prototype declaration
// if the declared types of the parameters in the K&R definition
// match the types in the prototype declaration, even when the
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 32541d6b9443..0452da4535a2 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -2922,6 +2922,16 @@ void Sema::HandleFunctionTypeMismatch(PartialDiagnostic &PDiag,
PDiag << ft_default;
}
+static QualType RemovePtrSizeAddrSpace(ASTContext &Ctx, QualType T) {
+ if (const PointerType *Ptr = T->getAs<PointerType>()) {
+ QualType Pointee = Ptr->getPointeeType();
+ if (isPtrSizeAddressSpace(Pointee.getAddressSpace())) {
+ return Ctx.getPointerType(Ctx.removeAddrSpaceQualType(Pointee));
+ }
+ }
+ return T;
+}
+
/// FunctionParamTypesAreEqual - This routine checks two function proto types
/// for equality of their argument types. Caller has already checked that
/// they have same number of arguments. If the parameters are
diff erent,
@@ -2933,8 +2943,12 @@ bool Sema::FunctionParamTypesAreEqual(const FunctionProtoType *OldType,
N = NewType->param_type_begin(),
E = OldType->param_type_end();
O && (O != E); ++O, ++N) {
- if (!Context.hasSameType(O->getUnqualifiedType(),
- N->getUnqualifiedType())) {
+ // Ignore address spaces in pointee type. This is to disallow overloading
+ // on __ptr32/__ptr64 address spaces.
+ QualType Old = RemovePtrSizeAddrSpace(Context, O->getUnqualifiedType());
+ QualType New = RemovePtrSizeAddrSpace(Context, N->getUnqualifiedType());
+
+ if (!Context.hasSameType(Old, New)) {
if (ArgPos)
*ArgPos = O - OldType->param_type_begin();
return false;
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 95762c0c6f7e..4dc10ffdd64e 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -6497,35 +6497,36 @@ static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
break;
}
+ llvm::SmallSet<attr::Kind, 2> Attrs;
attr::Kind NewAttrKind = A->getKind();
QualType Desugared = Type;
const AttributedType *AT = dyn_cast<AttributedType>(Type);
while (AT) {
- attr::Kind CurAttrKind = AT->getAttrKind();
-
- // You cannot specify duplicate type attributes, so if the attribute has
- // already been applied, flag it.
- if (NewAttrKind == CurAttrKind) {
- S.Diag(PAttr.getLoc(), diag::warn_duplicate_attribute_exact) << PAttr;
- return true;
- }
+ Attrs.insert(AT->getAttrKind());
+ Desugared = AT->getModifiedType();
+ AT = dyn_cast<AttributedType>(Desugared);
+ }
- // You cannot have both __sptr and __uptr on the same type, nor can you
- // have __ptr32 and __ptr64.
- if ((CurAttrKind == attr::Ptr32 && NewAttrKind == attr::Ptr64) ||
- (CurAttrKind == attr::Ptr64 && NewAttrKind == attr::Ptr32)) {
- S.Diag(PAttr.getLoc(), diag::err_attributes_are_not_compatible)
- << "'__ptr32'" << "'__ptr64'";
- return true;
- } else if ((CurAttrKind == attr::SPtr && NewAttrKind == attr::UPtr) ||
- (CurAttrKind == attr::UPtr && NewAttrKind == attr::SPtr)) {
- S.Diag(PAttr.getLoc(), diag::err_attributes_are_not_compatible)
- << "'__sptr'" << "'__uptr'";
- return true;
- }
+ // You cannot specify duplicate type attributes, so if the attribute has
+ // already been applied, flag it.
+ if (Attrs.count(NewAttrKind)) {
+ S.Diag(PAttr.getLoc(), diag::warn_duplicate_attribute_exact) << PAttr;
+ return true;
+ }
+ Attrs.insert(NewAttrKind);
- Desugared = AT->getEquivalentType();
- AT = dyn_cast<AttributedType>(Desugared);
+ // You cannot have both __sptr and __uptr on the same type, nor can you
+ // have __ptr32 and __ptr64.
+ if (Attrs.count(attr::Ptr32) && Attrs.count(attr::Ptr64)) {
+ S.Diag(PAttr.getLoc(), diag::err_attributes_are_not_compatible)
+ << "'__ptr32'"
+ << "'__ptr64'";
+ return true;
+ } else if (Attrs.count(attr::SPtr) && Attrs.count(attr::UPtr)) {
+ S.Diag(PAttr.getLoc(), diag::err_attributes_are_not_compatible)
+ << "'__sptr'"
+ << "'__uptr'";
+ return true;
}
// Pointer type qualifiers can only operate on pointer types, but not
@@ -6543,7 +6544,26 @@ static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
return true;
}
- Type = State.getAttributedType(A, Type, Type);
+ // Add address space to type based on its attributes.
+ LangAS ASIdx = LangAS::Default;
+ uint64_t PtrWidth = S.Context.getTargetInfo().getPointerWidth(0);
+ if (PtrWidth == 32) {
+ if (Attrs.count(attr::Ptr64))
+ ASIdx = LangAS::ptr64;
+ else if (Attrs.count(attr::UPtr))
+ ASIdx = LangAS::ptr32_uptr;
+ } else if (PtrWidth == 64 && Attrs.count(attr::Ptr32)) {
+ if (Attrs.count(attr::UPtr))
+ ASIdx = LangAS::ptr32_uptr;
+ else
+ ASIdx = LangAS::ptr32_sptr;
+ }
+
+ QualType Pointee = Type->getPointeeType();
+ if (ASIdx != LangAS::Default)
+ Pointee = S.Context.getAddrSpaceQualType(
+ S.Context.removeAddrSpaceQualType(Pointee), ASIdx);
+ Type = State.getAttributedType(A, Type, S.Context.getPointerType(Pointee));
return false;
}
diff --git a/clang/test/CodeGen/ms-mixed-ptr-sizes.c b/clang/test/CodeGen/ms-mixed-ptr-sizes.c
new file mode 100644
index 000000000000..111d29b4bb03
--- /dev/null
+++ b/clang/test/CodeGen/ms-mixed-ptr-sizes.c
@@ -0,0 +1,51 @@
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -fms-extensions -emit-llvm -O2 \
+// RUN: < %s | FileCheck %s --check-prefixes=X64,CHECK
+// RUN: %clang_cc1 -triple i386-pc-win32 -fms-extensions -emit-llvm -O2 \
+// RUN: < %s | FileCheck %s --check-prefixes=X86,CHECK
+
+struct Foo {
+ int * __ptr32 p32;
+ int * __ptr64 p64;
+};
+void use_foo(struct Foo *f);
+void test_sign_ext(struct Foo *f, int * __ptr32 __sptr i) {
+// X64-LABEL: define dso_local void @test_sign_ext({{.*}}i32 addrspace(270)* %i)
+// X86-LABEL: define dso_local void @test_sign_ext(%struct.Foo* %f, i32* %i)
+// X64: %{{.+}} = addrspacecast i32 addrspace(270)* %i to i32*
+// X86: %{{.+}} = addrspacecast i32* %i to i32 addrspace(272)*
+ f->p64 = i;
+ use_foo(f);
+}
+void test_zero_ext(struct Foo *f, int * __ptr32 __uptr i) {
+// X64-LABEL: define dso_local void @test_zero_ext({{.*}}i32 addrspace(271)* %i)
+// X86-LABEL: define dso_local void @test_zero_ext({{.*}}i32 addrspace(271)* %i)
+// X64: %{{.+}} = addrspacecast i32 addrspace(271)* %i to i32*
+// X86: %{{.+}} = addrspacecast i32 addrspace(271)* %i to i32 addrspace(272)*
+ f->p64 = i;
+ use_foo(f);
+}
+void test_trunc(struct Foo *f, int * __ptr64 i) {
+// X64-LABEL: define dso_local void @test_trunc(%struct.Foo* %f, i32* %i)
+// X86-LABEL: define dso_local void @test_trunc({{.*}}i32 addrspace(272)* %i)
+// X64: %{{.+}} = addrspacecast i32* %i to i32 addrspace(270)*
+// X86: %{{.+}} = addrspacecast i32 addrspace(272)* %i to i32*
+ f->p32 = i;
+ use_foo(f);
+}
+void test_noop(struct Foo *f, int * __ptr32 i) {
+// X64-LABEL: define dso_local void @test_noop({{.*}}i32 addrspace(270)* %i)
+// X86-LABEL: define dso_local void @test_noop({{.*}}i32* %i)
+// X64-NOT: addrspacecast
+// X86-NOT: addrspacecast
+ f->p32 = i;
+ use_foo(f);
+}
+
+void test_other(struct Foo *f, __attribute__((address_space(10))) int *i) {
+// X64-LABEL: define dso_local void @test_other({{.*}}i32 addrspace(10)* %i)
+// X86-LABEL: define dso_local void @test_other({{.*}}i32 addrspace(10)* %i)
+// X64: %{{.+}} = addrspacecast i32 addrspace(10)* %i to i32 addrspace(270)*
+// X86: %{{.+}} = addrspacecast i32 addrspace(10)* %i to i32*
+ f->p32 = (int * __ptr32)i;
+ use_foo(f);
+}
diff --git a/clang/test/CodeGenCXX/mangle-ptr-size-address-space.cpp b/clang/test/CodeGenCXX/mangle-ptr-size-address-space.cpp
new file mode 100644
index 000000000000..a7dfe526743c
--- /dev/null
+++ b/clang/test/CodeGenCXX/mangle-ptr-size-address-space.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -fms-extensions -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s --check-prefixes=CHECK
+// RUN: %clang_cc1 -fms-extensions -emit-llvm -triple x86_64-windows-msvc -o - %s | FileCheck %s --check-prefixes=WIN
+
+// CHECK-LABEL: define {{.*}}void @_Z2f0PU10ptr32_sptri
+// WIN-LABEL: define {{.*}}void @"?f0@@YAXPAH at Z"
+void f0(int * __ptr32 p) {}
+
+// CHECK-LABEL: define {{.*}}i8 addrspace(271)* @_Z2f1PU10ptr32_sptri
+// WIN-LABEL: define {{.*}}i8 addrspace(271)* @"?f1@@YAPAXPAH at Z"
+void * __ptr32 __uptr f1(int * __ptr32 p) { return 0; }
+
+// CHECK-LABEL: define {{.*}}void @_Z2f2Pi
+// WIN-LABEL: define {{.*}}void @"?f2@@YAXPEAH at Z"
+void f2(int * __ptr64 p) {}
+
+ // CHECK-LABEL: define {{.*}}i8* @_Z2f3Pi
+// WIN-LABEL: define {{.*}}i8* @"?f3@@YAPEAXPEAH at Z"
+void * __ptr64 f3(int * __ptr64 p) { return 0; }
diff --git a/clang/test/Sema/MicrosoftExtensions.c b/clang/test/Sema/MicrosoftExtensions.c
index 79dba88a9903..35570ff4371b 100644
--- a/clang/test/Sema/MicrosoftExtensions.c
+++ b/clang/test/Sema/MicrosoftExtensions.c
@@ -150,6 +150,20 @@ void ptr_func(int * __ptr64 i) {} // expected-error {{redefinition of 'ptr_func'
void ptr_func2(int * __sptr __ptr32 i) {} // expected-note {{previous definition is here}}
void ptr_func2(int * __uptr __ptr32 i) {} // expected-error {{redefinition of 'ptr_func2'}}
+// Check for warning when return types have the type attribute.
+void *__ptr32 ptr_func3() { return 0; } // expected-note {{previous definition is here}}
+void *__ptr64 ptr_func3() { return 0; } // expected-error {{redefinition of 'ptr_func3'}}
+
+// Test that __ptr32/__ptr64 can be passed as arguments with other address
+// spaces.
+void ptr_func4(int *i);
+void ptr_func5(int *__ptr32 i);
+void test_ptr_arguments() {
+ int *__ptr64 i64;
+ ptr_func4(i64);
+ ptr_func5(i64);
+}
+
int * __sptr __ptr32 __sptr wrong4; // expected-warning {{attribute '__sptr' is already applied}}
__ptr32 int *wrong5; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
diff --git a/clang/test/SemaTemplate/address_space-dependent.cpp b/clang/test/SemaTemplate/address_space-dependent.cpp
index f3d2f3c15d0d..bab6ca5d7b3d 100644
--- a/clang/test/SemaTemplate/address_space-dependent.cpp
+++ b/clang/test/SemaTemplate/address_space-dependent.cpp
@@ -43,7 +43,7 @@ void neg() {
template <long int I>
void tooBig() {
- __attribute__((address_space(I))) int *bounds; // expected-error {{address space is larger than the maximum supported (8388598)}}
+ __attribute__((address_space(I))) int *bounds; // expected-error {{address space is larger than the maximum supported (8388595)}}
}
template <long int I>
@@ -101,7 +101,7 @@ int main() {
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<0x7FFFF6>();
+ correct<0x7FFFF3>();
tooBig<8388650>(); // expected-note {{in instantiation of function template specialization 'tooBig<8388650>' requested here}}
__attribute__((address_space(1))) char *x;
More information about the llvm-branch-commits
mailing list