Convert clang::LangAS to a strongly typed enum
Summary:
Convert clang::LangAS to a strongly typed enum
Currently both clang AST address spaces and target specific address spaces
are represented as unsigned which can lead to subtle errors if the wrong
type is passed. It is especially confusing in the CodeGen files as it is
not possible to see what kind of address space should be passed to a
function without looking at the implementation.
I originally made this change for our LLVM fork for the CHERI architecture
where we make extensive use of address spaces to differentiate between
capabilities and pointers. When merging the upstream changes I usually
run into some test failures or runtime crashes because the wrong kind of
address space is passed to a function. By converting the LangAS enum to a
C++11 we can catch these errors at compile time. Additionally, it is now
obvious from the function signature which kind of address space it expects.
I found the following errors while writing this patch:
- ItaniumRecordLayoutBuilder::LayoutField was passing a clang AST address
space to TargetInfo::getPointer{Width,Align}()
- TypePrinter::printAttributedAfter() prints the numeric value of the
clang AST address space instead of the target address space.
However, this code is not used so I kept the current behaviour
- initializeForBlockHeader() in CGBlocks.cpp was passing
LangAS::opencl_generic to TargetInfo::getPointer{Width,Align}()
- CodeGenFunction::EmitBlockLiteral() was passing a AST address space to
TargetInfo::getPointerWidth()
- CGOpenMPRuntimeNVPTX::translateParameter() passed a target address space
to Qualifiers::addAddressSpace()
- CGOpenMPRuntimeNVPTX::getParameterAddress() was using
llvm::Type::getPointerTo() with a AST address space
- clang_getAddressSpace() returns either a LangAS or a target address
space. As this is exposed to C I have kept the current behaviour and
added a comment stating that it is probably not correct.
Other than this the patch should not cause any functional changes.
Reviewers: yaxunl, pcc, bader
Reviewed By: yaxunl, bader
Subscribers: jlebar, jholewinski, nhaehnle, Anastasia, cfe-commits
Differential Revision: https://reviews.llvm.org/D38816
llvm-svn: 315871
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 37f2ff3..cd534b2 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -3140,7 +3140,7 @@
// Treat this argument as _Nonnull as we want to show a warning if
// NULL is passed into it.
CheckNonNullArgument(*this, ValArg, DRE->getLocStart());
- unsigned AS = 0;
+ LangAS AS = LangAS::Default;
// Keep address space of non-atomic pointer type.
if (const PointerType *PtrTy =
ValArg->getType()->getAs<PointerType>()) {
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index e6f3aea..7df9ed5 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -7332,8 +7332,8 @@
// This includes arrays of objects with address space qualifiers, but not
// automatic variables that point to other address spaces.
// ISO/IEC TR 18037 S5.1.2
- if (!getLangOpts().OpenCL
- && NewVD->hasLocalStorage() && T.getAddressSpace() != 0) {
+ if (!getLangOpts().OpenCL && NewVD->hasLocalStorage() &&
+ T.getAddressSpace() != LangAS::Default) {
Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl) << 0;
NewVD->setInvalidDecl();
return;
@@ -8833,7 +8833,7 @@
if (getLangOpts().OpenCL) {
// OpenCL v1.1 s6.5: Using an address space qualifier in a function return
// type declaration will generate a compilation error.
- unsigned AddressSpace = NewFD->getReturnType().getAddressSpace();
+ LangAS AddressSpace = NewFD->getReturnType().getAddressSpace();
if (AddressSpace != LangAS::Default) {
Diag(NewFD->getLocation(),
diag::err_opencl_return_value_with_address_space);
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 1f4be44..655d6e9 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -4385,7 +4385,7 @@
static bool isValidSwiftContextType(QualType type) {
if (!type->hasPointerRepresentation())
return type->isDependentType();
- return type->getPointeeType().getAddressSpace() == 0;
+ return type->getPointeeType().getAddressSpace() == LangAS::Default;
}
/// Pointers and references in the default address space.
@@ -4397,7 +4397,7 @@
} else {
return type->isDependentType();
}
- return type.getAddressSpace() == 0;
+ return type.getAddressSpace() == LangAS::Default;
}
/// Pointers and references to pointers in the default address space.
diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp
index 104b2df..607ffe9 100644
--- a/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/clang/lib/Sema/SemaDeclObjC.cpp
@@ -4688,7 +4688,7 @@
// duration shall not be qualified by an address-space qualifier."
// Since all parameters have automatic store duration, they can not have
// an address space.
- if (T.getAddressSpace() != 0) {
+ if (T.getAddressSpace() != LangAS::Default) {
Diag(IdLoc, diag::err_arg_with_address_space);
Invalid = true;
}
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 4e27170..5e7ed2d 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -5064,7 +5064,7 @@
}
NeedsNewDecl = true;
- unsigned AS = ArgType->getPointeeType().getQualifiers().getAddressSpace();
+ LangAS AS = ArgType->getPointeeType().getAddressSpace();
QualType PointeeType = ParamType->getPointeeType();
PointeeType = Context.getAddrSpaceQualType(PointeeType, AS);
@@ -5760,8 +5760,8 @@
case Type::STK_ObjCObjectPointer:
switch (DestTy->getScalarTypeKind()) {
case Type::STK_CPointer: {
- unsigned SrcAS = SrcTy->getPointeeType().getAddressSpace();
- unsigned DestAS = DestTy->getPointeeType().getAddressSpace();
+ LangAS SrcAS = SrcTy->getPointeeType().getAddressSpace();
+ LangAS DestAS = DestTy->getPointeeType().getAddressSpace();
if (SrcAS != DestAS)
return CK_AddressSpaceConversion;
return CK_BitCast;
@@ -6365,9 +6365,9 @@
Qualifiers lhQual = lhptee.getQualifiers();
Qualifiers rhQual = rhptee.getQualifiers();
- unsigned ResultAddrSpace = 0;
- unsigned LAddrSpace = lhQual.getAddressSpace();
- unsigned RAddrSpace = rhQual.getAddressSpace();
+ LangAS ResultAddrSpace = LangAS::Default;
+ LangAS LAddrSpace = lhQual.getAddressSpace();
+ LangAS RAddrSpace = rhQual.getAddressSpace();
if (S.getLangOpts().OpenCL) {
// OpenCL v1.1 s6.5 - Conversion between pointers to distinct address
// spaces is disallowed.
@@ -7649,8 +7649,8 @@
if (const PointerType *LHSPointer = dyn_cast<PointerType>(LHSType)) {
// U* -> T*
if (isa<PointerType>(RHSType)) {
- unsigned AddrSpaceL = LHSPointer->getPointeeType().getAddressSpace();
- unsigned AddrSpaceR = RHSType->getPointeeType().getAddressSpace();
+ LangAS AddrSpaceL = LHSPointer->getPointeeType().getAddressSpace();
+ LangAS AddrSpaceR = RHSType->getPointeeType().getAddressSpace();
Kind = AddrSpaceL != AddrSpaceR ? CK_AddressSpaceConversion : CK_BitCast;
return checkPointerTypesForAssignment(*this, LHSType, RHSType);
}
@@ -7685,10 +7685,10 @@
// U^ -> void*
if (RHSType->getAs<BlockPointerType>()) {
if (LHSPointer->getPointeeType()->isVoidType()) {
- unsigned AddrSpaceL = LHSPointer->getPointeeType().getAddressSpace();
- unsigned AddrSpaceR = RHSType->getAs<BlockPointerType>()
- ->getPointeeType()
- .getAddressSpace();
+ LangAS AddrSpaceL = LHSPointer->getPointeeType().getAddressSpace();
+ LangAS AddrSpaceR = RHSType->getAs<BlockPointerType>()
+ ->getPointeeType()
+ .getAddressSpace();
Kind =
AddrSpaceL != AddrSpaceR ? CK_AddressSpaceConversion : CK_BitCast;
return Compatible;
@@ -7702,12 +7702,12 @@
if (isa<BlockPointerType>(LHSType)) {
// U^ -> T^
if (RHSType->isBlockPointerType()) {
- unsigned AddrSpaceL = LHSType->getAs<BlockPointerType>()
- ->getPointeeType()
- .getAddressSpace();
- unsigned AddrSpaceR = RHSType->getAs<BlockPointerType>()
- ->getPointeeType()
- .getAddressSpace();
+ LangAS AddrSpaceL = LHSType->getAs<BlockPointerType>()
+ ->getPointeeType()
+ .getAddressSpace();
+ LangAS AddrSpaceR = RHSType->getAs<BlockPointerType>()
+ ->getPointeeType()
+ .getAddressSpace();
Kind = AddrSpaceL != AddrSpaceR ? CK_AddressSpaceConversion : CK_BitCast;
return checkBlockPointerTypesForAssignment(*this, LHSType, RHSType);
}
@@ -9804,8 +9804,8 @@
<< LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
}
}
- unsigned AddrSpaceL = LCanPointeeTy.getAddressSpace();
- unsigned AddrSpaceR = RCanPointeeTy.getAddressSpace();
+ LangAS AddrSpaceL = LCanPointeeTy.getAddressSpace();
+ LangAS AddrSpaceR = RCanPointeeTy.getAddressSpace();
CastKind Kind = AddrSpaceL != AddrSpaceR ? CK_AddressSpaceConversion
: CK_BitCast;
if (LHSIsNull && !RHSIsNull)
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index d8036c7..17aa884 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -2113,7 +2113,7 @@
else if (AllocType->isVariablyModifiedType())
return Diag(Loc, diag::err_variably_modified_new_type)
<< AllocType;
- else if (AllocType.getAddressSpace())
+ else if (AllocType.getAddressSpace() != LangAS::Default)
return Diag(Loc, diag::err_address_space_qualified_new)
<< AllocType.getUnqualifiedType()
<< AllocType.getQualifiers().getAddressSpaceAttributePrintValue();
@@ -3185,7 +3185,7 @@
QualType Pointee = Type->getAs<PointerType>()->getPointeeType();
QualType PointeeElem = Context.getBaseElementType(Pointee);
- if (Pointee.getAddressSpace())
+ if (Pointee.getAddressSpace() != LangAS::Default)
return Diag(Ex.get()->getLocStart(),
diag::err_address_space_qualified_delete)
<< Pointee.getUnqualifiedType()
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index a4f7e8d..51f21be 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -1870,11 +1870,10 @@
Deduced);
}
- if (Arg.getAddressSpace() >= LangAS::FirstTargetAddressSpace) {
+ if (isTargetAddressSpace(Arg.getAddressSpace())) {
llvm::APSInt ArgAddressSpace(S.Context.getTypeSize(S.Context.IntTy),
false);
- ArgAddressSpace =
- (Arg.getAddressSpace() - LangAS::FirstTargetAddressSpace);
+ ArgAddressSpace = toTargetAddressSpace(Arg.getAddressSpace());
// Perform deduction on the pointer types.
if (Sema::TemplateDeductionResult Result =
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index d3f63b4..80b6c1d 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -5631,7 +5631,7 @@
// 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()) {
+ if (T.getAddressSpace() != LangAS::Default) {
Diag(AttrLoc, diag::err_attribute_address_multiple_qualifiers);
return QualType();
}
@@ -5655,15 +5655,16 @@
}
llvm::APSInt max(addrSpace.getBitWidth());
- max = Qualifiers::MaxAddressSpace - LangAS::FirstTargetAddressSpace;
+ max =
+ Qualifiers::MaxAddressSpace - (unsigned)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<unsigned>(addrSpace.getZExtValue()) +
- LangAS::FirstTargetAddressSpace;
+ LangAS ASIdx =
+ getLangASFromTargetAS(static_cast<unsigned>(addrSpace.getZExtValue()));
return Context.getAddrSpaceQualType(T, ASIdx);
}
@@ -5689,7 +5690,7 @@
// 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 (Type.getAddressSpace()) {
+ if (Type.getAddressSpace() != LangAS::Default) {
S.Diag(Attr.getLoc(), diag::err_attribute_address_multiple_qualifiers);
Attr.setInvalid();
return;
@@ -5703,7 +5704,7 @@
return;
}
- unsigned ASIdx;
+ LangAS ASIdx;
if (Attr.getKind() == AttributeList::AT_AddressSpace) {
// Check the attribute arguments.
@@ -7036,7 +7037,7 @@
(T->isVoidType() && !IsPointee))
return;
- unsigned ImpAddr;
+ LangAS ImpAddr;
// Put OpenCL automatic variable in private address space.
// OpenCL v1.2 s6.5:
// The default address space name for arguments to a function in a