[clang] [clang] Rework `hasBooleanRepresentation`. (PR #136038)
Michele Scandale via cfe-commits
cfe-commits at lists.llvm.org
Wed Apr 16 14:43:57 PDT 2025
https://github.com/michele-scandale created https://github.com/llvm/llvm-project/pull/136038
This is a follow-up of 13aac46332f607a38067b5ddd466071683b8c255. This commit adjusts the implementation of `hasBooleanRepresentation` to have a similar behavior as the one of `hasIntegerRepresentation`. In particular vector of booleans should be handled in `hasBooleanRepresentation`, while `_Atomic(bool)` should not.
>From 31777c1aad43b3dfc214beefe41c170f86aa9f04 Mon Sep 17 00:00:00 2001
From: Michele Scandale <michele.scandale at gmail.com>
Date: Wed, 16 Apr 2025 14:41:59 -0700
Subject: [PATCH] [clang] Rework `hasBooleanRepresentation`.
This is a follow-up of 13aac46332f607a38067b5ddd466071683b8c255.
This commit adjusts the implementation of `hasBooleanRepresentation` to
have a similar behavior as the one of `hasIntegerRepresentation`.
In particular vector of booleans should be handled in
`hasBooleanRepresentation`, while `_Atomic(bool)` should not.
---
clang/include/clang/AST/Decl.h | 8 ++++++++
clang/include/clang/AST/Type.h | 10 +++++++++-
clang/lib/AST/Type.cpp | 13 +++----------
clang/lib/CodeGen/CGExpr.cpp | 20 +++++++++++++-------
clang/lib/Sema/SemaType.cpp | 2 +-
5 files changed, 34 insertions(+), 19 deletions(-)
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index 3faf63e395a08..07ada202075a2 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -5238,6 +5238,14 @@ inline bool IsEnumDeclScoped(EnumDecl *ED) {
return ED->isScoped();
}
+/// Return the integer type corresponding to the given decl.
+///
+/// We use this function to break a cycle between the inline definitions in
+/// Type.h and Decl.h.
+inline QualType GetEnumDeclIntegerType(EnumDecl *ED) {
+ return ED->getIntegerType();
+}
+
/// OpenMP variants are mangled early based on their OpenMP context selector.
/// The new name looks likes this:
/// <name> + OpenMPVariantManglingSeparatorStr + <mangled OpenMP context>
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 5bf036e3347eb..ce6904abcc71a 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -2774,7 +2774,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
bool hasFloatingRepresentation() const;
/// Determine whether this type has a boolean representation
- /// of some sort.
+ /// of some sort, e.g., it is a boolean type or a vector thereof.
bool hasBooleanRepresentation() const;
// Type Checking Functions: Check to see if this type is structurally the
@@ -8531,6 +8531,7 @@ inline bool Type::isNullPtrType() const {
bool IsEnumDeclComplete(EnumDecl *);
bool IsEnumDeclScoped(EnumDecl *);
+QualType GetEnumDeclIntegerType(EnumDecl *);
inline bool Type::isIntegerType() const {
if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
@@ -8623,6 +8624,13 @@ inline bool Type::isIntegralOrEnumerationType() const {
inline bool Type::isBooleanType() const {
if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() == BuiltinType::Bool;
+ if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) {
+ // Incomplete enum types are not treated as integer types.
+ // FIXME: In C++, enum types are never integer types.
+ return IsEnumDeclComplete(ET->getDecl()) &&
+ !IsEnumDeclScoped(ET->getDecl()) &&
+ GetEnumDeclIntegerType(ET->getDecl())->isBooleanType();
+ }
return false;
}
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 53620003c9655..b456f43d39224 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -2336,16 +2336,9 @@ bool Type::isArithmeticType() const {
}
bool Type::hasBooleanRepresentation() const {
- if (isBooleanType())
- return true;
-
- if (const EnumType *ET = getAs<EnumType>())
- return ET->getDecl()->getIntegerType()->isBooleanType();
-
- if (const AtomicType *AT = getAs<AtomicType>())
- return AT->getValueType()->hasBooleanRepresentation();
-
- return false;
+ if (const auto *VT = dyn_cast<VectorType>(CanonicalType))
+ return VT->getElementType()->isBooleanType();
+ return isBooleanType();
}
Type::ScalarTypeKind Type::getScalarTypeKind() const {
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index abb88477062fc..786a56eed7ed5 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -1920,7 +1920,7 @@ static bool getRangeForType(CodeGenFunction &CGF, QualType Ty,
llvm::MDNode *CodeGenFunction::getRangeForLoadFromType(QualType Ty) {
llvm::APInt Min, End;
if (!getRangeForType(*this, Ty, Min, End, CGM.getCodeGenOpts().StrictEnums,
- Ty->hasBooleanRepresentation()))
+ Ty->hasBooleanRepresentation() && !Ty->isVectorType()))
return nullptr;
llvm::MDBuilder MDHelper(getLLVMContext());
@@ -1948,7 +1948,7 @@ bool CodeGenFunction::EmitScalarRangeCheck(llvm::Value *Value, QualType Ty,
if (!HasBoolCheck && !HasEnumCheck)
return false;
- bool IsBool = Ty->hasBooleanRepresentation() ||
+ bool IsBool = (Ty->hasBooleanRepresentation() && !Ty->isVectorType()) ||
NSAPI(CGM.getContext()).isObjCBOOLType(Ty);
bool NeedsBoolCheck = HasBoolCheck && IsBool;
bool NeedsEnumCheck = HasEnumCheck && Ty->getAs<EnumType>();
@@ -2068,11 +2068,8 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(Address Addr, bool Volatile,
/// by ConvertType) to its load/store type (as returned by
/// convertTypeForLoadStore).
llvm::Value *CodeGenFunction::EmitToMemory(llvm::Value *Value, QualType Ty) {
- if (Ty->hasBooleanRepresentation() || Ty->isBitIntType()) {
- llvm::Type *StoreTy = convertTypeForLoadStore(Ty, Value->getType());
- bool Signed = Ty->isSignedIntegerOrEnumerationType();
- return Builder.CreateIntCast(Value, StoreTy, Signed, "storedv");
- }
+ if (auto *AtomicTy = Ty->getAs<AtomicType>())
+ Ty = AtomicTy->getValueType();
if (Ty->isExtVectorBoolType()) {
llvm::Type *StoreTy = convertTypeForLoadStore(Ty, Value->getType());
@@ -2088,6 +2085,12 @@ llvm::Value *CodeGenFunction::EmitToMemory(llvm::Value *Value, QualType Ty) {
Value = Builder.CreateBitCast(Value, StoreTy);
}
+ if (Ty->hasBooleanRepresentation() || Ty->isBitIntType()) {
+ llvm::Type *StoreTy = convertTypeForLoadStore(Ty, Value->getType());
+ bool Signed = Ty->isSignedIntegerOrEnumerationType();
+ return Builder.CreateIntCast(Value, StoreTy, Signed, "storedv");
+ }
+
return Value;
}
@@ -2095,6 +2098,9 @@ llvm::Value *CodeGenFunction::EmitToMemory(llvm::Value *Value, QualType Ty) {
/// by convertTypeForLoadStore) to its primary IR type (as returned
/// by ConvertType).
llvm::Value *CodeGenFunction::EmitFromMemory(llvm::Value *Value, QualType Ty) {
+ if (auto *AtomicTy = Ty->getAs<AtomicType>())
+ Ty = AtomicTy->getValueType();
+
if (Ty->isPackedVectorBoolType(getContext())) {
const auto *RawIntTy = Value->getType();
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index eba7267904fb2..427905a4ddafe 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -9955,7 +9955,7 @@ QualType Sema::BuiltinChangeSignedness(QualType BaseType, UTTKind UKind,
SourceLocation Loc) {
bool IsMakeSigned = UKind == UnaryTransformType::MakeSigned;
if ((!BaseType->isIntegerType() && !BaseType->isEnumeralType()) ||
- BaseType->isBooleanType() ||
+ (BaseType->isBooleanType() && !BaseType->isEnumeralType()) ||
(BaseType->isBitIntType() &&
BaseType->getAs<BitIntType>()->getNumBits() < 2)) {
Diag(Loc, diag::err_make_signed_integral_only)
More information about the cfe-commits
mailing list