[clang] [PAC] Implement function pointer re-signing (PR #98847)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Jul 14 20:47:53 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-codegen
Author: Akira Hatanaka (ahatanak)
<details>
<summary>Changes</summary>
Re-signing occurs when function type discrimination is enabled and a function pointer is converted to another function pointer type that requires signing using a different discriminator. A function pointer is re-signed using discriminator zero when it's converted to a pointer to a non-function type such as `void*`.
---
Patch is 37.29 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/98847.diff
12 Files Affected:
- (modified) clang/lib/CodeGen/Address.h (+37-7)
- (modified) clang/lib/CodeGen/CGBuilder.h (+2-2)
- (modified) clang/lib/CodeGen/CGExpr.cpp (+2-1)
- (modified) clang/lib/CodeGen/CGExprScalar.cpp (+6-1)
- (modified) clang/lib/CodeGen/CGPointerAuth.cpp (+205)
- (modified) clang/lib/CodeGen/CGValue.h (+11-16)
- (modified) clang/lib/CodeGen/CodeGenFunction.cpp (+74-9)
- (modified) clang/lib/CodeGen/CodeGenFunction.h (+31-7)
- (modified) clang/lib/Headers/ptrauth.h (+15)
- (added) clang/test/CodeGen/ptrauth-function-lvalue-cast-disc.c (+55)
- (added) clang/test/CodeGen/ptrauth-function-type-discriminator-cast.c (+85)
- (added) clang/test/CodeGen/ptrauth.c (+77)
``````````diff
diff --git a/clang/lib/CodeGen/Address.h b/clang/lib/CodeGen/Address.h
index 35ec370a139c9..d753250d428d3 100644
--- a/clang/lib/CodeGen/Address.h
+++ b/clang/lib/CodeGen/Address.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_LIB_CODEGEN_ADDRESS_H
#define LLVM_CLANG_LIB_CODEGEN_ADDRESS_H
+#include "CGPointerAuthInfo.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/Type.h"
#include "llvm/ADT/PointerIntPair.h"
@@ -108,6 +109,22 @@ class RawAddress {
/// Like RawAddress, an abstract representation of an aligned address, but the
/// pointer contained in this class is possibly signed.
+///
+/// This is designed to be an IR-level abstraction, carrying just the
+/// information necessary to perform IR operations on an address like loads and
+/// stores. In particular, it doesn't carry C type information or allow the
+/// representation of things like bit-fields; clients working at that level
+/// should generally be using `LValue`.
+///
+/// An address may be either *raw*, meaning that it's an ordinary machine
+/// pointer, or *signed*, meaning that the pointer carries an embedded
+/// pointer-authentication signature. Representing signed pointers directly in
+/// this abstraction allows the authentication to be delayed as long as possible
+/// without forcing IRGen to use totally different code paths for signed and
+/// unsigned values or to separately propagate signature information through
+/// every API that manipulates addresses. Pointer arithmetic on signed addresses
+/// (e.g. drilling down to a struct field) is accumulated into a separate offset
+/// which is applied when the address is finally accessed.
class Address {
friend class CGBuilderTy;
@@ -121,7 +138,11 @@ class Address {
CharUnits Alignment;
- /// Offset from the base pointer.
+ /// The ptrauth information needed to authenticate the base pointer.
+ CGPointerAuthInfo PtrAuthInfo;
+
+ /// Offset from the base pointer. This is non-null only when the base
+ /// pointer is signed.
llvm::Value *Offset = nullptr;
llvm::Value *emitRawPointerSlow(CodeGenFunction &CGF) const;
@@ -140,12 +161,14 @@ class Address {
}
Address(llvm::Value *BasePtr, llvm::Type *ElementType, CharUnits Alignment,
- llvm::Value *Offset, KnownNonNull_t IsKnownNonNull = NotKnownNonNull)
+ CGPointerAuthInfo PtrAuthInfo, llvm::Value *Offset,
+ KnownNonNull_t IsKnownNonNull = NotKnownNonNull)
: Pointer(BasePtr, IsKnownNonNull), ElementType(ElementType),
- Alignment(Alignment), Offset(Offset) {}
+ Alignment(Alignment), PtrAuthInfo(PtrAuthInfo), Offset(Offset) {}
Address(RawAddress RawAddr)
- : Pointer(RawAddr.isValid() ? RawAddr.getPointer() : nullptr),
+ : Pointer(RawAddr.isValid() ? RawAddr.getPointer() : nullptr,
+ RawAddr.isValid() ? RawAddr.isKnownNonNull() : NotKnownNonNull),
ElementType(RawAddr.isValid() ? RawAddr.getElementType() : nullptr),
Alignment(RawAddr.isValid() ? RawAddr.getAlignment()
: CharUnits::Zero()) {}
@@ -192,6 +215,9 @@ class Address {
/// Return the IR name of the pointer value.
llvm::StringRef getName() const { return Pointer.getPointer()->getName(); }
+ const CGPointerAuthInfo &getPointerAuthInfo() const { return PtrAuthInfo; }
+ void setPointerAuthInfo(const CGPointerAuthInfo &Info) { PtrAuthInfo = Info; }
+
// This function is called only in CGBuilderBaseTy::CreateElementBitCast.
void setElementType(llvm::Type *Ty) {
assert(hasOffset() &&
@@ -199,7 +225,8 @@ class Address {
ElementType = Ty;
}
- /// Whether the pointer is known not to be null.
+ bool isSigned() const { return PtrAuthInfo.isSigned(); }
+
KnownNonNull_t isKnownNonNull() const {
assert(isValid());
return (KnownNonNull_t)Pointer.getInt();
@@ -215,6 +242,9 @@ class Address {
llvm::Value *getOffset() const { return Offset; }
+ Address getResignedAddress(const CGPointerAuthInfo &NewInfo,
+ CodeGenFunction &CGF) const;
+
/// Return the pointer contained in this class after authenticating it and
/// adding offset to it if necessary.
llvm::Value *emitRawPointer(CodeGenFunction &CGF) const {
@@ -240,8 +270,8 @@ class Address {
/// alignment.
Address withElementType(llvm::Type *ElemTy) const {
if (!hasOffset())
- return Address(getBasePointer(), ElemTy, getAlignment(), nullptr,
- isKnownNonNull());
+ return Address(getBasePointer(), ElemTy, getAlignment(),
+ getPointerAuthInfo(), nullptr, isKnownNonNull());
Address A(*this);
A.ElementType = ElemTy;
return A;
diff --git a/clang/lib/CodeGen/CGBuilder.h b/clang/lib/CodeGen/CGBuilder.h
index 0bc4fda62979c..6625c662e041f 100644
--- a/clang/lib/CodeGen/CGBuilder.h
+++ b/clang/lib/CodeGen/CGBuilder.h
@@ -190,8 +190,8 @@ class CGBuilderTy : public CGBuilderBaseTy {
const llvm::Twine &Name = "") {
if (!Addr.hasOffset())
return Address(CreateAddrSpaceCast(Addr.getBasePointer(), Ty, Name),
- ElementTy, Addr.getAlignment(), nullptr,
- Addr.isKnownNonNull());
+ ElementTy, Addr.getAlignment(), Addr.getPointerAuthInfo(),
+ nullptr, Addr.isKnownNonNull());
// Eagerly force a raw address if these is an offset.
return RawAddress(
CreateAddrSpaceCast(Addr.emitRawPointer(*getCGF()), Ty, Name),
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index ddb82571f53d7..7ae5f0b1cf760 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -1311,7 +1311,8 @@ static Address EmitPointerWithAlignment(const Expr *E, LValueBaseInfo *BaseInfo,
if (CE->getCastKind() == CK_AddressSpaceConversion)
Addr = CGF.Builder.CreateAddrSpaceCast(
Addr, CGF.ConvertType(E->getType()), ElemTy);
- return Addr;
+ return CGF.AuthPointerToPointerCast(Addr, CE->getSubExpr()->getType(),
+ CE->getType());
}
break;
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index f40f3c273206b..14ca9341c5148 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -2373,7 +2373,9 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
DestLV.setTBAAInfo(TBAAAccessInfo::getMayAliasInfo());
return EmitLoadOfLValue(DestLV, CE->getExprLoc());
}
- return Builder.CreateBitCast(Src, DstTy);
+
+ llvm::Value *Result = Builder.CreateBitCast(Src, DstTy);
+ return CGF.AuthPointerToPointerCast(Result, E->getType(), DestTy);
}
case CK_AddressSpaceConversion: {
Expr::EvalResult Result;
@@ -2523,6 +2525,8 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
if (DestTy.mayBeDynamicClass())
IntToPtr = Builder.CreateLaunderInvariantGroup(IntToPtr);
}
+
+ IntToPtr = CGF.AuthPointerToPointerCast(IntToPtr, E->getType(), DestTy);
return IntToPtr;
}
case CK_PointerToIntegral: {
@@ -2538,6 +2542,7 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
PtrExpr = Builder.CreateStripInvariantGroup(PtrExpr);
}
+ PtrExpr = CGF.AuthPointerToPointerCast(PtrExpr, E->getType(), DestTy);
return Builder.CreatePtrToInt(PtrExpr, ConvertType(DestTy));
}
case CK_ToVoid: {
diff --git a/clang/lib/CodeGen/CGPointerAuth.cpp b/clang/lib/CodeGen/CGPointerAuth.cpp
index 621d567dde721..3d44d697a29da 100644
--- a/clang/lib/CodeGen/CGPointerAuth.cpp
+++ b/clang/lib/CodeGen/CGPointerAuth.cpp
@@ -15,6 +15,7 @@
#include "CodeGenModule.h"
#include "clang/CodeGen/CodeGenABITypes.h"
#include "clang/CodeGen/ConstantInitBuilder.h"
+#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Support/SipHash.h"
using namespace clang;
@@ -165,6 +166,88 @@ CGPointerAuthInfo CodeGenModule::getPointerAuthInfoForType(QualType T) {
return ::getPointerAuthInfoForType(*this, T);
}
+static bool isZeroConstant(llvm::Value *value) {
+ if (auto ci = dyn_cast<llvm::ConstantInt>(value))
+ return ci->isZero();
+ return false;
+}
+
+static bool equalAuthPolicies(const CGPointerAuthInfo &left,
+ const CGPointerAuthInfo &right) {
+ if (left.isSigned() != right.isSigned())
+ return false;
+ assert(left.isSigned() && right.isSigned() &&
+ "should only be called with non-null auth policies");
+ return left.getKey() == right.getKey() &&
+ left.getAuthenticationMode() == right.getAuthenticationMode();
+}
+
+llvm::Value *CodeGenFunction::EmitPointerAuthResign(
+ llvm::Value *value, QualType type, const CGPointerAuthInfo &curAuthInfo,
+ const CGPointerAuthInfo &newAuthInfo, bool isKnownNonNull) {
+ // Fast path: if neither schema wants a signature, we're done.
+ if (!curAuthInfo && !newAuthInfo)
+ return value;
+
+ llvm::Value *null = nullptr;
+ // If the value is obviously null, we're done.
+ if (auto pointerValue = dyn_cast<llvm::PointerType>(value->getType())) {
+ null = CGM.getNullPointer(pointerValue, type);
+ } else {
+ assert(value->getType()->isIntegerTy());
+ null = llvm::ConstantInt::get(IntPtrTy, 0);
+ }
+ if (value == null) {
+ return value;
+ }
+
+ // If both schemas sign the same way, we're done.
+ if (equalAuthPolicies(curAuthInfo, newAuthInfo)) {
+ auto curD = curAuthInfo.getDiscriminator();
+ auto newD = newAuthInfo.getDiscriminator();
+ if (curD == newD)
+ return value;
+
+ if ((curD == nullptr && isZeroConstant(newD)) ||
+ (newD == nullptr && isZeroConstant(curD)))
+ return value;
+ }
+
+ llvm::BasicBlock *initBB = Builder.GetInsertBlock();
+ llvm::BasicBlock *resignBB = nullptr, *contBB = nullptr;
+
+ // Null pointers have to be mapped to null, and the ptrauth_resign
+ // intrinsic doesn't do that.
+ if (!isKnownNonNull && !llvm::isKnownNonZero(value, CGM.getDataLayout())) {
+ contBB = createBasicBlock("resign.cont");
+ resignBB = createBasicBlock("resign.nonnull");
+
+ auto isNonNull = Builder.CreateICmpNE(value, null);
+ Builder.CreateCondBr(isNonNull, resignBB, contBB);
+ EmitBlock(resignBB);
+ }
+
+ // Perform the auth/sign/resign operation.
+ if (!newAuthInfo) {
+ value = EmitPointerAuthAuth(curAuthInfo, value);
+ } else if (!curAuthInfo) {
+ value = EmitPointerAuthSign(newAuthInfo, value);
+ } else {
+ value = EmitPointerAuthResignCall(value, curAuthInfo, newAuthInfo);
+ }
+
+ // Clean up with a phi if we branched before.
+ if (contBB) {
+ EmitBlock(contBB);
+ auto phi = Builder.CreatePHI(value->getType(), 2);
+ phi->addIncoming(null, initBB);
+ phi->addIncoming(value, resignBB);
+ value = phi;
+ }
+
+ return value;
+}
+
llvm::Constant *
CodeGenModule::getConstantSignedPointer(llvm::Constant *Pointer, unsigned Key,
llvm::Constant *StorageAddress,
@@ -351,3 +434,125 @@ CodeGenModule::getVTablePointerAuthInfo(CodeGenFunction *CGF,
/* IsIsaPointer */ false,
/* AuthenticatesNullValues */ false, Discriminator);
}
+
+llvm::Value *CodeGenFunction::AuthPointerToPointerCast(llvm::Value *ResultPtr,
+ QualType SourceType,
+ QualType DestType) {
+ CGPointerAuthInfo CurAuthInfo, NewAuthInfo;
+ if (SourceType->isSignableType())
+ CurAuthInfo = getPointerAuthInfoForType(CGM, SourceType);
+
+ if (DestType->isSignableType())
+ NewAuthInfo = getPointerAuthInfoForType(CGM, DestType);
+
+ if (!CurAuthInfo && !NewAuthInfo)
+ return ResultPtr;
+
+ // If only one side of the cast is a function pointer, then we still need to
+ // resign to handle casts to/from opaque pointers.
+ if (!CurAuthInfo && DestType->isFunctionPointerType())
+ CurAuthInfo = CGM.getFunctionPointerAuthInfo(SourceType);
+
+ if (!NewAuthInfo && SourceType->isFunctionPointerType())
+ NewAuthInfo = CGM.getFunctionPointerAuthInfo(DestType);
+
+ return EmitPointerAuthResign(ResultPtr, DestType, CurAuthInfo, NewAuthInfo,
+ /*IsKnownNonNull=*/false);
+}
+
+Address CodeGenFunction::AuthPointerToPointerCast(Address Ptr,
+ QualType SourceType,
+ QualType DestType) {
+ CGPointerAuthInfo CurAuthInfo, NewAuthInfo;
+ if (SourceType->isSignableType())
+ CurAuthInfo = getPointerAuthInfoForType(CGM, SourceType);
+
+ if (DestType->isSignableType())
+ NewAuthInfo = getPointerAuthInfoForType(CGM, DestType);
+
+ if (!CurAuthInfo && !NewAuthInfo)
+ return Ptr;
+
+ if (!CurAuthInfo && DestType->isFunctionPointerType()) {
+ // When casting a non-signed pointer to a function pointer, just set the
+ // auth info on Ptr to the assumed schema. The pointer will be resigned to
+ // the effective type when used.
+ Ptr.setPointerAuthInfo(CGM.getFunctionPointerAuthInfo(SourceType));
+ return Ptr;
+ }
+
+ if (!NewAuthInfo && SourceType->isFunctionPointerType()) {
+ NewAuthInfo = CGM.getFunctionPointerAuthInfo(DestType);
+ Ptr = Ptr.getResignedAddress(NewAuthInfo, *this);
+ Ptr.setPointerAuthInfo(CGPointerAuthInfo());
+ return Ptr;
+ }
+
+ return Ptr;
+}
+
+Address CodeGenFunction::EmitPointerAuthSign(Address Addr,
+ QualType PointeeType) {
+ CGPointerAuthInfo Info = getPointerAuthInfoForPointeeType(CGM, PointeeType);
+ llvm::Value *Ptr = EmitPointerAuthSign(Info, Addr.emitRawPointer(*this));
+ return Address(Ptr, Addr.getElementType(), Addr.getAlignment());
+}
+
+Address CodeGenFunction::EmitPointerAuthAuth(Address Addr,
+ QualType PointeeType) {
+ CGPointerAuthInfo Info = getPointerAuthInfoForPointeeType(CGM, PointeeType);
+ llvm::Value *Ptr = EmitPointerAuthAuth(Info, Addr.emitRawPointer(*this));
+ return Address(Ptr, Addr.getElementType(), Addr.getAlignment());
+}
+
+Address CodeGenFunction::getAsNaturalAddressOf(Address Addr,
+ QualType PointeeTy) {
+ CGPointerAuthInfo Info =
+ PointeeTy.isNull() ? CGPointerAuthInfo()
+ : CGM.getPointerAuthInfoForPointeeType(PointeeTy);
+ return Addr.getResignedAddress(Info, *this);
+}
+
+Address Address::getResignedAddress(const CGPointerAuthInfo &NewInfo,
+ CodeGenFunction &CGF) const {
+ assert(isValid() && "pointer isn't valid");
+ CGPointerAuthInfo CurInfo = getPointerAuthInfo();
+ llvm::Value *Val;
+
+ // Nothing to do if neither the current or the new ptrauth info needs signing.
+ if (!CurInfo.isSigned() && !NewInfo.isSigned())
+ return Address(getBasePointer(), getElementType(), getAlignment(),
+ isKnownNonNull());
+
+ assert(ElementType && "Effective type has to be set");
+
+ // If the current and the new ptrauth infos are the same and the offset is
+ // null, just cast the base pointer to the effective type.
+ if (CurInfo == NewInfo && !hasOffset())
+ Val = getBasePointer();
+ else {
+ assert(!Offset && "unexpected non-null offset");
+ Val = CGF.EmitPointerAuthResign(getBasePointer(), QualType(), CurInfo,
+ NewInfo, isKnownNonNull());
+ }
+
+ Val = CGF.Builder.CreateBitCast(Val, getType());
+ return Address(Val, getElementType(), getAlignment(), NewInfo, nullptr,
+ isKnownNonNull());
+}
+
+llvm::Value *LValue::getPointer(CodeGenFunction &CGF) const {
+ assert(isSimple());
+ return emitResignedPointer(getType(), CGF);
+}
+
+llvm::Value *LValue::emitResignedPointer(QualType PointeeTy,
+ CodeGenFunction &CGF) const {
+ assert(isSimple());
+ return CGF.getAsNaturalAddressOf(Addr, PointeeTy).getBasePointer();
+}
+
+llvm::Value *LValue::emitRawPointer(CodeGenFunction &CGF) const {
+ assert(isSimple());
+ return Addr.isValid() ? Addr.emitRawPointer(CGF) : nullptr;
+}
diff --git a/clang/lib/CodeGen/CGValue.h b/clang/lib/CodeGen/CGValue.h
index f1ba3cf95ae59..c4ec8d207d2e3 100644
--- a/clang/lib/CodeGen/CGValue.h
+++ b/clang/lib/CodeGen/CGValue.h
@@ -15,6 +15,7 @@
#define LLVM_CLANG_LIB_CODEGEN_CGVALUE_H
#include "Address.h"
+#include "CGPointerAuthInfo.h"
#include "CodeGenTBAA.h"
#include "EHScopeStack.h"
#include "clang/AST/ASTContext.h"
@@ -233,9 +234,6 @@ class LValue {
// this lvalue.
bool Nontemporal : 1;
- // The pointer is known not to be null.
- bool IsKnownNonNull : 1;
-
LValueBaseInfo BaseInfo;
TBAAAccessInfo TBAAInfo;
@@ -263,7 +261,6 @@ class LValue {
this->ImpreciseLifetime = false;
this->Nontemporal = false;
this->ThreadLocalRef = false;
- this->IsKnownNonNull = false;
this->BaseIvarExp = nullptr;
}
@@ -349,28 +346,26 @@ class LValue {
LValueBaseInfo getBaseInfo() const { return BaseInfo; }
void setBaseInfo(LValueBaseInfo Info) { BaseInfo = Info; }
- KnownNonNull_t isKnownNonNull() const {
- return (KnownNonNull_t)IsKnownNonNull;
- }
+ KnownNonNull_t isKnownNonNull() const { return Addr.isKnownNonNull(); }
LValue setKnownNonNull() {
- IsKnownNonNull = true;
+ Addr.setKnownNonNull();
return *this;
}
// simple lvalue
- llvm::Value *getPointer(CodeGenFunction &CGF) const {
- assert(isSimple());
- return Addr.getBasePointer();
- }
- llvm::Value *emitRawPointer(CodeGenFunction &CGF) const {
- assert(isSimple());
- return Addr.isValid() ? Addr.emitRawPointer(CGF) : nullptr;
- }
+ llvm::Value *getPointer(CodeGenFunction &CGF) const;
+ llvm::Value *emitResignedPointer(QualType PointeeTy,
+ CodeGenFunction &CGF) const;
+ llvm::Value *emitRawPointer(CodeGenFunction &CGF) const;
Address getAddress() const { return Addr; }
void setAddress(Address address) { Addr = address; }
+ CGPointerAuthInfo getPointerAuthInfo() const {
+ return Addr.getPointerAuthInfo();
+ }
+
// vector elt lvalue
Address getVectorAddress() const {
assert(isVectorElt());
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 26deeca95d326..fab3091f0581c 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -195,34 +195,45 @@ CodeGenFunction::CGFPOptionsRAII::~CGFPOptionsRAII() {
CGF.Builder.setDefaultConstrainedRounding(OldRounding);
}
-static LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T,
- bool ForPointeeType,
- CodeGenFunction &CGF) {
+static LValue
+MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T, bool ForPointeeType,
+ bool MightBeSigned, CodeGenFunction &CGF,
+ KnownNonNull_t IsKnownNonNull = NotKnownNonNull) {
LValueBaseInfo BaseInfo;
TBAAAccessInfo TBAAInfo;
CharUnits Alignment =
CGF.CGM.getNaturalTypeAlignment(T, &BaseInfo, &TBAAInfo, ForPointeeType);
- Address Addr = Address(V, CGF.ConvertTypeForMem(T), Alignment);
+ Address Addr =
+ MightBeSigned
+ ? CGF.makeNaturalAddressForPointer(V, T, Alignment, false, nullptr,
+ nullptr, IsKnownNonNull)
+ : Address(V, CGF.ConvertTypeForMem(T), Alignment, IsKnownNonNull);
return CGF.MakeAddrLValue(Addr, T, BaseInfo, TBAAInfo);
}
-LValue CodeGenFunction::MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T) {
- return ::MakeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ false, *this);
+LValue
+CodeGenFunction::MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T,
+ KnownNonNull_t IsKnownNonNull) {
+ return ::MakeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ false,
+ /*IsSigned*/ true, *this, IsKnownNonNull);
}
LValue
CodeGenFunction::MakeNaturalAlignPointeeAddrLValue(llvm::Value *V, QualType T) {
- return ::MakeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ true, *this);
+ return ::MakeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ true,
+ /*IsSigned*/ true, *this);
}
LValue CodeGenFunction::MakeNaturalAlignRawAddrLValue(...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/98847
More information about the cfe-commits
mailing list