summaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CGExprScalar.cpp
diff options
context:
space:
mode:
authorVitaly Buka <vitalybuka@google.com>2024-04-03 10:27:09 -0700
committerGitHub <noreply@github.com>2024-04-03 10:27:09 -0700
commit5822ca5a013256bbca33fbbae56f49caa2e37fe3 (patch)
tree70264248326cd40964719bb9b76236e71df0ec4f /clang/lib/CodeGen/CGExprScalar.cpp
parent315c88c5fbdb2b27cebf23c87fb502f7a567d84b (diff)
Revert "[clang][UBSan] Add implicit conversion check for bitfields" (#87518)
Reverts llvm/llvm-project#75481 Breaks multiple bots, see #75481
Diffstat (limited to 'clang/lib/CodeGen/CGExprScalar.cpp')
-rw-r--r--clang/lib/CodeGen/CGExprScalar.cpp257
1 files changed, 32 insertions, 225 deletions
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index a4ab8a11b867..397b4977acc3 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -15,7 +15,6 @@
#include "CGDebugInfo.h"
#include "CGObjCRuntime.h"
#include "CGOpenMPRuntime.h"
-#include "CGRecordLayout.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "ConstantEmitter.h"
@@ -309,7 +308,6 @@ public:
llvm::Type *DstTy, SourceLocation Loc);
/// Known implicit conversion check kinds.
- /// This is used for bitfield conversion checks as well.
/// Keep in sync with the enum of the same name in ubsan_handlers.h
enum ImplicitConversionCheckKind : unsigned char {
ICCK_IntegerTruncation = 0, // Legacy, was only used by clang 7.
@@ -1105,21 +1103,6 @@ void ScalarExprEmitter::EmitIntegerTruncationCheck(Value *Src, QualType SrcType,
{Src, Dst});
}
-static llvm::Value *EmitIsNegativeTestHelper(Value *V, QualType VType,
- const char *Name,
- CGBuilderTy &Builder) {
- bool VSigned = VType->isSignedIntegerOrEnumerationType();
- llvm::Type *VTy = V->getType();
- if (!VSigned) {
- // If the value is unsigned, then it is never negative.
- return llvm::ConstantInt::getFalse(VTy->getContext());
- }
- llvm::Constant *Zero = llvm::ConstantInt::get(VTy, 0);
- return Builder.CreateICmp(llvm::ICmpInst::ICMP_SLT, V, Zero,
- llvm::Twine(Name) + "." + V->getName() +
- ".negativitycheck");
-}
-
// Should be called within CodeGenFunction::SanitizerScope RAII scope.
// Returns 'i1 false' when the conversion Src -> Dst changed the sign.
static std::pair<ScalarExprEmitter::ImplicitConversionCheckKind,
@@ -1144,12 +1127,30 @@ EmitIntegerSignChangeCheckHelper(Value *Src, QualType SrcType, Value *Dst,
assert(((SrcBits != DstBits) || (SrcSigned != DstSigned)) &&
"either the widths should be different, or the signednesses.");
+ // NOTE: zero value is considered to be non-negative.
+ auto EmitIsNegativeTest = [&Builder](Value *V, QualType VType,
+ const char *Name) -> Value * {
+ // Is this value a signed type?
+ bool VSigned = VType->isSignedIntegerOrEnumerationType();
+ llvm::Type *VTy = V->getType();
+ if (!VSigned) {
+ // If the value is unsigned, then it is never negative.
+ // FIXME: can we encounter non-scalar VTy here?
+ return llvm::ConstantInt::getFalse(VTy->getContext());
+ }
+ // Get the zero of the same type with which we will be comparing.
+ llvm::Constant *Zero = llvm::ConstantInt::get(VTy, 0);
+ // %V.isnegative = icmp slt %V, 0
+ // I.e is %V *strictly* less than zero, does it have negative value?
+ return Builder.CreateICmp(llvm::ICmpInst::ICMP_SLT, V, Zero,
+ llvm::Twine(Name) + "." + V->getName() +
+ ".negativitycheck");
+ };
+
// 1. Was the old Value negative?
- llvm::Value *SrcIsNegative =
- EmitIsNegativeTestHelper(Src, SrcType, "src", Builder);
+ llvm::Value *SrcIsNegative = EmitIsNegativeTest(Src, SrcType, "src");
// 2. Is the new Value negative?
- llvm::Value *DstIsNegative =
- EmitIsNegativeTestHelper(Dst, DstType, "dst", Builder);
+ llvm::Value *DstIsNegative = EmitIsNegativeTest(Dst, DstType, "dst");
// 3. Now, was the 'negativity status' preserved during the conversion?
// NOTE: conversion from negative to zero is considered to change the sign.
// (We want to get 'false' when the conversion changed the sign)
@@ -1244,136 +1245,6 @@ void ScalarExprEmitter::EmitIntegerSignChangeCheck(Value *Src, QualType SrcType,
{Src, Dst});
}
-// Should be called within CodeGenFunction::SanitizerScope RAII scope.
-// Returns 'i1 false' when the truncation Src -> Dst was lossy.
-static std::pair<ScalarExprEmitter::ImplicitConversionCheckKind,
- std::pair<llvm::Value *, SanitizerMask>>
-EmitBitfieldTruncationCheckHelper(Value *Src, QualType SrcType, Value *Dst,
- QualType DstType, CGBuilderTy &Builder) {
- bool SrcSigned = SrcType->isSignedIntegerOrEnumerationType();
- bool DstSigned = DstType->isSignedIntegerOrEnumerationType();
-
- ScalarExprEmitter::ImplicitConversionCheckKind Kind;
- if (!SrcSigned && !DstSigned)
- Kind = ScalarExprEmitter::ICCK_UnsignedIntegerTruncation;
- else
- Kind = ScalarExprEmitter::ICCK_SignedIntegerTruncation;
-
- llvm::Value *Check = nullptr;
- // 1. Extend the truncated value back to the same width as the Src.
- Check = Builder.CreateIntCast(Dst, Src->getType(), DstSigned, "bf.anyext");
- // 2. Equality-compare with the original source value
- Check = Builder.CreateICmpEQ(Check, Src, "bf.truncheck");
- // If the comparison result is 'i1 false', then the truncation was lossy.
-
- return std::make_pair(
- Kind, std::make_pair(Check, SanitizerKind::ImplicitBitfieldConversion));
-}
-
-// Should be called within CodeGenFunction::SanitizerScope RAII scope.
-// Returns 'i1 false' when the conversion Src -> Dst changed the sign.
-static std::pair<ScalarExprEmitter::ImplicitConversionCheckKind,
- std::pair<llvm::Value *, SanitizerMask>>
-EmitBitfieldSignChangeCheckHelper(Value *Src, QualType SrcType, Value *Dst,
- QualType DstType, CGBuilderTy &Builder) {
- // 1. Was the old Value negative?
- llvm::Value *SrcIsNegative =
- EmitIsNegativeTestHelper(Src, SrcType, "bf.src", Builder);
- // 2. Is the new Value negative?
- llvm::Value *DstIsNegative =
- EmitIsNegativeTestHelper(Dst, DstType, "bf.dst", Builder);
- // 3. Now, was the 'negativity status' preserved during the conversion?
- // NOTE: conversion from negative to zero is considered to change the sign.
- // (We want to get 'false' when the conversion changed the sign)
- // So we should just equality-compare the negativity statuses.
- llvm::Value *Check = nullptr;
- Check =
- Builder.CreateICmpEQ(SrcIsNegative, DstIsNegative, "bf.signchangecheck");
- // If the comparison result is 'false', then the conversion changed the sign.
- return std::make_pair(
- ScalarExprEmitter::ICCK_IntegerSignChange,
- std::make_pair(Check, SanitizerKind::ImplicitBitfieldConversion));
-}
-
-void CodeGenFunction::EmitBitfieldConversionCheck(Value *Src, QualType SrcType,
- Value *Dst, QualType DstType,
- const CGBitFieldInfo &Info,
- SourceLocation Loc) {
-
- if (!SanOpts.has(SanitizerKind::ImplicitBitfieldConversion))
- return;
-
- // We only care about int->int conversions here.
- // We ignore conversions to/from pointer and/or bool.
- if (!PromotionIsPotentiallyEligibleForImplicitIntegerConversionCheck(SrcType,
- DstType))
- return;
-
- if (DstType->isBooleanType() || SrcType->isBooleanType())
- return;
-
- // This should be truncation of integral types.
- assert(isa<llvm::IntegerType>(Src->getType()) &&
- isa<llvm::IntegerType>(Dst->getType()) && "non-integer llvm type");
-
- // TODO: Calculate src width to avoid emitting code
- // for unecessary cases.
- unsigned SrcBits = ConvertType(SrcType)->getScalarSizeInBits();
- unsigned DstBits = Info.Size;
-
- bool SrcSigned = SrcType->isSignedIntegerOrEnumerationType();
- bool DstSigned = DstType->isSignedIntegerOrEnumerationType();
-
- CodeGenFunction::SanitizerScope SanScope(this);
-
- std::pair<ScalarExprEmitter::ImplicitConversionCheckKind,
- std::pair<llvm::Value *, SanitizerMask>>
- Check;
-
- // Truncation
- bool EmitTruncation = DstBits < SrcBits;
- // If Dst is signed and Src unsigned, we want to be more specific
- // about the CheckKind we emit, in this case we want to emit
- // ICCK_SignedIntegerTruncationOrSignChange.
- bool EmitTruncationFromUnsignedToSigned =
- EmitTruncation && DstSigned && !SrcSigned;
- // Sign change
- bool SameTypeSameSize = SrcSigned == DstSigned && SrcBits == DstBits;
- bool BothUnsigned = !SrcSigned && !DstSigned;
- bool LargerSigned = (DstBits > SrcBits) && DstSigned;
- // We can avoid emitting sign change checks in some obvious cases
- // 1. If Src and Dst have the same signedness and size
- // 2. If both are unsigned sign check is unecessary!
- // 3. If Dst is signed and bigger than Src, either
- // sign-extension or zero-extension will make sure
- // the sign remains.
- bool EmitSignChange = !SameTypeSameSize && !BothUnsigned && !LargerSigned;
-
- if (EmitTruncation)
- Check =
- EmitBitfieldTruncationCheckHelper(Src, SrcType, Dst, DstType, Builder);
- else if (EmitSignChange) {
- assert(((SrcBits != DstBits) || (SrcSigned != DstSigned)) &&
- "either the widths should be different, or the signednesses.");
- Check =
- EmitBitfieldSignChangeCheckHelper(Src, SrcType, Dst, DstType, Builder);
- } else
- return;
-
- ScalarExprEmitter::ImplicitConversionCheckKind CheckKind = Check.first;
- if (EmitTruncationFromUnsignedToSigned)
- CheckKind = ScalarExprEmitter::ICCK_SignedIntegerTruncationOrSignChange;
-
- llvm::Constant *StaticArgs[] = {
- EmitCheckSourceLocation(Loc), EmitCheckTypeDescriptor(SrcType),
- EmitCheckTypeDescriptor(DstType),
- llvm::ConstantInt::get(Builder.getInt8Ty(), CheckKind),
- llvm::ConstantInt::get(Builder.getInt32Ty(), Info.Size)};
-
- EmitCheck(Check.second, SanitizerHandler::ImplicitConversion, StaticArgs,
- {Src, Dst});
-}
-
Value *ScalarExprEmitter::EmitScalarCast(Value *Src, QualType SrcType,
QualType DstType, llvm::Type *SrcTy,
llvm::Type *DstTy,
@@ -2749,8 +2620,6 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
llvm::PHINode *atomicPHI = nullptr;
llvm::Value *value;
llvm::Value *input;
- llvm::Value *Previous = nullptr;
- QualType SrcType = E->getType();
int amount = (isInc ? 1 : -1);
bool isSubtraction = !isInc;
@@ -2839,8 +2708,7 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
"base or promoted) will be signed, or the bitwidths will match.");
}
if (CGF.SanOpts.hasOneOf(
- SanitizerKind::ImplicitIntegerArithmeticValueChange |
- SanitizerKind::ImplicitBitfieldConversion) &&
+ SanitizerKind::ImplicitIntegerArithmeticValueChange) &&
canPerformLossyDemotionCheck) {
// While `x += 1` (for `x` with width less than int) is modeled as
// promotion+arithmetics+demotion, and we can catch lossy demotion with
@@ -2851,26 +2719,13 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
// the increment/decrement in the wider type, and finally
// perform the demotion. This will catch lossy demotions.
- // We have a special case for bitfields defined using all the bits of the
- // type. In this case we need to do the same trick as for the integer
- // sanitizer checks, i.e., promotion -> increment/decrement -> demotion.
-
value = EmitScalarConversion(value, type, promotedType, E->getExprLoc());
Value *amt = llvm::ConstantInt::get(value->getType(), amount, true);
value = Builder.CreateAdd(value, amt, isInc ? "inc" : "dec");
// Do pass non-default ScalarConversionOpts so that sanitizer check is
- // emitted if LV is not a bitfield, otherwise the bitfield sanitizer
- // checks will take care of the conversion.
- ScalarConversionOpts Opts;
- if (!LV.isBitField())
- Opts = ScalarConversionOpts(CGF.SanOpts);
- else if (CGF.SanOpts.has(SanitizerKind::ImplicitBitfieldConversion)) {
- Previous = value;
- SrcType = promotedType;
- }
-
+ // emitted.
value = EmitScalarConversion(value, promotedType, type, E->getExprLoc(),
- Opts);
+ ScalarConversionOpts(CGF.SanOpts));
// Note that signed integer inc/dec with width less than int can't
// overflow because of promotion rules; we're just eliding a few steps
@@ -3055,12 +2910,9 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
}
// Store the updated result through the lvalue.
- if (LV.isBitField()) {
- Value *Src = Previous ? Previous : value;
+ if (LV.isBitField())
CGF.EmitStoreThroughBitfieldLValue(RValue::get(value), LV, &value);
- CGF.EmitBitfieldConversionCheck(Src, SrcType, value, E->getType(),
- LV.getBitFieldInfo(), E->getExprLoc());
- } else
+ else
CGF.EmitStoreThroughLValue(RValue::get(value), LV);
// If this is a postinc, return the value read from memory, otherwise use the
@@ -3565,15 +3417,8 @@ LValue ScalarExprEmitter::EmitCompoundAssignLValue(
// Convert the result back to the LHS type,
// potentially with Implicit Conversion sanitizer check.
- // If LHSLV is a bitfield, use default ScalarConversionOpts
- // to avoid emit any implicit integer checks.
- Value *Previous = nullptr;
- if (LHSLV.isBitField()) {
- Previous = Result;
- Result = EmitScalarConversion(Result, PromotionTypeCR, LHSTy, Loc);
- } else
- Result = EmitScalarConversion(Result, PromotionTypeCR, LHSTy, Loc,
- ScalarConversionOpts(CGF.SanOpts));
+ Result = EmitScalarConversion(Result, PromotionTypeCR, LHSTy, Loc,
+ ScalarConversionOpts(CGF.SanOpts));
if (atomicPHI) {
llvm::BasicBlock *curBlock = Builder.GetInsertBlock();
@@ -3592,14 +3437,9 @@ LValue ScalarExprEmitter::EmitCompoundAssignLValue(
// specially because the result is altered by the store, i.e., [C99 6.5.16p1]
// 'An assignment expression has the value of the left operand after the
// assignment...'.
- if (LHSLV.isBitField()) {
- Value *Src = Previous ? Previous : Result;
- QualType SrcType = E->getRHS()->getType();
- QualType DstType = E->getLHS()->getType();
+ if (LHSLV.isBitField())
CGF.EmitStoreThroughBitfieldLValue(RValue::get(Result), LHSLV, &Result);
- CGF.EmitBitfieldConversionCheck(Src, SrcType, Result, DstType,
- LHSLV.getBitFieldInfo(), E->getExprLoc());
- } else
+ else
CGF.EmitStoreThroughLValue(RValue::get(Result), LHSLV);
if (CGF.getLangOpts().OpenMP)
@@ -4711,24 +4551,6 @@ Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E,
E->getExprLoc());
}
-llvm::Value *CodeGenFunction::EmitWithOriginalRHSBitfieldAssignment(
- const BinaryOperator *E, Value *Previous, QualType *SrcType) {
- // In case we have the integer or bitfield sanitizer checks enabled
- // we want to get the expression before scalar conversion.
- if (auto *ICE = dyn_cast<ImplicitCastExpr>(E->getRHS())) {
- CastKind Kind = ICE->getCastKind();
- if (Kind == CK_IntegralCast) {
- *SrcType = ICE->getSubExpr()->getType();
- Previous = EmitScalarExpr(ICE->getSubExpr());
- // Pass default ScalarConversionOpts to avoid emitting
- // integer sanitizer checks as E refers to bitfield.
- return EmitScalarConversion(Previous, *SrcType, ICE->getType(),
- ICE->getExprLoc());
- }
- }
- return EmitScalarExpr(E->getRHS());
-}
-
Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) {
bool Ignore = TestAndClearIgnoreResultAssign();
@@ -4757,16 +4579,7 @@ Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) {
case Qualifiers::OCL_None:
// __block variables need to have the rhs evaluated first, plus
// this should improve codegen just a little.
- Value *Previous = nullptr;
- QualType SrcType = E->getRHS()->getType();
- // Check if LHS is a bitfield, if RHS contains an implicit cast expression
- // we want to extract that value and potentially (if the bitfield sanitizer
- // is enabled) use it to check for an implicit conversion.
- if (E->getLHS()->refersToBitField())
- RHS = CGF.EmitWithOriginalRHSBitfieldAssignment(E, Previous, &SrcType);
- else
- RHS = Visit(E->getRHS());
-
+ RHS = Visit(E->getRHS());
LHS = EmitCheckedLValue(E->getLHS(), CodeGenFunction::TCK_Store);
// Store the value into the LHS. Bit-fields are handled specially
@@ -4775,12 +4588,6 @@ Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) {
// the assignment...'.
if (LHS.isBitField()) {
CGF.EmitStoreThroughBitfieldLValue(RValue::get(RHS), LHS, &RHS);
- // If the expression contained an implicit conversion, make sure
- // to use the value before the scalar conversion.
- Value *Src = Previous ? Previous : RHS;
- QualType DstType = E->getLHS()->getType();
- CGF.EmitBitfieldConversionCheck(Src, SrcType, RHS, DstType,
- LHS.getBitFieldInfo(), E->getExprLoc());
} else {
CGF.EmitNullabilityCheck(LHS, RHS, E->getExprLoc());
CGF.EmitStoreThroughLValue(RValue::get(RHS), LHS);