Look through calls to std::addressof to compute pointer alignment.

This is sort of a followup to D37310; that basically fixed the same
issue, but then the libstdc++ implementation of <atomic> changed. Re-fix
the the issue in essentially the same way: look through the addressof
operation to find the alignment of the underlying object.

Differential Revision: https://reviews.llvm.org/D123950
This commit is contained in:
Eli Friedman 2022-04-18 10:19:57 -07:00
parent 61e36e87df
commit ecc8479a01
2 changed files with 37 additions and 1 deletions

View File

@ -1170,6 +1170,22 @@ Address CodeGenFunction::EmitPointerWithAlignment(const Expr *E,
}
}
// std::addressof and variants.
if (auto *Call = dyn_cast<CallExpr>(E)) {
switch (Call->getBuiltinCallee()) {
default:
break;
case Builtin::BIaddressof:
case Builtin::BI__addressof:
case Builtin::BI__builtin_addressof: {
LValue LV = EmitLValue(Call->getArg(0));
if (BaseInfo) *BaseInfo = LV.getBaseInfo();
if (TBAAInfo) *TBAAInfo = LV.getTBAAInfo();
return LV.getAddress(*this);
}
}
}
// TODO: conditional operators, comma.
// Otherwise, use the alignment of the type.

View File

@ -1,4 +1,4 @@
// RUN: %clang_cc1 %s -std=c++11 -emit-llvm -o - -triple=x86_64-linux-gnu | FileCheck %s
// RUN: %clang_cc1 %s -std=c++14 -emit-llvm -o - -triple=x86_64-linux-gnu | FileCheck %s
struct AM {
int f1, f2;
@ -28,3 +28,23 @@ AM load2() {
__atomic_load(&bm.f2, &am, 0);
return am;
}
namespace std {
template <class _Tp>
inline constexpr
__attribute__ ((__visibility__("hidden"), __internal_linkage__))
_Tp* __addressof(_Tp& __x) noexcept
{
return __builtin_addressof(__x);
}
}
AM load3() {
AM am;
// m is declared to align to 8bytes, so generate load atomic instead
// of libcall.
// CHECK-LABEL: @_Z5load3v
// CHECK: load atomic {{.*}} monotonic, align 8
__atomic_load(std::__addressof(m), &am, 0);
return am;
}